C语言中函数原型的重要性

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

null

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" , strerror ( errno ));
return errno ;
}
printf ( "file exist" );
fclose (fp);
return 0;
}


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

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

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

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

再举一个例子。

C

#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模型中被截断。 本文由 纳伦德拉·康拉尔卡 。如果您发现任何不正确的地方,或者您想分享有关上述主题的更多信息,请发表评论。

© 版权声明
THE END
喜欢就支持一下吧
点赞15 分享