什么时候可以用char *相等比较C字符串?

时间:2018-06-26 02:23:24

标签: c string-literals

我知道通过比较两个const char *对任意两个c字符串((a == b))没有意义。

但是我认为当两者都由SAME字符串文字定义时,这是合法的。

例如,在这里:

#include <stddef.h>

const char * const meals[] = {
    "none",
    "breakfast",
    "lunch",
    "dinner"
};

#define NO_MEALS  meals[0]
#define BREAKFAST meals[1]
#define LUNCH     meals[2]
#define DINNER    meals[3]

// i hours after midnight, hour_to_meals_map[floor(i)] is being served.
const char * hour_to_meal_map[] = {
    NO_MEALS,
    NO_MEALS,
    NO_MEALS,
    NO_MEALS,
    NO_MEALS,
    BREAKFAST, // i = 5
    BREAKFAST,
    BREAKFAST,
    BREAKFAST,
    BREAKFAST,
    BREAKFAST,
    LUNCH, // i = 11
    LUNCH,
    LUNCH,
    LUNCH,
    LUNCH,
    LUNCH,
    DINNER, // i = 17
    DINNER,
    DINNER,
    DINNER,
    DINNER,
    DINNER,
    DINNER // i = 23
};

// Returns a boolean for whether the two hours have the same meal being eaten.
int same_meal(size_t hour_one, size_t hour_two) {
    return hour_to_meal_map[hour_one] == hour_to_meal_map[hour_two];
}

(关于为什么您会hour_to_meal_map映射到字符串而不是索引的问题,这是任何人的猜测。.但是我正在一个以这种方式设置的项目中。)

我是否正确,在这里,这是合法的,重要的是,只有一个地方可以将每个值写为文字? (故意避免使用#define NO_MEALS "none"!)

如果此代码位于头文件中,那没有什么不同,是吗? (我希望标准要求meals在每个编译单元中具有相同的值?)。

我从初学者那里发现了很多问题,询问他们很明显应该使用strcmp的情况,但是我找不到能回答这种特殊情况的情况。任何帮助将不胜感激,特别是如果您可以将我指向C标准的正确部分,以便使我可以真的确保我理解所有的微妙之处。

2 个答案:

答案 0 :(得分:3)

将两个相同类型的字符串与==!=进行比较始终是合法的。 C standard的6.5.9节对此进行了详细说明,其中详细介绍了平等运算符:

  

2 满足以下条件之一:

     
      
  • 两个操作数都具有算术类型;
  •   
  • 两个操作数都是指向兼容类型的合格或不合格版本的指针;
  •   
  • 一个操作数是一个对象类型的指针,另一个是void的合格或不合格版本的指针;或者
  •   
  • 一个操作数是一个指针,另一个是空指针常量。
  •   
     

...

     

4 两个指针比较相等,当且仅当两个都是空指针时,两者都是指向同一对象的指针(包括指向对象的指针)   以及子对象的开头)或函数,它们都是指向   一个数组对象的最后一个元素之后,或者一个是   指向一个数组对象末尾的指针,另一个是   指向发生的另一个数组对象的开始的指针   立即跟随地址空间中的第一个数组对象

在这种情况下,您有一个指针数组,并将这些指针之一的值分配给另一个数组。因此,如果您比较两个指针,并且它们都包含(例如)meals[0]的值,例如字符串常量“ none”的地址,可以保证它们比较相等。

您需要注意的是,是否在多个位置使用了给定的字符串常量。在这种情况下,它们不一定相同。

例如,鉴于此:

const char *s1 = "test";
const char *s2 = "test";

s1s2的值不能保证相同,因为两个字符串常量可以彼此不同,尽管编译器可以选择使它们相同。这不同于:

const char *s1 = "test";
const char *s2 = s1;

s1s2 相同的地方,这反映了您的情况。

正如您所提到的,hour_to_meal_map包含数字常量(最好是enum的成员),然后将这些常量映射到字符串数组会更有意义。但是实际上,指向字符串常量的指针就是这样。

答案 1 :(得分:0)

我想到了char *相等有意义的几种情况:

  1. 您给出的案例:通过从同一指针复制
  2. 对于大多数(所有?)编译器:在同一转换单元中具有任何相同值的字符串文字。这是一个非常常见的优化,并且无论如何都可以轻松进行测试。
  3. 如果您通过intern()函数显式传递字符串
  4. 作为快速短路比较,然后进行昂贵的值检查