代码之家  ›  专栏  ›  技术社区  ›  seereddi sekhar

指向不同字符串文字的两个字符指针的地址相同

  •  81
  • seereddi sekhar  · 技术社区  · 11 年前
    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
        char * p = "abc";
        char * p1 = "abc";
        printf("%d %d", p, p1);
    }
    

    当我打印两个指针的值时,它打印的是相同的地址。为什么?

    10 回复  |  直到 6 年前
        1
  •  89
  •   Community miroxlav    7 年前

    将具有相同内容的两个不同字符串文字放在同一内存位置还是不同内存位置取决于实现。

    你应该经常治疗 p p1 作为两个不同的指针(即使它们具有相同的内容),因为它们可能指向或可能不指向相同的地址。您不应该依赖编译器优化。

    C11标准,6.4.5,字符串文字,语义

    未指定这些数组是否是不同的,前提是它们 元素具有适当的值。如果程序试图 修改这样的数组,行为是未定义的。


    打印格式必须为 %p :

      printf("%p %p", (void*)p, (void*)p1);
    

    看见 this answer 原因。

        2
  •  28
  •   Community miroxlav    7 年前

    您的编译器似乎很聪明,可以检测到两个文本是相同的。由于文字是常量,编译器决定不存储两次。

    值得一提的是,情况并非一定如此。请参阅 Blue Moon answer on this .


    顺便说一句: printf() 语句应该是这样的

    printf("%p %p", (void *) p, (void *) p1);
    

    "%p" 应用于打印指针值,并且它是为类型的指针定义的 void * 只有 *1


    此外,我想说代码错过了 return 语句,但C标准似乎正在被更改。其他人可能会澄清这一点。


    *1:铸造到 无效* 这里没有必要 char * 指针,但用于指向所有其他类型的指针。

        3
  •  18
  •   kfsone    11 年前

    您的编译器已经完成了一项名为“字符串池”的操作。您指定需要两个指针,两个指针都指向同一个字符串文字,所以它只复制了文字的一个副本。

    从技术上讲:它应该抱怨你没有把指针变成“const”

    const char* p = "abc";
    

    这可能是因为您使用的是Visual Studio,或者使用的是不带-Wall的GCC。

    如果您明确希望它们在内存中存储两次,请尝试:

    char s1[] = "abc";
    char s2[] = "abc";
    

    在这里,您明确表示需要两个c字符串字符数组,而不是两个指向字符的指针。

    注意:字符串池是编译器/优化器的一个特性,而不是语言的一个方面。因此,不同环境下的不同编译器将产生不同的行为,这取决于优化级别、编译器标志以及字符串是否位于不同的编译单元中。

        4
  •  15
  •   huon John U    11 年前

    正如其他人所说,编译器注意到它们具有相同的值,因此决定让它们在最终可执行文件中共享数据。但它变得更花哨了:当我用 gcc -O

    #include<stdio.h>
    #include<string.h>
    
    int main()
    {
      char * p = "abcdef";
      char * p1 = "def";
      printf("%d %d", p, p1);
    }
    

    它打印 4195780 4195783 对我来说。也就是说, p1 在之后3个字节开始 p ,所以GCC看到了的常见后缀 def (包括 \0 terminator),并进行了与您所展示的类似的优化。

    (这是一个答案,因为太长了,无法发表评论。)

        5
  •  3
  •   Salgar    11 年前

    代码中的字符串文字存储在代码的只读数据段中。当你写下像“abc”这样的字符串文字时,它实际上会返回一个“const char*”,如果你有所有的编译器警告,它会告诉你此时正在进行强制转换。你不能因为你在这个问题中指出的原因而更改这些字符串。

        6
  •  2
  •   Lord Zsolt    11 年前

    当你创建一个字符串文字(“abc”)时,它会被保存到一个内存中,内存中包含字符串文字,然后如果你引用相同的字符串文字,它就会被重用,因此两个指针都指向存储“abc”字符串文字的同一位置。

    我很早以前就知道了,所以我可能没有解释清楚,对不起。

        7
  •  2
  •   Rajesh Paul    11 年前

    事实上 取决于您使用的编译器 .

    在我的系统中 总胆固醇++3.5 它打印 两个指针的两个不同值,即两个不同的地址 .

    你的编译器是经过设计的。它会 检查内存中是否存在任何值 并且取决于它的存在 它将重新分配 使用相同的引用 如果引用了相同的值,则为先前存储的值的值。

    所以不要想太多 取决于编译器解析的方式 代码。

    这就是全部。。。

        8
  •  1
  •   SANDEEP    11 年前

    因为字符串“abc”本身就是内存中的一个地址。当你再次写“abc”时,它会存储相同的地址

        9
  •  1
  •   Amir Saniyan    11 年前

    这是编译器优化,但忽略了可移植性的优化。有时编译后的代码比实际代码更具可读性。

        10
  •  0
  •   Dev    11 年前

    您使用的是字符串文字,

    当编译器捕获两个相同的字符串文字时,

    它给出相同的存储器位置, 因此它显示相同的指针位置/