char * str; STR =“HELLO”; 如果没有为字符串分配任何内存,它如何工作?

码:

#include  int main() { char *str; char i = 'a'; str = &i; str = "Hello"; printf("%s, %c, %x, %x", str, i, str, &i); return 0; } 

我得到这个输出:

 Hello, a, 403064, 28ff0b 

我有两个疑问:

  1. 如何在不为其分配任何内存的情况下存储字符串。 str是一个字符指针,指向char变量i 。 当我添加str = "Hello"; 我不是使用该位置的5个字节,其中4未分配?

  2. 因为,我编码str = &i; 当我打印它们时,不应该str&i具有相同的值吗? 当我删除str = "Hello"; 语句str&i是一样的。 如果str&i相同,那么我相信当我说str = "Hello"它应该用'H'覆盖'a' 'H'而其余'ello\0'进入后续字节。

    我相信整个问题是str = "Hello"语句。 它似乎没有像我想的那样工作。

请有人解释它是如何工作的?

当编译器遇到字符串文字时,在本例中为"Hello" ,内存在静态(全局)内存区域中分配。 这个“分配”是在程序执行之前完成的。

当程序在main处开始执行时,会分配一个堆栈帧来存储mainstri的局部变量。 请注意, str是一个只存储地址的简单变量。 它不存储任何字符。 它只存储一个指针。

语句str = &i; 将变量str写入i的地址。

语句str = "Hello"写入变量str即编译器预先分配的字符串文字"Hello"的地址 。 这是一个完全不同于i地址。 该赋值不会移动单词“Hello”中的任何字符。

TL; DR C中“string”变量的值只是一个指针。 分配给字符串变量是指定一个数字,即地址。

编译器在称为数据段的可执行文件的一部分中写入字节序列{‘H’,’E’,’L’,’L’,’O’,’\ 0’}。

当应用程序运行时,它获取这些字节的地址并将它们存储在表示’str’的变量中。

它不必“分配”内存,因为在运行时,程序不必向操作系统请求内存来存储文本。

你应该尽量避免将像这样的字符串文字视为非const。 GCC的“-Wall”选项促进将字符串文字赋值为“char *”指针

 warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings] 

许多编译器在使用优化进行编译时,会执行一些称为“字符串池化”的操作,这样可以避免重复字符串。

 const char* str1 = "hello"; const char* str2 = "hello"; 

如果使用字符串池进行编译,则可执行文件可能只包含一个“hello”实例。

当我说str =“Hello”不是我使用5个字节时,那个位置没有分配4个?

不。编译器在内存的不同部分(只读部分,但这是对不同问题的答案 )留出6个字节(记住空终止符 。 分配:

 str = "Hello"; 

导致str指向这6个字节中第一个的位置,即H

从那以后,我说str =&i; 当我打印它们时,我没有str和&我有相同的价值?

是的,但是在你打印任何东西之前,你将str设置为指向下一行的其他内容。

文字字符串"Hello"在某处占用6个字节的内存,可能在程序空间中。 将指针指定给它只是将指针设置为字符串已存在的位置。 它根本不复制字符。

如果你想复制你需要使用strcpy的字符,但由于你没有将指针设置为足够大小的可写缓冲区,如果你这样做会导致未定义的行为。

  1. str是指向char的指针。 当你说str = &i; 你指向一个int。 当你说str = "Hello"; 你正在改变str指向存储字符序列’H’,’e’,’l’,’l’,’o’,0的位置。

  2. 但是你说str = &i之后你就说str = &i str = something else

看起来你还没有完全掌握指针……

好吧,简单地说,每个字符串都是C中的指针。

如果我们运行:

 int main() { char *str; char i='a'; str = &i; str = "Hello"; printf("%s, %c, %x, %x", str, i, str, &i); return 0; } 

当你设置str = &i ,你正在指向 i 。 因此, i == *str&i == str成立。

当你调用str = "Hello";str现在指向一个大小为6的静态分配数组(这通常直接存在于程序代码中)。 因为str是一个指针,当你将它重置为指向新数组时,它不会改变为i 。 现在,如果不是将str设置为"Hello" ,我们确实*str = 'Z';i现在有’Z’的值,而str仍然指向i

首先,我如何存储字符串而不为其分配任何内存。 str是一个chracter指针,指向char i的存储位置。 当我说str =“Hello”不是我使用5个字节时,那个位置没有分配4个?

字符串的内存由编译器分配。 我不认为该标准确切地指定了编译器必须如何执行此操作。 如果对可执行文件运行“字符串”,则应该在某处找到“Hello”。

从那以后,我说str =&i; 当我打印它们时,我没有str和&我有相同的价值? 当我删除str =“Hello”语句str和&i相同时。 如果str和&i相同,那么我相信当我说str =“Hello”它应该用’H’覆盖’a’而其余’ello \ 0’进入后续字节。

我想你在这里缺少的是str =“Hello”不会将字符串复制到str指向的位置。 它改变了str指向的内容。 “Hello”在内存中,您将该内存位置分配给指针。 如果要将内存复制到指针,则需要使用memcpy()或类似的东西。