C语言中的函数原型

C语言中的函数原型,c,header,C,Header,今天早些时候,我浏览了各种头文件,只是为了将它们与我正在制作的头文件进行比较,并注意到它们的函数声明似乎有点不同 例如,这里是来自string.h的strlen的声明: extern size\u t\u cdecl strlen(const char*) 在做一些研究后,我发现extern用于在函数块外声明变量。使用extern在头文件中声明我的函数是否也是最佳做法 我看到他们在这里使用size\u t这是unsigned long而不是int,我假设这是因为有几个原因(例如字符串的长度永远不

今天早些时候,我浏览了各种头文件,只是为了将它们与我正在制作的头文件进行比较,并注意到它们的函数声明似乎有点不同

例如,这里是来自
string.h
strlen
的声明:

extern size\u t\u cdecl strlen(const char*)

在做一些研究后,我发现
extern
用于在函数块外声明变量。使用
extern
在头文件中声明我的函数是否也是最佳做法

我看到他们在这里使用
size\u t
这是
unsigned long
而不是
int
,我假设这是因为有几个原因(例如字符串的长度永远不会是负数)它更有效,但这就是他们在这里使用
size\u t
的原因吗?还是我完全没有抓住要点

最后我看到了我找不到太多信息的
\uu cdecl
。确切地说,什么是cdecl?我也应该用吗

最后,我注意到在这个声明中,传递给strlen
的参数没有变量名。我猜这是因为这不是一个函数原型,只是一个声明,原型在别处。为什么声明中没有变量名,例如
strlen(const char*str)

最后一个问题是,如果这只是一个声明,strlen的函数原型会是什么样子?我猜是这样的:

size\u t strlen(常量字符*str)

我这样问是因为我想学习和改进我的代码(假设我在C文件中创建函数原型/声明,然后在头文件中创建函数声明,以便其他C文件可以使用它们)

  • size\u t
    strlen
    的更合适的返回值,而不是
    int
  • \uu cdecl
    是函数的调用约定。这表示谁为参数、返回值等设置堆栈,谁清除堆栈。更多参考:
  • 声明函数时,实际上不需要参数名。仅参数类型就足够了
  • 外部
    更新

    • extern
      告诉编译器该语句只是一个声明,而不是定义。因此,对于函数原型,
      extern
      不会添加任何值,因为它已经只是一个定义。参考:

    希望这有帮助。

    在声明函数时,
    extern
    关键字是多余的,因为很明显它必须在其他地方定义。对于声明和定义之间没有差异的变量,如果没有
    extern

    size\u t
    strlen
    定义返回的值,则情况就不一样了。在您的例子中,它似乎也是一个64位系统,理论上,字符串可以比
    int
    中存储的字符串大

    \uu cdecl
    是编译标准库时使用的调用转换。如果您应该为程序选择不同的调用约定(使用某些编译器选项),预编译库函数仍将使用正确的约定


    我通常在函数声明中命名所有参数,因为它有助于记录它们是什么。仅仅
    intf(int,int,int,int)
    对我帮助不大,但对于编译器来说已经足够了。因此,名称是可选的。

    关于大小,正如@Rohan所说,它是一种用来容纳大小的类型。例如,它不能是负的。这主要是因为一些安全问题。(例如,FreeBSD中的
    getpeername
    中由于使用int而不是size\t而导致的安全漏洞)
    关于cdecl,这可能会帮助您(来自):

    Borland和Microsoft使用通用语法进行声明。它们将cdecl和stdcall关键字添加到C中。这些关键字充当函数修饰符,并在原型中出现在函数名的前面。例如,对于Borland和Microsoft,函数f的定义如下:

    void uu cdecl f(int)

    每种调用约定都有优点和缺点。cdecl公约的主要优点是简单且非常灵活。它可以用于任何类型的C函数和C编译器。使用其他约定可能会限制子例程的可移植性。它的主要缺点是速度可能比其他一些慢,并且使用更多的内存(因为每次调用函数都需要代码来删除 堆栈上的参数)

    stdcall约定的优点是使用更少的内存 而不是cdecl。调用指令后不需要进行堆栈清理。主要 缺点是它不能与具有变量的函数一起使用 参数的数量。[如
    printf
    ]


    我真的很喜欢这个答案,但是如果你不使用参数名,你实际上如何在函数中使用给定的参数呢?这只是原型。当您编写实际函数时,参数将被命名。啊,这实际上现在很有意义!:-)非常感谢。