【问题标题】:Comparing Char Pointers比较字符指针
【发布时间】:2014-05-29 14:07:06
【问题描述】:

我正在尝试比较两个字符指针:

   char * x;
   char * y;

   x = "Hesham";
   y = "Hesham";

   printf("%d %d \n", &x, &y);

   if(x==y)
   {
     printf("=\n");
   }
   else
   {
     printf("!=\n");
   }

执行结果是:

2293368 2293360
=

1 - 为什么两个指针的地址不同,== 操作返回 true ?

2 - 为什么编译器不将字符串文字 Hesham 只存储一次,并将其地址两次用于 xy

【问题讨论】:

  • 您的意思是使用strncmp()
  • 不,我不是这个意思。
  • 将 printf 更改为 printf("%d %d \n", x, y);,它们应该相等。此外,您应该使用%p 来打印指针。
  • 约翰尼说了什么。这不是重复的。另一个问题是关于字符串的,这个问题是关于恰好是 char 指针的指针。编辑:我应该早点刷新。
  • printf("%d %d \n", &x, &y)printf("%d %d \n", x, y) 都调用未定义的行为,因为它们传递的参数类型错误,格式为 %d,它需要一个类型为 int 的参数。你应该使用printf("%p %p", (void*)x, (void*)y)

标签: c++ c pointers char equality


【解决方案1】:

为什么两个指针地址不同,而==的操作返回true?

&x&y 是指针变量的地址,而不是字符串的地址。由于xy 是不同的变量,所以它们的地址也不同。

然后您比较 xy 的值,这恰好是相同的,因为编译器注意到这两个字符串文字具有相同的值并且只存储了该文字的一个副本。

为什么编译器不将字符串文字 "Hesham" 只存储一次,并将其地址两次用于 xy

确实如此。这就是 x == y 评估为 true 的原因。


另外一点是在打印指针时应该使用%p 格式说明符。

【讨论】:

  • 对不起,我应该打印:printf("%d %d \n", x, y); 不是&x&y。查看他们指向的数据。谢谢:)
  • 更正之前的评论:查看他们指向的地址
  • 使用%p 的建议不应该只是旁白。传递指向%d 的指针是未定义的行为。
  • @JamesKanze 谢谢。我想我把这个词放在一边是因为那个问题不是问题的主旨。我已经编辑删除了那个词。
【解决方案2】:

编译器是将相等的字符串文字存储为单独的文字还是作为一个文字/通常默认情况下,编译器将相等的字符串文字存储为一个字符串文字以最小化内存使用量,这取决于编译器选项。

在这些陈述中

   x = "Hesham";
   y = "Hesham";

您将字符串文字的第一个字符的相同地址分配给变量 x 和 y。由于编译器将这两个字符串文字存储为一个字符串文字,因此很明显 x == y 即 x 和 y 被分配了相同的值。

但是,如果您设置编译器选项以强制编译器将相等的字符串文字存储为单独的文字,那么表达式x == y 的结果将等于false。 如果你想比较你必须写的字符串文字

if ( strcmp( x, y ) == 0 ) { /*...*/ }

【讨论】:

  • 对不起,我应该打印:printf("%d %d \n", x, y); 不是&x&y。查看他们指向的地址。你知道 ARM 的编译器选项吗?找了好久都没找到。
【解决方案3】:

根据 Bjarne Stroustrup 的 The C++ Programming Language,他说

将两个相同的字符串文字分配为一个数组还是两个 实现定义。

鉴于 C++ 基于 C99,我认为它也适用于 C。在您的情况下,仅分配其中一个并使用两次,这意味着 xy 指向相同的字符串。

【讨论】:

  • 在C99标准中,"foo" == "foo"是否是未指定的,比“实现定义”弱很多。我对您找到的报价感到非常惊讶,无论如何,它可能不应该被视为规范。
  • 我有一个 2005 年的 C++ 标准草案,它确实说“是否所有字符串文字都是不同的(即存储在不重叠的对象中)是实现定义的”(2.13. 4:2)。相应的 C99 提及是“字符串字面量和具有 const 限定类型的复合字面量,不需要指定不同的对象。”这并不强制实现记录其行为或使其保持一致。 (C99 6.5.2.5:8)
  • @PascalCuoq 我不认为它必须被视为未指定,而是用于确切的情况正如 Bjarne Stroustrup 所描述的,由于根本原因,行为是不可预测的。显然,除非采用了某种同步机制,否则从两个线程分配给变量的值是不可预测的。但是,似乎每个实现都可以轻松处理两个相同的字符串文字是否具有相同的地址。
  • 如果 C99 标准化委员会希望 C99 程序员将字符串文字标识视为实现定义的,则不会在“J.1 未指定行为”部分列出“两个字符串文字是否导致不同的数组” .你还需要什么?该部分的标题是“未指定的行为”,其下的项目是“两个字符串文字是否导致不同的数组”。
  • @PascalCuoq 误解这里。我不是在谈论 C99,而是在谈论您所说的无论如何,它可能不应该被视为规范。我以为你想说它应该在 C++ 中未指定,就像在 C99 中一样。