C ++中字符串文字的数据类型是什么?

时间:2020-12-27 16:37:39

Similar questions have been asked about the data type of string literals in C++.

关于C ++中字符串文字的数据类型,已经提出了类似的问题。

Many people have cited the standard:

很多人都引用了这个标准:

A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7)

窄字符串文字的类型为“n const char数组”,其中n是下面定义的字符串大小,并且具有静态存储持续时间(3.7)

I've written the following statement in the main function:

我在main函数中写了以下语句:

  char cstring[]= "hellohellohellohellohellohello";

But I can't find any string literal stored as static data in the assembly. In fact, the assembly shows that the string is decomposed and "stored" directly in the instructions.

但我找不到任何字符串文字作为静态数据存储在程序集中。事实上,程序集显示字符串被分解并直接“存储”在指令中。

    movl    $1819043176, -48(%rbp)
    movl    $1818585199, -44(%rbp)
    movl    $1701343084, -40(%rbp)
    movl    $1752132716, -36(%rbp)
    movl    $1869376613, -32(%rbp)
    movl    $1819043176, -28(%rbp)
    movl    $1818585199, -24(%rbp)
    movw    $28524, -20(%rbp)
    movb    $0, -18(%rbp)

While a similar statement in the global scope has as a result the string stored as static data.

虽然全局范围中的类似语句因此将字符串存储为静态数据。

char cstring1[] = "hellohellohellohellohellohello";

The assembly

cstring1:
    .string "hellohellohellohellohellohello"

The above example is available online here.

以上示例可在此处在线获取。

So this seems not conform to the cited standard. Maybe there are some exceptions to what is cited here?

所以这似乎不符合引用的标准。也许这里引用的内容有一些例外情况?

3 个解决方案

#1


8  

Expressions have type. String literals have type if they are used as an expression. Yours isn't.

表达式有类型。字符串文字如果用作表达式,则具有类型。你的不是。

Consider the following code:

请考虑以下代码:

#include <stdio.h>

#define STR "HelloHelloHello"

char global[] = STR;

int main(void)
{
    char local[] = STR;
    puts(STR);
}

There are three string literals in this program formed using the same tokens, but they are not treated the same.

此程序中有三个字符串文字使用相同的标记形成,但它们的处理方式不同。

The first, the initializer for global, is part of static initialization of an object with static lifetime. By section 3.6.2, static initialization doesn't have to take place at runtime; the compiler can arrange for the result to be pre-formatted in the binary image so that the process starts execution with the data already in place, and it has done so here. It would also be legal to initialize this object in the same fashion as local[], as long as it was performed before the beginning of dynamic initialization of globals.

第一个是global的初始化器,是具有静态生存期的对象的静态初始化的一部分。根据3.6.2节,静态初始化不必在运行时进行;编译器可以安排在二进制映像中预先格式化结果,以便进程在已经存在的数据的情况下开始执行,并且在此处已完成。以local []的方式初始化此对象也是合法的,只要它在全局变量动态初始化之前执行即可。

The second, the initializer for local, is a string literal, but it isn't really an expression. It is handled under the special rules of 8.5.2, which states that the characters within the string literal are independently used to initialize the array elements; the string literal is not used as a unit. This object has dynamic initialization, resulting in loading the value at runtime.

第二个是local的初始化器,是一个字符串文字,但它实际上不是表达式。它是根据8.5.2的特殊规则处理的,该规则规定字符串文字中的字符独立用于初始化数组元素;字符串文字不用作单位。此对象具有动态初始化,从而导致在运行时加载值。

The third, an argument to the puts() call, actually does use the string literal as an expression, and it will have type const char[N], which decays to const char* for the call. If you really want to study object code used to handle the runtime type of a string literal, you should be using the literal in an expression, like this function call does.

第三个是puts()调用的参数,实际上确实使用字符串文字作为表达式,它将具有类型const char [N],它将衰减为const char *用于调用。如果你真的想学习用于处理字符串文字的运行时类型的目标代码,你应该在表达式中使用文字,就像这个函数调用一样。

#2


21  

It does conform to the standard, under the "as-if" rule.

它符合“as-if”规则下的标准。

Since the only thing that the string literal is ever used for is to initialize cstring, there is no need for any object representation for it. The compiler has eliminated it in favour of initializing cstring by an alternative means that has equivalent results, but that the compiler decides is better in some respect (speed or code size).

由于字符串文字的唯一用途是初始化cstring,因此不需要任何对象表示。编译器已经取消了它,有利于通过具有相同结果的替代方法初始化cstring,但编译器在某些方面(速度或代码大小)决定更好。

#3


0  

I think the definition you cite has to be interpreted as referring to string literals whose storage location is not explicitly declared, such as the format expression in a printf(). In order for such code to work, those string literals have to be stored somewhere; the definition specifies where they are stored if that cannot be inferred from context.

我认为您引用的定义必须解释为引用其存储位置未显式声明的字符串文字,例如printf()中的格式表达式。为了使这样的代码有效,那些字符串文字必须存储在某个地方;如果无法从上下文中推断出定义,则定义指定它们的存储位置。

On a side note: The string literal in your main() doesn't appear as static data because variables declared in functions are 'automatic' by default. If you had instead written static char cstring[]=... then you would have seen it in the same place as cstring1[].

注意:main()中的字符串文字不会显示为静态数据,因为函数中声明的变量默认为“自动”。如果您改为编写静态char cstring [] = ...那么您可能会在与cstring1 []相同的位置看到它。

And another thing: Storage location IS NOT part of the data type!

另一件事:存储位置不是数据类型的一部分!

#1


8  

Expressions have type. String literals have type if they are used as an expression. Yours isn't.

表达式有类型。字符串文字如果用作表达式,则具有类型。你的不是。

Consider the following code:

请考虑以下代码:

#include <stdio.h>

#define STR "HelloHelloHello"

char global[] = STR;

int main(void)
{
    char local[] = STR;
    puts(STR);
}

There are three string literals in this program formed using the same tokens, but they are not treated the same.

此程序中有三个字符串文字使用相同的标记形成,但它们的处理方式不同。

The first, the initializer for global, is part of static initialization of an object with static lifetime. By section 3.6.2, static initialization doesn't have to take place at runtime; the compiler can arrange for the result to be pre-formatted in the binary image so that the process starts execution with the data already in place, and it has done so here. It would also be legal to initialize this object in the same fashion as local[], as long as it was performed before the beginning of dynamic initialization of globals.

第一个是global的初始化器,是具有静态生存期的对象的静态初始化的一部分。根据3.6.2节,静态初始化不必在运行时进行;编译器可以安排在二进制映像中预先格式化结果,以便进程在已经存在的数据的情况下开始执行,并且在此处已完成。以local []的方式初始化此对象也是合法的,只要它在全局变量动态初始化之前执行即可。

The second, the initializer for local, is a string literal, but it isn't really an expression. It is handled under the special rules of 8.5.2, which states that the characters within the string literal are independently used to initialize the array elements; the string literal is not used as a unit. This object has dynamic initialization, resulting in loading the value at runtime.

第二个是local的初始化器,是一个字符串文字,但它实际上不是表达式。它是根据8.5.2的特殊规则处理的,该规则规定字符串文字中的字符独立用于初始化数组元素;字符串文字不用作单位。此对象具有动态初始化,从而导致在运行时加载值。

The third, an argument to the puts() call, actually does use the string literal as an expression, and it will have type const char[N], which decays to const char* for the call. If you really want to study object code used to handle the runtime type of a string literal, you should be using the literal in an expression, like this function call does.

第三个是puts()调用的参数,实际上确实使用字符串文字作为表达式,它将具有类型const char [N],它将衰减为const char *用于调用。如果你真的想学习用于处理字符串文字的运行时类型的目标代码,你应该在表达式中使用文字,就像这个函数调用一样。

#2


21  

It does conform to the standard, under the "as-if" rule.

它符合“as-if”规则下的标准。

Since the only thing that the string literal is ever used for is to initialize cstring, there is no need for any object representation for it. The compiler has eliminated it in favour of initializing cstring by an alternative means that has equivalent results, but that the compiler decides is better in some respect (speed or code size).

由于字符串文字的唯一用途是初始化cstring,因此不需要任何对象表示。编译器已经取消了它,有利于通过具有相同结果的替代方法初始化cstring,但编译器在某些方面(速度或代码大小)决定更好。

#3


0  

I think the definition you cite has to be interpreted as referring to string literals whose storage location is not explicitly declared, such as the format expression in a printf(). In order for such code to work, those string literals have to be stored somewhere; the definition specifies where they are stored if that cannot be inferred from context.

我认为您引用的定义必须解释为引用其存储位置未显式声明的字符串文字,例如printf()中的格式表达式。为了使这样的代码有效,那些字符串文字必须存储在某个地方;如果无法从上下文中推断出定义,则定义指定它们的存储位置。

On a side note: The string literal in your main() doesn't appear as static data because variables declared in functions are 'automatic' by default. If you had instead written static char cstring[]=... then you would have seen it in the same place as cstring1[].

注意:main()中的字符串文字不会显示为静态数据,因为函数中声明的变量默认为“自动”。如果您改为编写静态char cstring [] = ...那么您可能会在与cstring1 []相同的位置看到它。

And another thing: Storage location IS NOT part of the data type!

另一件事:存储位置不是数据类型的一部分!