1

最近的 C 标准规定对于printf("%s",p)

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

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

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

4

2 回答 2

10

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

因此,“字符类型”的数组将包含这 3 个。

const, volatile, 和restrict是各种类型的限定符,属于同一类型类别。他们也适用。

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

于 2013-09-13T14:25:25.127 回答
3

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

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

如果你写%ls,参数必须兼容wchar_t[],否则为char[]

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

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

于 2013-09-13T14:30:46.037 回答