如果您能帮助我理解下一个代码中究竟发生了什么,我将不胜感激?(写“a”而不是“a”等......)。我的意思是什么将存储在内存中,为什么程序不会崩溃。
char str[10] ;
str[0] = "a";
str[1] = "b";
str[2] = "\0";
谢谢。
C 允许它,但它并没有按照您的期望做。对于第一个(str[0]
和"a"
),编译器所做的是将编译器创建的字符数组转换"a"
为指针,然后将其转换为指针char
。
所以存储的是字符串字面量数组地址str[0]
的最后一个字节。"a"
'a' 是具有 ASCII 值 97 的单个字符(类型char
)。“a”是 C 风格的字符串,一个char
包含两个元素“a”和“\0”的数组。
如果您编译上面的代码,您将收到三个针对三个分配的警告。在 GCC 上,这些警告是这样说的:
main.c:6:12: warning: assignment makes integer from pointer without a cast [enabled by default]
让我们在您的代码中进行第一个分配:
str[0] = "a";
右侧操作数“a”是 a char *
。左边的操作数是 a char
,它是一个整数类型。正如警告提示的那样,它获取指针的值,将其转换为整数,然后将其截断为 的大小char
并将截断的值存储在str[0]
. 因此,赋值后str[0]
不会像您期望的那样包含值“a”(ASCII 97),而是如上所述获得的一些值。
到目前为止一切顺利,程序没有崩溃的原因,只需注意str
不会包含任何有意义的字符串。
现在,如果您尝试使用该字符串做一些有用的事情,例如打印它:
printf("%s", str);
您找到了可能导致程序崩溃(或导致许多其他问题,例如内存损坏)的原因。问题是最后一个赋值 ,str[2] = "\0"
没有像您预期的那样正确终止字符串。因此,您最终会得到一个未正确以 NULL 结尾的 C 样式字符串。这是一条通向灾难的可靠而短暂的道路。
要测试此行为,请尝试显示在str
这些分配之后存储的实际值:
printf("%d - %d - %d", str[0], str[1], str[2]);
您很可能会发现与预期不同的值(97、98、0)。
Simplistic terms... Take this for an example, -Image an array as a Rack with lots of shelves. -String are basically like an array of chars. -Chars are like knick-knacks. 'a' is a char and "a" is a string. Reworded: 'a' is a knick-knack and "a" is a rack with a knick-knack 'a' in it. Str[10] is a rack with 10 shelves. Now doing this, Str[0] = "a"; is like shoving a rack with a knick-knack 'a' in it, on to the first shelf of another rack...
So it's like shoving a whole rack into another rack, and then expect it to have it fit...
Even if this answer has no logic at all, its just to show that, str[0] = "a"; makes absolutely no sense either. You might as well just do str[0] = 97; to just completely forget about quotes.. :P