为什么我不能在头文件中定义普通的 C 函数? [英] Why can't I define plain C functions in header file?

查看:89
本文介绍了为什么我不能在头文件中定义普通的 C 函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I always get a build error when I try to define a C function in the header file just above the interface of the class.

但是当我在实现文件中做同样的事情并在标题中给出一个声明时.事情解决了.

but when I do the same in the implementation file and give a declaration in the header. Things work out.

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

I wanted to know, why is it so becuase I have defined enums, structs , constant NSStrings in the header-file , so why not C functions ?

推荐答案

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

This is to do with the way that the C linker (or link editor) works. When the C compiler comes across a function definition, it prepares the assembler code that implements that function and marks it with a symbol that says to the linker "this is where the function with this name starts". The symbol is usually named with an underscore followed by the function name, e.g. _printf.

如果在头文件中定义函数,那么每个导入该头文件的 .c.m 文件都会编译该函数,并导致编译器发出相同的符号.链接器期望只找到每个符号的一个实例,所以这是一个错误.

If you define the function in a header file, then every .c or .m file that imports this header will compile the function, and will cause the compiler to emit the same symbol. The linker expects to only find one instance of each symbol, so this is an error.

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

This is unrelated to the existence of #include guards, or to using #import instead of #include. The C compiler works on individual translation units - by which it means individual source files. Preprocessor strategies stop you including the same header file twice into a single source file, but do nothing to coordinate activities across multiple files. That means that it's valid to include the same headers in different source files: it also means that when you compile different files, they can (legitimately) contain the same symbol.

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

It's the job of the link editor to put these files together, resolving any references to symbols that were unknown at compilation time. If you try to link objects (the name of compiled and assembled translation units) that have the same symbol into the same archive, shared library or executable, then you'll get the error you're seeing here.

解决方案:

  • 不要在头文件中定义函数,只需在那里声明并在实现文件中定义它;因为你已经发现这很有效.
  • 在标头中定义函数,但仅在代码中的一处包含该标头.由于设计原因,这通常是不可接受的.
  • 使用修饰符 inline 在标头中定义函数.内联函数只是由编译器复制到调用它们的函数中,因此永远不会为它们发出链接器符号.这有其自身的权衡,您 可能希望阅读更多关于的信息.
  • Don't define the function in the header, just declare it there and define it in an implementation file; as you've already found this works.
  • Define the function in the header, but only include that header in one place in your code. This is often unacceptable for design reasons.
  • Define the function in the header with the modifier inline. Inline functions are just copied by the compiler into the function where they're called, so a linker symbol is never emitted for them. This has its own trade-offs that you may wish to read more about.

这篇关于为什么我不能在头文件中定义普通的 C 函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆