【问题标题】:What does “shall be a pointer to the initial element of an array of character type” mean in C99 7.19 / C11 7.21?在 C99 7.19 / C11 7.21 中,“应该是指向字符类型数组的初始元素的指针”是什么意思?
【发布时间】:2013-09-13 14:11:45
【问题描述】:

最近的 C 标准指定 printf("%s",p)

如果不存在 l 长度修饰符,则参数应为指向字符类型数组的初始元素的指针

这是否意味着p 必须与char * 兼容,还是应该以更宽松的方式解释这句话?标准的其他部分是否阐明了“字符类型数组”的确切含义?

为什么这很重要:如果该短语被严格解释为意味着 p 必须与 char * 兼容,那么一个重要的结果是 unsigned char *p; … printf("%s", p); 在编译平台上未定义,其中 @ 987654327@ 已签名,const char *p; … printf("%s", p); 未定义。

【问题讨论】:

  • 恕我直言,“字符类型数组”可能意味着 ["const", "volatile", ""]["unsigned", "signed", ""] char
  • 我不明白 const 的重要性,只有 %n 修饰符被描述为写入参数之一。
  • @Mat const-ness 可能很重要,因为 const char * 不是与 char * 兼容的类型。没关系,printf() 不写在那里。

标签: c pointers printf language-lawyer c11


【解决方案1】:

charsigned charunsigned char 这三种类型统称为字符类型。 ...
C11 6.2.5 15

所以“字符类型”的数组将包含这 3 个。

constvolatilerestrict是各种类型的限定符,属于同一类型范畴。他们也适用。

到目前为止提到的任何类型都是不合格的类型。每个非限定类型都有其类型的多个限定版本,对应于constvolatilerestrict 限定符中的一个、两个或所有三个的组合。类型的合格或不合格版本是属于同一类型类别并具有相同表示和对齐要求的不同类型。派生类型不受其派生类型的限定符(如果有)限定。
C11 6.2.5 26

【讨论】:

    【解决方案2】:

    是的,p 必须与 char 兼容。那行文字的主要目的很可能是指出 char 和 wchar_t 之间的区别。如果您在同一章(C11 7.21/7)中进一步阅读,它会变得更清楚:

    l (ell)
    "指定...以下 s 转换说明符适用 指向 wchar_t 参数的指针;"

    如果写成%ls,则参数必须与wchar_t[]兼容,否则与char[]兼容。

    至于charunsigned char正式,指向char 的指针与指向unsigned char 的指针不兼容。因此,将unsigned char* 传递给printf("%s",p) 是形式上未定义的行为。

    但是……在 C 标准之外的现实世界中,不存在不能使用 unsigned char 代替 char 来存储字符符号的情况。仅仅是因为不存在带有负索引的符号表。 ASCII、UTF8 等都从 0 开始并从那里向上计数。即使理论上这是未定义的行为,您的代码也将是 100% 可移植的

    【讨论】:

    • 请注意,“与char * 兼容”是我试图将标准内容形式化的尝试。它只说“指向字符类型数组的初始元素的指针”,这似乎允许指向 unsigned char 的指针(根据 chux 挖出的定义),尽管这与 char * 不兼容。
    猜你喜欢
    • 1970-01-01
    • 2019-12-17
    • 2021-03-22
    • 1970-01-01
    • 2021-01-04
    • 2020-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多