在C中,我可以在指针声明中初始化字符串,就像我可以在char数组声明中初始化字符串一样吗?
这两行代码是否实现了相同的结果? 如果我在函数中有这些行,那么在两种情况下字符串都存储在堆栈中吗? 除了不需要在第一行代码中声明空终止符之外,我是否应该使用一个而不是另一个?
char s[] = "string"; char* s = "string\0";
不,这两行没有达到相同的效果。
char s[] = "string"
产生一个7个字节的可修改数组,最初填充内容's' 't' 'r' 'i' 'n' 'g' '\0'
(全部复制过来)在运行时从字符串文字)。
char *s = "string"
导致指向包含string-literal“string”的只读内存的指针。
如果你想修改你的字符串的内容,那么第一个是唯一的方法。 如果您只需要对字符串的只读访问权限,那么第二个将稍微更快,因为不必复制字符串。
在这两种情况下,都不需要在字符串文字中指定空终止符。 当遇到结束时,编译器将为您处理“。
这两者之间的区别:
char a[] = "string"; char* b = "string";
是一个实际上是堆栈上的静态数组,而b是一个指向常量的指针。 您可以修改a的内容,但不能修改b的内容。
除了其他答案,我将尝试解释为什么你不能在程序流程后修改*s
变量。
从概念上讲,当程序加载到内存中时,它有3个区域(段):
- 代码段:程序的文本存储在这里(它是一个只读区域)
- 数据段:包含具有预定义值且可以修改的任何全局或静态变量
- stack segment:这里加载了调用它们的函数。 每个函数调用在堆栈上推送的值集(堆栈帧),其中包含函数和局部变量的返回地址。
在您的情况下, s[]
变量是main()
函数中的局部变量(数组),它使用值"string"
初始化。 因此,它存储在堆栈中并且可以被修改。
*s
变量是一个指向"string\0"
地址的指针,这是一个位于代码段中的常量。 作为只读区域,您无法修改其内容。