代码之家  ›  专栏  ›  技术社区  ›  quinmars

(字符串)字面值的范围

  •  36
  • quinmars  · 技术社区  · 17 年前

    我总是尽量避免返回字符串文字,因为我担心它们不是在函数外部定义的。但我不确定情况是否如此。让我们以这个函数为例:

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

    这是正确的代码吗?它确实对我有效,但也许它只对我的编译器(gcc)有效。所以问题是,(字符串)文字是否有作用域,或者它们是否一直存在/定义。

    7 回复  |  直到 17 年前
        1
  •  40
  •   Brian R. Bondy    17 年前

    这段代码在所有平台上都很好。字符串作为静态字符串文字被编译成二进制文件。例如,如果你在windows上,你甚至可以用记事本打开.exe并搜索字符串本身。

    因为它是一个静态字符串,所以文字范围并不重要。

    字符串池:

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

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

    字符串文字的最大大小:

    几个编译器对字符串文字有最大大小限制。例如,在VC++中,这大约是2048个字节。

    修改字符串文字会产生未定义的行为:

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

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

    宽字符串文字:

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

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

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

    1字符串文字是一个序列 字符(定义见 lex.ccon )用双引号括起来,可以选择以 字母L,如“…”或L“…”。未开始的字符串文字 L是一个普通的字符串文字,也称为狭义 字符串文字。普通字符串文字的类型为“n数组” 恒定的 char”和静态存储持续时间( 基本.stc ),其中n是 大小 如下定义的字符串,并用给定的值初始化 字符。以L开头的字符串文字,例如L“asdf”, 是 宽字符串文字。宽字符串文字的类型为“array of n const wchar_t”,具有静态存储持续时间,其中n是大小 属于的 如下定义的字符串,并用给定的字符进行初始化- 特斯。

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

        2
  •  9
  •   Sumit Trehan    14 年前

    我给你举个例子,这样你的困惑就有点清楚了

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

    这行不通。

    但是

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

    这行得通。

    原因: "SUMIT" 是一个具有全局范围的文字。 而数组只是一个字符序列 {'S','U','M','I',"T''\0'} 它的作用域有限,一旦程序返回,它就会消失。

        3
  •  5
  •   Steve Jessop    17 年前

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

    我可以想到要注意的一件事是,如果你使用dll,那么如果卸载了包含此代码的dll,指针将不再有效。

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

        4
  •  3
  •   Bill K    17 年前

    是的,那很好。它们生活在一个全局字符串表中。

        5
  •  3
  •   Adam Rosenfield    17 年前

    不,字符串文字没有作用域,因此您的代码可以保证在所有平台和编译器上工作。它们存储在程序的二进制映像中,因此您始终可以访问它们。然而,试图给他们写信(通过扔掉 const )将导致未定义的行为。

        6
  •  0
  •   PhiLho    17 年前

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

        7
  •  0
  •   Jason Coco superfell    17 年前

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