使用gcc5.2.0,我注意到这段代码没有生成警告:
#include <stddef.h>
int function(void)
{
return NULL;
}
void procedure(void)
{
return NULL;
}
Run Code Online (Sandbox Code Playgroud)
我使用了旗帜-Wall -Wextra -std=c99 -pedantic,我正在运行archlinux.我不确定为什么这段代码可以正常工作gcc,特别是因为clang3.7.0会产生警告.
我也尝试使用gcc类似4.9或4.7的旧版本,它们都会产生警告.
警告是:
warning: return makes integer from pointer without a cast
Run Code Online (Sandbox Code Playgroud)
和
warning: ‘return’ with a value, in function returning void
Run Code Online (Sandbox Code Playgroud)
我应该提一下,我尝试在Debian上编译gcc 5.2,结果是一样的.所以archlinux似乎不是问题所在.
理由是什么?我似乎无法在其他任何地方找到与此相关的任何内容.
谢谢!
假设我们有以下代码:
#if !defined(__cplusplus)
# error This file should be compiled as C++
#endif
#include <stdio.h>
#include <string>
//#define USE_CXX_CLASS
#ifdef USE_CXX_CLASS
class SomeClass
{
public:
SomeClass() {}
~SomeClass() {}
std::string GetSomeString()
{
// case #1
}
};
#endif // USE_CXX_CLASS
int foo()
{
// case #2
}
int
main (int argc, char *argv[])
{
(void)argc;
(void)argv;
#ifdef USE_CXX_CLASS
SomeClass someInstance;
someInstance.GetSomeString();
#endif // USE_CXX_CLASS
foo();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
并且假设它是使用选项从GCC版本4.2.1编译C++编译器(而不是C编译器)-Wreturn-type -Werror=return-type.如果上面的代码是按原样编译而没有先取消//#define USE_CXX_CLASS上面的行,那么你会看到一个警告但没有错误:
.../gcc-4.2.1/bin/g++ -g -fPIC …Run Code Online (Sandbox Code Playgroud) 如果函数声明为 void 返回值(无返回值),则函数定义返回任何值都是错误的。
如果函数声明为非空返回值(返回某个值或对象),那么如果函数定义未能返回值,则不是错误。一些编译器会生成关于此的缺失返回值警告。
这是什么原因?对我来说,交换这些值是有意义的,这样如果返回值失败就会产生错误,并且只有在尝试从声明为 void 返回类型的函数中返回值时才会收到警告。
我很惊讶包含以下代码行的文件已成功编译,链接器生成可执行文件.除了返回类型之外main,我认为所有函数除了必须有一个有效的return语句void.
int foo(){}
double bar(){}
int main(){}
Run Code Online (Sandbox Code Playgroud)
我错过了什么?
简单的问题。asmC语言中的函数用于在代码中进行内联汇编。但是它返回什么呢?它是常规的eax吗?如果不是,返回的是什么?
操作系统:ubuntu2204
编译器:gcc 11.2 x86_64
这是一个简单的代码:
#include <cstdlib>
int func(int val) {
if (val == 1) {
} else {
abort();
}
}
int main(int argc, char* argv[]) {
func(argc);
}
Run Code Online (Sandbox Code Playgroud)
当我在没有任何优化的情况下编译它并运行它时,它工作正常。
但是当我用 编译它时g++ tmp.cpp -O3,结果func会忽略输入值,而只调用abort.
当然,我可以通过在 的末尾添加 return 语句来修复它func,但是,为什么呢?
这是objdump -d a.out优化函数的一些输出func:
0000000000001060 <_Z4funci>:
1060: f3 0f 1e fa endbr64
1064: 50 push %rax
1065: 58 pop %rax
1066: 50 push %rax
1067: e8 e4 ff ff ff …Run Code Online (Sandbox Code Playgroud) c++ optimization assembly compiler-optimization undefined-behavior
关于SO的大多数问题都涉及非虚假返回类型,但是我们正在就此开展一场火焰战,并希望了解社区的想法.
void DoSomething()
{
return; // Is this needed?
}
Run Code Online (Sandbox Code Playgroud)
从这个讨论中,看起来具有未定义行为的问题涉及非void返回类型的函数.void返回类型是否具有相同的未定义行为,还是仅在非void返回函数中?
我担心的是,这最终将成为一种不可靠的编码风格.但是,如果它也是void返回函数的未定义行为,那么我可以看到需要将它添加到编码标准中.如果对C和C++的答案不同,这也是可以的.
§6.6.3退货声明
2没有表达式的return语句只能用于不返回值的函数,即返回类型为void的函数,contrsuctor(12.1)或析构函数(12.4).
§6.6.3/ 2
流出函数末尾相当于没有值的返回; 这会导致值返回函数中的未定义行为.
我知道我应该从"operator <<"返回"ostream&",以便能够像这样"链接"运算符
cout<<a<<b<<c;
Run Code Online (Sandbox Code Playgroud)
但是,在下面的代码中,我没有返回"ostream&",并且仍然可以进行链接.为什么?
#include <iostream>
using namespace std;
class CComplexNumber{
float m_realPart;
float m_imagPart;
public:
CComplexNumber(float r,float i):m_realPart(r),m_imagPart(i){}
friend ostream& operator<<(ostream& lhs,CComplexNumber rhs){
lhs<<"["<<rhs.m_realPart<<","<<rhs.m_imagPart<<"]"<<endl;
//MISSING RETURN STATEMENT!
}
};
int main() {
CComplexNumber a(1,2);
CComplexNumber b(3,4);
CComplexNumber c(5,6);
cout<<a<<b<<c;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
OUTPUT
[1,2]
[3,4]
[5,6]
Run Code Online (Sandbox Code Playgroud) 我找到了一些无法理解的东西.我认为它应该与函数堆栈和一些未定义的行为有关.
假设我有一个功能工厂模板(傻一个):
template <unsigned int N=10>
std::function<int&&(const int& n)> build_add_function() {
return [](const int& n) -> int&& {std::move(n+N);};
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,它缺少非void函数的return语句,因此编译器向我发出警告......奇怪的是它"按预期"工作
int main() {
auto foo = build_add_function();
std::cout << foo(10);
}
Run Code Online (Sandbox Code Playgroud)
主要输出: 20
当然,为了修复代码,我添加了return语句,它给了我一个分段错误
Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)
Run Code Online (Sandbox Code Playgroud)
我对我正在做的事情有一些误解,但我无法理解它.有人会向我解释这里发生了什么吗?我正在使用gcc版本8.0.1
编辑:刚刚测试gcc 4.8.1并使用return语句按预期工作,没有编译错误.
它是编译器的东西吗?
在这个高尔夫答案中,我看到了一个技巧,其中返回值是未传入的第二个参数。
int f(i, j)
{
j = i;
}
int main()
{
return f(3);
}
Run Code Online (Sandbox Code Playgroud)
从gcc 的汇编输出来看,当代码复制时,j = i它存储的结果eax恰好是返回值。
f:
pushq %rbp
movq %rsp, %rbp
movl %edi, -4(%rbp)
movl %esi, -8(%rbp)
movl -4(%rbp), %eax
movl %eax, -8(%rbp)
nop
popq %rbp
ret
main:
pushq %rbp
movq %rsp, %rbp
movl $3, %edi
movl $0, %eax
call f
popq %rbp
ret
Run Code Online (Sandbox Code Playgroud)
那么,这一切仅仅是因为幸运吗?gcc 对此有记录吗?它只适用于,但它适用于我尝试过-O0的一堆值,以及一堆不同版本的 GCC。i-m32