使用没有原型的旧式函数的 C 编译器的行为

发布于 2024-08-22 04:28:41 字数 638 浏览 8 评论 0原文

当我的程序由两个文件组成时:

main.c

#include <stdio.h>

int main(void) { 
     printf("%lf\n",f());   
     return 0;
 }

func.c

double f(int a) {
 return 1;
}

编译器不显示任何错误。

当我的程序仅包含一个文件:

main.c

#include <stdio.h>

int main(void) { 
     printf("%lf\n",f());   
     return 0;
 }

double f(int a) {
 return 1;
}

Visual C++ 2008 编译器显示以下错误:

Error 2 error C2371: 'f' : redefinition; different basic types d:\temp\projects\function1\function1\1.c 8 function1

任何人都可以解释这一奇怪的行为吗?

When my program consists of two files:

main.c

#include <stdio.h>

int main(void) { 
     printf("%lf\n",f());   
     return 0;
 }

func.c

double f(int a) {
 return 1;
}

compiler do not show any errors.

When my program consists of only one file:

main.c

#include <stdio.h>

int main(void) { 
     printf("%lf\n",f());   
     return 0;
 }

double f(int a) {
 return 1;
}

Visual C++ 2008 compiler show the following error:

Error 2 error C2371: 'f' : redefinition; different basic types d:\temp\projects\function1\function1\1.c 8 function1

Can anybody explain this strange behavior?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

睫毛上残留的泪 2024-08-29 04:28:41

C 将假设一个函数具有原型 int func();除非你另有说明。(请注意,在 C 中 int func(); 和 int func(void); 是不同的东西)

在第二种情况下,你调用 f() ,其中编译器没有看到任何原型,因此假设它是 int f(); 。稍后它会看到您对 f() 的定义,它具有不同的原型 - 并发出错误。

在 1. 情况下不会发生这种情况,因为它们位于不同的编译单元中。

C will assume a function has the prototype int func(); unless you have told it otherwise.(Note that in C int func(); and int func(void); are different things)

In your second case, you do a call to f() for which the compiler hasn't seen any prototype, so it assumes it is int f(); . Later on it sees your definition for f() which has a different prototype - and issues an error.

This doesn't happen in the 1. case, as they're in different compilation units.

素手挽清风 2024-08-29 04:28:41

这两个程序都是错误的。

如果范围内没有原型,编译器会假定函数返回 int 并采用未指定数量的参数。

让我们稍微更改一下您的文件:

$ cat func.c
double f(int a) {
    return 1.0;
}
$ cat main.c
#include <stdio.h>

int main(void) { 
    double d = f();
    printf("%lf\n", d);
    return 0;
}

当我编译它时,gcc 会警告我(Visual C++ 也应该如此,在一致模式下)。但让我们忽略这个警告。

$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
func.c:1: warning: unused parameter 'a'
main.c: In function 'main':
main.c:4: warning: implicit declaration of function 'f'
$ ./test
0.000000

它没有打印 1,而是打印 0。这是因为编译器假设 f() 返回一个 int,并且赋值 d = f(); 将“int”转换为double。编译器仍然编译代码,因为它无法判断 f() 没有按照(隐式)声明的方式定义。但是标准并不要求编译上述程序,因此编译器可能会拒绝它(例如尝试使用 gcc -Werror!)

如果我们将所有内容都放在一个文件中:

$ cat func.c >>main.c
$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
main.c:4: warning: implicit declaration of function 'f'
main.c: At top level:
main.c:9: error: conflicting types for 'f'
main.c:4: error: previous implicit declaration of 'f' was here
main.c:9: warning: unused parameter 'a'

现在编译器会看到冲突,并给出错误消息。但是,编译器不需要拒绝上述程序,它可能会也可能不会。

大多数编译器不会拒绝第一个程序,因为它们不知道您在另一个翻译单元中是否有正确的函数 f() 定义。他们拒绝第二个计划,因为他们知道你不知道。

Both the programs are wrong.

Without a prototype in scope, a compiler assumes that a function returns int and takes an unspecified number of parameters.

Let's change your files a bit:

$ cat func.c
double f(int a) {
    return 1.0;
}
$ cat main.c
#include <stdio.h>

int main(void) { 
    double d = f();
    printf("%lf\n", d);
    return 0;
}

When I compile it, gcc warns me (Visual C++ should too, in conformant mode). But let's ignore the warning.

$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
func.c:1: warning: unused parameter 'a'
main.c: In function 'main':
main.c:4: warning: implicit declaration of function 'f'
$ ./test
0.000000

It did not print 1, but printed 0. This is because the compiler assumed that f() returned an int, and the assignment d = f(); converted that "int" to a double. The compiler still compiled the code because it couldn't tell that f() wasn't defined the way it was (implicitly) declared. But compiling the above program isn't required by the standard, so the compiler could have rejected it (try with gcc -Werror for example!)

If we have everything in one file:

$ cat func.c >>main.c
$ gcc -std=c99 -pedantic -W -Wall func.c main.c -o test
main.c:4: warning: implicit declaration of function 'f'
main.c: At top level:
main.c:9: error: conflicting types for 'f'
main.c:4: error: previous implicit declaration of 'f' was here
main.c:9: warning: unused parameter 'a'

Now the compiler sees the conflict, and gives you an error message. But, a compiler is not required to reject the above program, it may or may not.

Most compilers don't reject the first program because they don't know if you have a correct definition of the function f() in another translation unit or not. They reject the second program because they know that you don't.

静若繁花 2024-08-29 04:28:41

您的第一个示例从不使用 func.c 所以我不确定编译器对 f() 做了什么,因为它没有定义。

在第二个示例中,我不知道为什么不能有两个具有不同签名的函数,但您没有调用您定义的函数。您可以不带参数调用 f(),但您定义的 f 采用 int,这使其成为不同的函数。

Your first example never uses func.c so I'm not sure exactly what the compiler is doing about f() because it has no definition.

In the second example, I don't know why you can't have two functions with different signatures, but you aren't calling the function you've defined. You call f() with no arguments, but the f you define takes an int which makes it a different function.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文