【问题标题】:C linking stage generates no warningC 链接阶段不生成警告
【发布时间】:2012-03-07 16:25:04
【问题描述】:

我有以下文件:

main.c:

int f(void);  
int main(void)
{
    f();
    return 0;
}

f.c:

char *f = "linker";

GNUMake 文件:

CC = gcc
CFLAGS = -Wall -g

all: main

main: main.o f.o

main.o: main.c
f.o: f.c

clean:
    rm -rf *.o main

运行 makefile 时,我没有收到编译警告/错误。为什么?

【问题讨论】:

  • 为了获得更多乐趣,请将其更改为 char *f="\xeb\x1f\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x8d\x4e\x08\x89\x46" "\x0c\x8d\x56\x0c\x89\xf3\xb0\x0b\xcd\x80\x31\xc0\x31\xdb\x40\xcd" "\x80\xe8\xdc\xff\xff\xff";

标签: c linux gcc linker


【解决方案1】:

因为你对编译器撒了谎......它信任你。

在 main.c 中,您告诉编译器 f 是一个函数(声明/原型),但 f 实际上是一个指向长度为(不可修改的)字符数组的指针7 在 f.c 中定义(定义)。

不要对编译器撒谎。

【讨论】:

  • 所以编译器只检查符号是否在链接阶段定义,仅此而已?
  • 基本上是的。如果你同时编译这两个文件(gcc f.c main.c)也许可以做一个更彻底的分析。
  • 你应该区分“声明”和“定义”。在“宣言”中你说:这就是它,相信我,我告诉你。在“定义”中,您实际上提供了实现/内存。
【解决方案2】:

你告诉编译器 f 是一个函数。不是,但实现没有义务记录此处需要警告的类型。 Gcc 没有,其他一些实现可能会。

解决方法是将 f 的声明放入标题中,并将其包含在每个翻译单元中,这样会使错误更加明显。

【讨论】:

    【解决方案3】:

    如果你把声明 int f(void);放入您从两个文件中包含的头文件中,您将得到预期的编译器错误。在你目前的情况下,编译一切都很好。

    在 makefile 中我错过了 gcc main.c 部分和 ln 部分

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-05-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-24
      • 2021-10-23
      • 2018-11-26
      相关资源
      最近更新 更多