C语言中的void函数返回什么?

3
#include <stdio.h>

void main()

{

    int k = m();

    printf("%d", k);

}

void m()

{

    printf("hello");

}  

输出
hello5

这个void函数返回什么? 如果没有printf()函数,那么输出是1。 这里发生了什么?


你使用的编译器是哪个? - anatolyg
https://dev59.com/7HVC5IYBdhLWcg3wtzkQ - Grijesh Chauhan
2
在你的 C 技能大幅提高并且知道何时不适用时,始终使用 GCC 的 -Wall 选项。这意味着“启用所有默认应该开启但为了兼容性而未开启的警告”。(如果需要,还有更多警告可用,但误报率更高。) - zwol
5个回答

7
一个 void 函数不返回任何内容。你的程序会引起未定义行为,因为它隐式地将 m 定义为返回类型为 int(在 C89 中,如果一个函数在声明之前被调用,它会被默认为返回类型为 int),但是后来将其定义为返回类型为 void
如果你为 m 添加前向声明,编译器会正确地抱怨你试图使用一个无返回值函数的返回值,这是不可能的。

4
实际发生的事情(虽然没有一致性的保证)是 main 函数获取了 printf 函数留下的返回值(因为它打印了 5 个字符,所以返回值为 5)。 - hobbs

4

在两种情况下(带有期望为int的调用者的void m,带有在C库中期望为int的调用者的void main),这都是未定义行为,您的编译器应该给出警告,例如[GCC 4.8 with -Wall]:

test.c:3:6: warning: return type of ‘main’ is not ‘int’
 void main()
      ^
test.c: In function ‘main’:
test.c:7:5: warning: implicit declaration of function ‘m’
     int k = m();
     ^
test.c: At top level:
test.c:13:6: warning: conflicting types for ‘m’
 void m()
      ^
test.c:7:13: note: previous implicit declaration of ‘m’ was here
     int k = m();
             ^

"

隐式声明"仅为向与C1989之前相比超过20年的旧程序保持向后兼容性而存在。如果您以更现代的风格编写此代码,则会收到一个严格的错误提示:

"
#include <stdio.h>

extern void m(void);

int main(void)
{
    int k = m();
    printf("%d", k);
    return 0;
}

void m(void)
{
    printf("hello");
}

test.c: In function ‘main’:
test.c:7:13: error: void value not ignored as it ought to be
     int k = m();
             ^

关键的添加是 extern void m(void); 这一行。当编译器检查 main 是否存在错误时,它不允许向前查看 m 的定义,因此需要一个前向声明来告诉它 m 的类型。你还应该知道,在 C 语言中(但不是在 C++ 中),void m() 表示 "m 接受 未指定数量的 参数"。要声明一个不带参数的函数,也就是你想要的内容,必须写成 void m(void)
我相信在你特定的系统上发生的情况是,printf 的返回值被忽略了,但实际上仍然存储在返回值寄存器中,并被解释为 m 的返回值,但是 你不能依赖于任何可预测的结果。这就是所谓的“未定义行为”。

2

这是未定义行为。

编译器允许你进行赋值的原因是它没有可用的m原型。当发生这种情况时,C标准规定函数必须返回int。由于在这种情况下实际的函数返回类型是void,因此行为未定义。变量k中得到的值是完全任意的。


1

函数的返回值通常存储在CPU寄存器之一中,对于x86架构来说是EAX。由于C语言就像友好的汇编语言一样,您可以随时从寄存器中读取该值,并且您将得到其中的任何内容。有效地说,int k = m()告诉程序将寄存器EAX的值存储在变量k中。


0

在调用main中的void m();之前,您尚未声明它。

一些编译器将未知函数符号的返回类型视为int(当然是在编译时未知的)。实际上,您的编译器可能已经发出了编译警告。

如果您在main之前(应该)声明此函数,则可能会收到编译错误。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接