【问题标题】:risk of compile warning编译警告的风险
【发布时间】:2014-10-29 07:42:54
【问题描述】:

我主要有两种编译警告:

1.函数的隐式声明

a.c,它有char *foo(char *ptr1, char *ptr2),在b.c,一些函数使用这个foo函数没有任何声明,我发现编译器似乎会将函数foo的返回值视为整数,甚至我可以传递一些少于或多于foo函数声明的变量

2。枚举类型与其他类型混合

我的目标芯片是ARM11,看来即使我没有解决这两种编译警告,我的程序也可以运行没有任何问题,但我相信这背后一定有一些风险。谁能给我一个很好的例子说明这两种编译警告会导致一些意想不到的问题吗?

同时,如果这两个警告有潜在的风险,为什么c编译器允许这些警告发生而不直接将它们设置为错误?有什么故事吗?

【问题讨论】:

  • 不要将警告视为风险,而应将其视为有用的帮助。始终启用所有这些 (gcc -Wall -Wextra),并始终改进您的代码以避免它们。有时你会得到误报。而且它们中的大多数都不是错误,因为 C99 标准要求这样做。当心undefined behavior
  • 现在可能不是问题,但将来可能。几周后,您想更改代码中的某些内容。如果您解决了所有警告,编译器会告诉您您的新修改可能会以某种方式损坏或错误。想象一下,你例如在新版本中为 foo 函数添加参数。使用头文件中声明的函数,编译器会告诉你,你必须在所有地方更正它,但没有它,它会编译但不能正常工作。

标签: gcc armcc


【解决方案1】:

隐式声明。例如。你有函数:float foo(float a),当你调用它时没有声明它。隐式规则将创建具有以下签名的自动声明:int foo(double)(如果传递的参数是浮点数)。所以你传递的值将被转换为双倍,但foo 期望float。与返回相同 - 调用代码需要 int,但返回 float。价值观会一团糟。

枚举与其他类型混合。枚举类型具有它可以采用的值列表。如果您尝试为其分配数值,则它可能不是列出的值之一;如果稍后您的代码只需要指定的范围并且假定没有其他内容可能存在 - 它可能行为不端。

【讨论】:

  • 好的,我可以知道为什么c编译器默认允许Implicit declaration吗?这背后有什么故事吗?
  • 因为历史原因。有答案stackoverflow.com/questions/11835001/…
  • 历史原因。 C99+ 禁止隐式声明。 C++ 也是。
【解决方案2】:

简单示例:

文件:warn.c

#include <stdio.h>

double foo(double x)
{
  return myid(x);
}

int
main (void)
{
  double x = 1.0;
  fprintf (stderr, "%lg == %lg\n", x, foo (x));
  return 0;
}

文件:foo.c

double
myid (double x)
{
  return x;
}

编译运行:

$ gcc warn.c foo.c -Wall
warn.c: In function ‘foo’:
warn.c:5: warning: implicit declaration of function ‘myfabs’
$ ./a.out 
1 == 0

旧的 C 标准 (C90) 有这个奇怪的“默认 int”规则,为了兼容性,即使在最新的编译器中也支持它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-11-16
    • 1970-01-01
    • 2022-11-25
    • 2011-05-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多