1. 主页
  2. 文档
  3. C语言教程
  4. C语言函数
  5. C中函数原型的重要性

C中函数原型的重要性

函数原型告诉编译器一些参数函数接受参数的数据类型和函数的返回类型。通过使用这些信息,编译器通过函数定义和函数调用交叉检查函数参数及其数据类型。如果我们忽略函数原型,程序可能会在编译时出现警告并可能正常工作。但有时,它会给出奇怪的输出,并且很难找到这样的编程错误。让我们看看例子

#include <errno.h>
#include <stdio.h>

int main(int argc, char *argv[])
{
FILE *fp;

fp = fopen(argv[1], "r");
if (fp == NULL) {
fprintf(stderr, "%s\n", strerror(errno));
return errno;
}

printf("file exist\n");

fclose(fp);

return 0;
}

上述程序检查从命令行提供的文件是否存在,如果给定文件存在,则程序打印“文件存在”,否则打印适当的错误消息。让我们提供一个文件系统中不存在的文件名,并检查程序在 x86_64 架构上的输出。 

[narendra@/media/partition/GFG]$ ./file_existence hello.c
Segmentation fault (core dumped)

为什么这个程序崩溃了,它应该显示一个适当的错误信息。该程序在 x86 架构上可以正常工作,但在 x86_64 架构上会崩溃。让我们看看代码有什么问题。仔细浏览程序,我特意没有包含“strerror()”函数的原型。此函数返回“指向字符的指针”,它将打印一条错误消息,该错误消息取决于传递给此函数的 errno。请注意,x86 架构是 ILP-32 模型,这意味着整数、指针和 long 都是 32 位宽,这就是程序可以在此架构上正常工作的原因。但是 x86_64 是 LP-64 模型,这意味着 long 和指针是 64 位宽的。在 C 语言中,当我们不提供 函数的原型时,编译器假定函数返回一个整数. 在我们的示例中,我们没有包含“string.h”头文件(strerror 的原型在该文件中声明),这就是编译器假定函数返回整数的原因。但它的返回类型是一个指向字符的指针。在 x86_64 中,指针是 64 位宽,整数是 32 位宽,这就是为什么从函数返回时,返回的地址会被截断(即 32 位宽地址,即 x86_64 上整数的大小),这是无效的当我们试图取消引用这个地址时,结果是一个分段错误。
现在包含“string.h”头文件并检查输出,程序将正常工作。 

[narendra@/media/partition/GFG]$ ./file_existence hello.c
No such file or directory

再考虑一个例子。 

#include <stdio.h>

int main(void)
{
int *p = malloc(sizeof(int));

if (p == NULL) {
perror("malloc()");
return -1;
}

*p = 10;
free(p);

return 0;
}

上面的代码在 IA-32 模型上可以正常工作,但在 IA-64 模型上会失败。这段代码失败的原因是我们没有包含 malloc() 函数的原型,并且返回值在 IA-64 模型中被截断。

这篇文章对您有用吗?