局部变量的地址
address of local variable
我很难理解这三者之间的区别:
const char * f() {
return "this is a test";
}
const char * g() {
const char * str = "test again";
return str;
}
const double * h() {
const double a = 2.718;
return &a;
}
我收到一个关于h()
的警告,作为warning: address of local variable ‘a’ returned
。这是有道理的,但我不明白为什么编译器(gcc -Wall
)可以使用f()
和g()
函数。
- 那里不是有一个局部变量吗
f()
或g()
返回的指针何时以及如何被释放
字符串文字不存储在本地堆栈帧中。它们位于可执行文件中的固定位置。对比度:
const char * g() {
const char * p = "test again";
return p;
}
带有
const char * g() {
const char a[] = "test again";
return a;
}
在前者中,返回值指向可执行文件中的固定位置。在后者中,返回值指向堆栈(现在是堆栈中的无效位置)。
它是字符串文字。
n3337 2.14.5/8
普通字符串文字和UTF-8字符串文字也称为窄字符串文字。狭窄string literal的类型为"array of n const char",其中n是下面定义的字符串大小,并且静态存储持续时间
const char * g() {
const char * str = "test again";
return str;
}
这不会返回局部变量的地址。变量是str
,因此它的地址应该是&str
,这与str
本身不同:
std::cout << (void*) str << std::endl;
std::cout << (void*) &str << std::endl; //address of str (local variable)
他们会打印不同的值!
因此,一个更恰当的例子是:
const char ** g() {
const char * str = "test again";
return &str; //difference!
}
现在它返回局部变量的地址。一个好的编译器可能会对此发出警告。
另一个例子是:
const char * g() {
const char str[] = "test again"; //difference!
return str; //same as before
}
现在,即使您返回的str
似乎不是本地变量的地址,但它可能会发出警告,因为在这种情况下,str
和&str
的值将完全相同!现在尝试打印这些:
std::cout << (void*) str << std::endl;
std::cout << (void*) &str << std::endl; //address of str (local variable)
他们会打印相同的值!
字符串文字不是局部变量。第三个函数的字符串等价物是这个
const char * f() {
const char str[] = "this is a test";
return str;
}
在函数h
中,a
是一个局部变量,在函数返回后将不存在。您正在向该变量返回指针,因此在函数外取消引用指针是不正确的,并且是未定义的行为。
在f
和g
中,您将返回文字字符串。文本字符串具有静态存储:它们不是在堆栈上分配的,并且它们将在函数的生存期之后存在。
在g
的定义中:
const char *g()
{
const char *str = "test again";
return str;
}
str
是局部变量,但它是指向非-局部-静态分配-内存的指针。返回的是地址,而不是对局部变量的引用。
考虑g
的另一个定义:
const char *g()
{
const char str[] = "test again";
// incorrect: can't use str after the return:
return str;
}
现在g
和函数h
有同样的问题,在编译它时,应该会看到关于返回局部变量地址的同样警告。
字符串文字的存储分配是静态的,这就是为什么不会收到警告的原因。
试试这个,你会得到未定义的行为:
const char* getFoo()
{
std::string foo("hi");
return foo.c_str();
}
因为字符串foo是文本字符串的副本。
这些字符串被物理地和永久地放置在数据存储器中,因此它们的地址是永久的。自动变量在堆栈上,因此当您从调用返回时,它将消失。
- libmysql:警告:返回局部变量"行"的地址(C++/C)
- 从函数返回变量地址时如何修复"与局部变量关联的堆栈内存地址"?
- 变量循环范围会导致返回局部变量的地址引用
- 局部变量保存相同的内存地址
- 使用函数模板中静态局部变量的地址作为类型标识符是否安全
- 警告:返回局部变量'buffer'地址
- 返回的与局部变量关联的堆栈内存的地址 (C++)
- 局部变量的地址
- 警告:返回局部变量"角度"的地址 [-Wreturn-local-addr]
- 是否释放了局部变量的地址
- 局部变量和其他变量类型的地址存储在哪里
- 局部变量的内存地址根据 lambda 参数的预感而变化
- 我想返回局部变量的地址
- 为什么局部变量的地址每次都不同
- 将局部变量的地址作为C++11中的常量表达式
- 为什么编译器在编译时不知道局部变量的地址?
- 更改局部变量的地址
- 局部变量的返回地址和程序仍然有效
- 为什么局部变量的地址对于不同的执行是相同的
- 将地址返回给局部变量与返回指向局部变量的指针