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

时间:2013-11-01 04:34:30

标签: c++ c pointers memory-management char-pointer

代码:

    #include <stdio.h>
    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"它应该用'a'覆盖'H'而其余'ello\0'进入后续的字节。

    我认为整个问题是str = "Hello"声明。它似乎没有像我想的那样工作。

  3. 请有人解释它是如何运作的?

7 个答案:

答案 0 :(得分:7)

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

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

声明str = &i;str的地址写入变量i

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

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

答案 1 :(得分:2)

编译器在可执行文件的一部分data segment中写入字节序列{'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”实例。

答案 2 :(得分:1)

  

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

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

str = "Hello";

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

  

因为,我说str =&amp; i; shoudl not str and&amp; i当我有同样的价值   printf他们?

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

答案 3 :(得分:0)

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

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

答案 4 :(得分:0)

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

    < / LI>
  2. 但是在您说str = something else

  3. 后立即说str = &i

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

答案 5 :(得分:0)

好的,简单地说,每个字符串都是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时,您正在str 指向i。因此,i == *str&i == str成立。

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

答案 6 :(得分:0)

  

首先,如何在不为其分配任何内存的情况下存储字符串。 str是一个chracter指针,指向char i的存储位置。当我说str =&#34;你好&#34;我没有使用该位置的5个字节,其中4个未分配?

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

  

因为,我说str =&amp; i; shoudln&amp; t str和&amp; i在我打印时有相同的价值?当我删除str =&#34; Hello&#34;声明str和&amp; i是一样的。如果str和&amp; i相同,那么我相信当我说str =&#34;你好&#34;它应该覆盖&#39; a&#39;用&#39; H&#39;其余的ello \ 0&#39;进入后续的字节。

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