这个问题只是为了让我更好地理解C ++中的静态变量。
我认为如果它被声明为静态,我可以在C ++中返回对局部变量的引用,因为变量应该在函数返回后生效。为什么这不起作用?
#include <stdio.h>
char* illegal()
{
char * word = "hello" ;
return word ;
}
char* alsoNotLegal()
{
static char * word = "why am I not legal?" ;
return word ;
}
int main()
{
// I know this is illegal
//char * ill = illegal();
//ill[ 0 ] = '5' ;
//puts( ill ) ;
// but why is this? I thought the static variable should "live on" forever -
char * leg = alsoNotLegal() ;
leg[ 0 ] = '5' ;
puts( leg ) ;
}
答案 0 :(得分:20)
这两个功能本身并不违法。首先,在这两种情况下,您都会返回指针的副本,该指针指向具有静态存储持续时间的对象:字符串文字将在整个程序持续时间内生效。
但是你的main
函数是关于未定义的行为。你不能写入字符串文字的内存:)你的主要功能可以减少到相同的行为
"hello"[0] = '5';
"why am I not legal?"[0] = '5';
两者都是未定义的行为,并且在某些平台上崩溃(好!)。
编辑:请注意,字符串文字在C ++中具有const类型(在C中不是这样):char const[N]
。对指向非const字符的指针的赋值会触发不推荐的转换(无论如何,一个好的实现都会警告)。因为上面对const数组的写法不会触发转换,所以代码会错误编译。真的,你的代码正在这样做
((char*)"hello")[0] = '5';
((char*)"why am I not legal?")[0] = '5';
答案 1 :(得分:4)
只有指针是静态的,它指向一个常量字符串。做leg [0] ='5'不行,因为它修改了常量字符串。
静态在这种情况下没有什么区别,这实际上是一样的:
char* alsoNotLegal()
{
return "why am I not legal?";
}
答案 2 :(得分:3)
当您定义并初始化指向char的指针时:
char * word = "hello";
你实际上是在告诉编译器将固定字符串“hello”放到某个固定的存储区中,然后创建word
指针变量来指向它。
虽然您更改了word
变量以指向其他内容,如果它确实指向某个可变存储,您可以通过*和[]运算符更改其指向的内容,则不允许更改已修复的字符串“你好”通过它。
C ++允许将固定字符串分配给指向非const char
的指针,纯粹是为了向后兼容。最好只将这些字符串分配给指向const char
的指针。 e.g。
const char * word = "hello";
这样可以防止通过编译时类型检查导致非法的运行时行为。
编辑:
在您的示例中,将局部变量声明为静态与否之间基本上没有外部可见的区别。这会影响每个函数中指针变量的生命周期。它不会影响指针变量指向的固定字符串的生命周期。当函数返回指针变量的值时(在C ++中返回总是按值),函数末尾是否销毁函数中的指针变量并不特别重要。字符串本身将永远超出函数的范围,因为字符串文字具有静态存储持续时间。
答案 3 :(得分:2)
你可能想要的是:
char* alsoNotLegal()
{
static char[] word = "why am I not legal?" ;
// static char* x = "X"; <- Not good.
// static const char* y = "Y"; <- Good. As the compiler will warn you about
// Illegal attempts to modify it.
return word ;
}
注意:在这里你要创建一个字符数组'单词'并复制“为什么我不合法?”进入阵列。您可以对阵列进行更改。
另外,由于语言处理数组的方式,它们会在一个帽子处生成指针,当你返回一个数组(或将它作为参数传递)时,它会自动转换为指针。
答案 4 :(得分:1)
这些“即时”字符串存储在Windows上PE的READ-ONLY“r”部分中。这就是当您尝试写入该位置时出现操作系统异常的原因。
如果您有Ollydbg或者您阅读了反汇编输出,则可以看到字符串位于RDATA部分(只读数据部分)。 如果它是存储在堆上的常规字符串,则没有问题
char* alsoNotLegal()
{
static char word[] = "why am I not legal?" ;
return word ;
}
这将起作用,因为字符串将存储在“堆”中,即可执行映像的读/写部分。
答案 5 :(得分:0)
你的static是一个const字符串文字。你不应该修改它。有些编译器可能允许你这样做。如果你的静态是一个std :: string,那么你就可以从调用者那里修改它。
答案 6 :(得分:0)
来自wikipedia:
在C编程语言及其中 后代,术语静态变量 至少有两个特定和 基本上不相关的含义 与C的静态语义有关 关键字:
静态局部变量,它们通常作用域,但具有静态 储存期限(相对于 声明自动局部变量 使用auto关键字)
- 醇>
静态全局变量,具有通常的静态存储持续时间,但是 范围限定在它们所在的文件中 定义(与外部相对) 用extern声明的变量 关键字)
因此。您声明的静态变量通常是作用域 - 它们的范围仍然在它们各自的函数内,并且在这些函数之外不可用。
你仍然可以返回指针,但它们并不意味着什么。
编辑:
同样来自this page:
全局函数中的静态局部可以 被认为是全局变量, 因为他们的价值仍然在记忆中 为了节目的生命。1 唯一的区别是它们只是 可访问(即,作用域)到一个 功能
答案 7 :(得分:0)
适合我......?
#include<iostream>
using namespace std;
char* legal() {
char* word = "helllo";
return word;
}
char* alsoLegal() {
static char* word = "hello!";
return word;
}
int main(){
cout << legal() << endl;
cout << alsoLegal() << endl;
return 0;
}
但正如你在问题中的评论中已经指出的那样,我们返回指针而不是引用,这只是一个字符&amp;,你只需要输入“字符串”的第一个字母。