为什么我不能在头文件中定义普通的C函数?

Amo*_*kar 11 objective-c

当我尝试在类接口上方的头文件中定义C函数时,我总是遇到构建错误.

但是当我在实现文件中执行相同操作并在标头中给出声明时.事情很成功.

我想知道,为什么它是这样因为我在头文件中定义了枚举,结构,常量NSStrings,那么为什么不用C函数呢?

小智 18

这与C链接器(或链接编辑器)的工作方式有关.当C编译器遇到函数定义时,它会准备实现该函数的汇编程序代码,并使用符号表示链接器"这是具有此名称的函数开始的位置".符号通常以下划线后跟函数名称命名,例如_printf.

如果在头文件中定义函数,则导入此头的每个.c或每个.m文件都将编译该函数,并使编译器发出相同的符号.链接器期望只找到每个符号的一个实例,因此这是一个错误.

这与#include守卫的存在无关,或与使用#import而不是#include.C编译器适用于各个翻译单元 - 它意味着单个源文件.预处理器策略会阻止您将相同的头文件两次包含在单个源文件中,但不会在多个文件之间协调活动.这意味着在不同的源文件中包含相同的头文件是有效的:它还意味着当您编译不同的文件时,它们可以(合法地)包含相同的符号.

链接编辑器的工作是将这些文件放在一起,解决对编译时未知的符号的任何引用.如果您尝试将具有相同符号的对象(已编译和已组装的翻译单元的名称)链接到同一存档,共享库或可执行文件中,那么您将收到您在此处看到的错误.

解决方案:

  • 不要在头文件中定义函数,只需在那里声明它并在实现文件中定义它; 因为你已经发现这个有效.
  • 在标题中定义函数,但只在代码中的一个位置包含该标题.出于设计原因,这通常是不可接受的.
  • 使用修饰符在标题中定义函数inline.内联函数只是由编译器复制到它们被调用的函数中,因此永远不会为它们发出链接器符号.这有其自身的权衡,您可能希望阅读更多.

  • @Graham Lee ahhhhhhh ......好吧..现在我明白了.是的......你当然是对的!你不能多次定义同一个功能!我说要宣布一次,然后再包括一次. (2认同)