这会产生gcc警告吗?

时间:2013-06-26 00:45:42

标签: c arrays string pointers compiler-warnings

K& R C(第二版,第5.5节)陈述以下内容(我强调):

char amessage[] = "a message"; /* an array */
char *pmessage = amessage; /* a pointer */
  

amessage 是一个足以容纳字符序列的数组,以及用于初始化字符的'\ 0'。阵列中的单个字符可能会更改,但 amessage 将始终引用相同的存储空间。 OTOH, pmessage 是一个指针,初始化为指向一个字符串常量;随后可以修改指针以指向别处;但如果您尝试修改字符串内容,则结果为未定义

现在,我的问题是我的Linux机器上的gcc 4.6.1(或c99)是否应该在使用-Wall编译以下程序时生成警告:

int main(void) {
  char amessage[] = "a message";
  char *pmessage = "a message";
  pmessage[0] = 'b';
  return 0;
}

(我发现gcc没有产生任何警告。如果我正确解释上述情况,我的期望是它应该。)

4 个答案:

答案 0 :(得分:5)

虽然你对K& R的引用是正确的,但我不希望这段代码产生警告,因为这样的错误在一般情况下很难跟踪。

例如,考虑一段代码,其中指针最初指向可修改内存块,然后稍微操作它,然后将其指定为字符串文字:

char [] ok = "quick brown fox";
char *ptr = ok;
for (int i = 0 ; i != 5 ; i++) {
    *ptr++ = '-'; // OK
}
ptr = "jumps over the lazy dog";
ptr[0] = 'J'; // Bad

对于编译器,跟踪这些分配并发出警告将非常棘手。覆盖所有情况是不可能的,因为指向字符串文字的指针可能来自外部链接的函数。

答案 1 :(得分:2)

仅仅因为代码错误并不意味着gcc可以为它生成警告。如果在编译时可以检测到所有未定义行为的实例,则没有理由将该行为保留为未定义。它可能只是一个强制性错误,或者编译为等效的abort();或类似的。

我同意gcc在这种情况下生成警告很容易。但是怎么样:

int main(void) {
  char amessage[] = "a message";
  char *pmessage = "a message";
  if (is_prime(some_constant_with_100_million_digits))
      pmessage = amessage;
  pmessage[0] = 'b';
  return 0;
}

是否会调用UB?

答案 2 :(得分:0)

它可能没有警告,因为它未定义。

同样我可以这样做:

char amessage[] = "a message";
char *pmessage = amessage;
free(pmessage);

它没有警告,但应该是段错误。

我认为警告是针对既定行为的。

答案 3 :(得分:0)

嗯,预计不会说任何东西,因为pmessage不是指向const的指针,我想在这种情况下它并没有因为它没有做足够的静态分析而烦恼可能会尝试-O切换以查看是否会带来更多洞察力,或者因为没有人在这种情况下让它说出任何内容 - 这通常意味着没有机会根据未定义的行为进行不直观的优化。

GCC支持-Wwrite-strings,这会在初始化时引发问题,迫使你pmessage指向const的指针,随后使以下行成为非法。