(字符串)文字的范围

我总是尽量避免返回字符串文字,因为我担心它们不是在函数之外定义的。 但我不确定是不是这样。 我们来看一下这个函数:

const char * return_a_string(void) { return "blah"; } 

这是正确的代码吗? 它确实适用于我,但它可能只适用于我的编译器(gcc)。 所以问题是,do(字符串)文字有一个范围,或者它们是否一直存在/定义。

这段代码适用于所有平台。 字符串作为静态字符串文字编译到二进制文件中。 例如,如果您在Windows上,您甚至可以使用记事本打开.exe并搜索字符串本身。

既然它是一个静态字符串文字范围无关紧要。

字符串池:

需要注意的一点是,在某些情况下,可以“汇集”相同的字符串文字以节省可执行文件中的空间。 在这种情况下,每个相同的字符串文字可以具有相同的内存地址。 你永远不应该假设它会或不会是这种情况。

在大多数编译器中,您可以设置是否使用静态字符串池进行搅拌文字。

字符串文字的最大大小:

几个编译器具有字符串文字的最大大小。 例如,对于VC ++,这大约是2,048字节。

修改字符串文字会给出未定义的行为:

永远不应该修改字符串文字。 它有一个未定义的行为。

 char * sz = "this is a test"; sz[0] = 'T'; //<--- undefined results 

宽字符串文字:

以上所有内容同样适用于宽字符串文字。

示例:L“这是一个宽字符串文字”;

C ++标准规定:( section lex.string)

1字符串文字是由双引号括起来的字符序列(在lex.ccon中定义),可选地以字母L开头,如“......”或“L”......“。 不以L开头的字符串文字是普通的字符串文字,也称为窄字符串文字。 普通的字符串文字具有类型“n const char数组”和静态存储持续时间( basic.stc ),其中n是下面定义的字符串的大小,并使用给定的字符进行初始化。 以L开头的字符串文字,例如L“asdf”,是一个宽字符串文字。 宽字符串文字具有类型“n const wchar_t的数组”并具有静态存储持续时间,其中n是下面定义的字符串的大小,并使用给定的字符进行初始化。

2是否所有字符串文字都是不同的(即存储在非重叠对象中)是实现定义的。 尝试修改字符串文字的效果未定义。

我举个例子,让你的困惑变得有些明显

 char *f() { char a[]="SUMIT"; return a; } 

这不行。

 char *f() { char *a="SUMIT"; return a; } 

这很有效。

原因:“SUMIT”是一个具有全局范围的文字。 虽然数组只是一个字符序列{‘S’,’U’,’M’,’I’,“T”\ 0’}具有有限的范围,并且一旦返回程序就会消失。

希望这可以帮助

正如其他人所解释的那样,这在C(或C ++)中是有效的。

我能想到的一点是,如果你正在使用dll,那么如果卸载包含这段代码的dll,指针将不会保持有效。

C(或C ++)标准不理解或考虑在运行时加载和卸载代码,因此执行此操作的任何内容都将面临实现定义的后果:在这种情况下,结果是字符串文字,应该具有静态存储持续时间,从调用代码的POV出现,不会持续整个程序的持续时间。

是的,没关系。 它们存在于全局字符串表中。

不,字符串文字没有范围,因此您的代码可以保证在所有平台和编译器中工作。 它们存储在程序的二进制映像中,因此您可以随时访问它们。 但是,尝试写入它们(通过丢弃const )将导致未定义的行为。

实际上,您返回一个指向存储在可执行文件数据部分中的以零结尾的字符串的指针,这是加载程序时加载的区域。 只是避免尝试更改字符,它可能会产生不可预测的结果……

记下Brian提到的未定义结果非常重要。 由于您已将该函数声明为返回const char *类型,因此您应该没问题,但在许多平台上,字符串文字被放入可执行文件中的只读段(通常是文本段)并修改它们将导致访问冲突在大多数平台上。