2012-12-13 75 views
0

对于返回值:未指定的返回值

func() 
{ 
    while(1) 
    { 
    /* do stuff here */ 
    if(error1) exit(0); 
    if(error2) break; 
    }  
    /* no return statement anywhere in func() */ 
} 

但主叫方检查FUNC()

if(func()) {/* error handling */} 

什么了不错的返回码会有人来确认返回值func()不默认任何东西,并且是垃圾。并认为这是对所有这些真:

  • void func()
  • int func(),未设有return语句所有,或与普通return;
  • func(),未指定返回类型,我明白默认返回int。

感谢..

+1

另请注意,在没有列出参数的情况下在C中定义或声明函数意味着参数也是未指定的。如果函数不需要参数,则必须明确地定义/声明参数为“void”。 –

+0

谢谢@JoachimPileborg,我真的在那里发布了一些东西来表达我的观点,但是谢谢。 – nantonop

回答

3

注意:此答案适用于C89(及更早版本)。

void func()指定不返回值的函数。在这种情况下,if (func())应该会导致编译错误。

int func()func()是等价的并返回一个整数值。 如果return语句未提供任何值,则结果未定义,并且如果警告级别足够高,编译器会发出警告。 实际上,大多数编译器会生成代码,返回用于返回值的寄存器或内存位置中的内容。

+0

-1,隐式int无效C,它已从标准中删除。 – Lundin

+0

谢谢,就此添加了一个注释。 –

+1

“结果未定义” - 准确地说*如果“调用者使用函数调用的值”,行为*未定义。所以它不只是“可以是任何整数,不知道哪个”,它可能会“崩溃”。不过,我不确定什么调用约定实际上会导致崩溃。 –

2

一个函数的返回值是通常由处理器的第一寄存器,例如返回基于x86的EAX或基于ARM的r0处理器。它是编译器特定的,但是或多或少是标准的。

例如在C中的return 10;将被编译为

mov eax 10 ; pseudo code 
ret  ; pseudo code 

用于基于x86的处理器的程序集。

&虽然检查返回值,它只会检查eax寄存器。无论该寄存器中包含的内容是否被调用者视为返回值。

SO ...如果你没有返回值(简单的return;),或者它是一个void函数,EAX中的ret语句在汇编语言中的任何值都被调用者作为返回值。

对于基于ARM的处理器,请在上面的答案中将EAX替换为r0。 :-)

我用这个事实,作为一个黑客下面的功能;-)

void* getStackTop(){ 
    asm("mov eax esp"); 
} 

要检查它究竟是如何工作的,而由C翻译成ASM,下面写一个简单的代码:

int testfn(int unused){ 
    int unused2=unused; // Check how input is passed 
    return 10;   // Check how output is returned 
} 

&然后用gcc -S编译。 (或与您的编译器只会生成组件的一些标志)。


我不知道它是如何返回浮点/结构值。 可能是它返回一个指向struct &的指针,整个返回的结构在引擎盖下被memcpy化,同时转化为asm。有人可能会纠正:-)

+0

您只是描述了许多可能的未定义行为之一。在这种情况下,这并不是真正相关的,因为发布的代码是无效的。 – Lundin

+0

这个答案与常见的编译器(如gcc/visual studio等)一致。但是,它在某些编译器上可能会有所不同。加上许多编译器,包括gcc _allow_一些增加/放宽到**标准** C.至少在gcc上,它只会给出警告,如果你省略了返回类型并且它会假设'int':'warning:返回类型默认为int [-Wreturn-type]' – anishsane

+0

但是还有很多其他的CPU架构,你的答案不适用。对于每个这样的体系结构,都有各种不同的编译器,具有不同的调用约定。 – Lundin

0

自从C99标准以来,您在无效的C代码中发布的代码。

如果您使用的是一个实现了C90标准的过时编译器,它将进行编译,并且默认类型将为int。我相信从这样的函数中省略return语句会导致未定义的行为,尽管我不能引用C90标准。

+0

“一个过时的编译器” - 例如gcc。或者用合适的命令行选项铿锵声。或MSVC。这不是编译器实现的问题,而是编写代码的语言。如果它是用C89编写的,那么你可能需要一个C89编译器来编译它,即使它碰巧也是有效的C99,为了谨慎起见,编译C89通常比编译它在C99中的含义是否更容易与C89中的含义相同。 –