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

时间:2013-09-30 06:56:08

标签: c pointers literals

#include<stdio.h>
#include<string.h>

int main()
{
    char * p = "abc";
    char * p1 = "abc";
    printf("%d %d", p, p1);
}

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

10 个答案:

答案 0 :(得分:86)

具有相同内容的两个不同字符串文字是否放置在相同的内存位置或不同的内存位置是依赖于实现的。

您应始终将pp1视为两个不同的指针(即使它们具有相同的内容),因为它们可能指向同一地址,也可能不指向同一地址。您不应该依赖编译器优化。

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

  

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


打印格式必须为%p

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

请参阅this answer了解原因。

答案 1 :(得分:28)

您的编译器似乎非常聪明,检测到两个文字是相同的。由于文字是不变的,编译器决定不再存储它们两次。

似乎值得一提的是,这不一定是必须的。请参阅Blue Moonanswer on this


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

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

因为"%p"将用于打印指针值,并且仅为类型void *的指针定义。 * 1


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


* 1:对于void *指针,不需要转换为char *,而是指向所有其他类型的指针。

答案 2 :(得分:18)

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

技术上:它应该抱怨你没有指出“const”

const char* p = "abc";

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

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

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

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

警告:字符串池是一种编译器/优化器功能,而不是该语言的一个方面。因此,不同环境下的不同编译器会根据优化级别,编译器标志以及字符串是否位于不同的编译单元中而产生不同的行为。

答案 3 :(得分:14)

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

编译以下内容时
#include<stdio.h>
#include<string.h>

int main()
{
  char * p = "abcdef";
  char * p1 = "def";
  printf("%d %d", p, p1);
}

它为我打印4195780 4195783。也就是说,p1p之后的3个字节开始,因此GCC看到了def的公共后缀(包括\0终结符),并对您进行了类似的优化已经表明了。

(这是一个答案,因为评论太久了。)

答案 4 :(得分:3)

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

答案 5 :(得分:2)

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

前段时间我已经学会了这个,所以我可能没有说清楚,很抱歉。

答案 6 :(得分:2)

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

在我的 TC ++ 3.5 系统中,它为两个指针打印两个不同的值,即两个不同的地址

您的编译器设计为检查内存中是否存在任何值并根据其存在它将重新分配使用相同的引用< / strong>如果引用相同的值,则先前存储的值。

所以不要过多考虑,因为取决于编译器解析代码的方式。

这一切......

答案 7 :(得分:1)

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

答案 8 :(得分:1)

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

答案 9 :(得分:0)

你使用的是字符串文字,

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

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