【问题标题】:char array initialization with octal constant用八进制常量初始化字符数组
【发布时间】:2018-07-30 17:57:48
【问题描述】:

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

未编辑的评论:

字符输入[SIZE] = "";是足够的初始化。如果你已经初始化了 input[SIZE] = "\001"; while ( '\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?

【问题讨论】:

  • 我会说引用的评论是错误的。
  • \0 本身 产生一个 NUL,但标准行为是 \001 产生一个数值为 1 的字符,正如您所观察到的。 (一般规则是反斜杠后跟一个、两个或三个八进制数字是单个转义。)请引用我们您看到的完整且未经编辑的实际评论,至少有五行上面和下面的上下文,如果可能,请提供指向您引用的整个程序的链接。
  • '\001'"\001"有区别
  • @SaeidYazdani 但这里并不真正相关
  • 是的,@SaeidYazdani,OP 给出了理解这一点的所有迹象。

标签: c octal


【解决方案1】:

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

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

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

(C2011, 6.4.4.4/7)

在这种情况下,\0 是一个八进制转义序列,而不是空字符的特殊独立代码,这一点也很重要。上述引文的更广泛背景将说明这一点。

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

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

"\00001"

或者像这样拆分:

"\0" "01"

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

【讨论】:

    【解决方案2】:

    我看到一条评论说,用“\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 的字符。

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

    【讨论】:

    • 最重要的部分是未引用的port70.net/~nsz/c/c11/n1570.html#6.4.4.4p7
    • 这就是我最后一段的解释,是的。 (我不想将 hexadecimal-escape-sequence 的正式“泄露”规范拖入其中。)
    • The definition -- both for integer constants as well as character constants -- is "greedy" - 这是maximal munch rule的一个例子吗?
    • @ArkadiuszDrabczyk:我实际上不确定 C 语法定义 作为一个整体 是否意味着贪婪;在我知道它有所作为的地方,它在周围的文字中明确表达。
    【解决方案3】:

    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 处不应有空字节。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-10
      • 1970-01-01
      • 2011-05-15
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-25
      相关资源
      最近更新 更多