具有八进制常量的char数组初始化

时间:2018-07-30 17:57:49

标签: c octal

我看到一条评论,说用"\001"初始化char数组会将nul作为第一个字符。我已经看到\0在哪里设置了nul。

未编辑的评论:

  

字符输入[SIZE] =“”;足够的初始化。如果您已初始化input [SIZE] =“ \ 001”,则('\ 001'== input [0])不会执行您认为的操作; (它将创建一个以nul字符作为第一个字符的空字符串。)

该程序

#include <stdio.h>
#define SIZE 8
int main ( void) {
    char input[SIZE] = "\001";

    if ( '\001' == input[0]) {//also tried 1 == input[0]
        printf ( "octal 1\n\n");
    }
    else {
        printf ( "empty string\n");
    }
    return 0;
}

在Linux上运行并用gcc编译,输出:

octal 1

因此第一个字符是1而不是'\0'
这是标准行为还是Linux和gcc的某些行为?为什么不设置nul?

3 个答案:

答案 0 :(得分:3)

  

我看到一条评论,说用“ \ 001”初始化char数组会将nul作为第一个字符。

该评论有误。

来自 6.4.4.1整数常量,第3段,重点是:

  

八进制常量由前缀0 组成,可选地,其后是仅数字0到7的序列。

但是我们在这里看到的根本不是整数常量。实际上,我们这里是一个八进制转义序列。定义如下(在 6.4.4.4字符常量中):

octal-escape-sequence:
        \ octal-digit
        \ octal-digit octal-digit
        \ octal-digit octal-digit octal-digit

如第7段所述,整数常量和字符常量的定义都是“贪婪的”:

  

每个八进制或十六进制转义序列是可以构成转义序列的最长字符序列。

这意味着,如果第一个八进制数字后跟可能是八进制数字,则表示下一个字符被视为属于该常数的八进制数字(对于字符常量,最多为三个-对于整数常量,则不是这样!)。

因此,您的"\001"实际上是一个值为1的字符。

请注意,虽然 octal 字符常量最多可以运行三个字符(如果需要使用前导零填充该常量以获得三位数的长度,则使该常量使用非常安全),只要有十六进制数字(可能会溢出它们打算初始化的char类型),>十六进制字符常量就可以运行。

答案 1 :(得分:3)

  

这是标准行为还是Linux和gcc的某些行为?为什么不设置nul?

您提供的代码的行为符合标准要求。在字符串文字和整数字符常量中,八进制转义都可以包含一位,两位或三位数字,并且C标准指定

  

每个八进制转义序列是的最长序列   可以构成转义序列的字符。

C2011, 6.4.4.4/7

在此上下文中,另外重要的是\0是八进制转义序列,而不是用于空字符的特殊,独立代码。以上引文的更广泛的上下文将使这一点变得清楚。

在字符串文字"\001"中,反斜杠后跟三个八进制数字,并且八进制转义可以具有三个数字,因此,转义序列由反斜杠和所有三个数字组成。结果字符串的第一个字符是整数值为1的字符。

如果由于某种原因,您想要一个由空字符组成的字符串文字,其后跟十进制数字0和1,那么您可以使用完整的三位数转义符来表示空值,

"\00001"

或像这样将其拆分:

"\0" "01"

C将连接相邻的字符串文字以产生所需的结果。

答案 2 :(得分:2)

请参见http://c0x.coding-guidelines.com/6.4.4.4.html

八进制定义为:

  octal-escape-sequence:
            \ octal-digit
            \ octal-digit octal-digit
            \ octal-digit octal-digit octal-digit

和项目873:

  

八进制转义序列中反斜杠后面的八进制数字   被视为构成单个字符的一部分   整数字符常量或一个宽字符的宽字符   字符常量。

还有项目877:

  

每个八进制或十六进制转义序列是最长的序列   可以构成转义序列的字符。

因此,行为是正确的。 “ \ 001”在位置0处不应为空字节。