“可表示”在C11中意味着什么?

根据C11 WG14草案版本N1570 :

头文件声明了几个对字符分类和映射有用的函数。 在所有情况下,参数都是一个int ,其值应表示为unsigned char或者等于宏EOF的值。 如果参数具有任何其他值,则行为未定义。

是不确定的行为?:

 #include  #include  #include  int main(void) { char c = CHAR_MIN; /* let assume that char is signed and CHAR_MIN < 0 */ return isspace(c) ? EXIT_FAILURE : EXIT_SUCCESS; } 

标准是否允许将char传递给isspace()charint )? 换句话说,转换为int后的unsigned char是否可表示unsigned char


以下是wiktionary定义“可表示”的方式 :

能够代表。

char是否能够表示为unsigned char是的 §6.2.6.1/ 4:

存储在任何其他对象类型的非位字段对象中的值由n × CHAR_BIT位组成,其中n是该类型对象的大小(以字节为单位)。 可以将该值复制到unsigned char [ n ]类型的对象中(例如,通过memcpy ); 生成的字节集称为值的对象表示

sizeof(char) == 1因此它的对象表示是unsigned char[1]char能够表示为unsigned char 。 我哪里错了?

具体例子,我可以将[-2, -1, 0, 1][0, 1, 2, 3] 。 如果我不能那么?


相关:根据§6.3.1.3,如果INT_MAX >= UCHAR_MAX ,则isspace((unsigned char)c)是可移植的,否则它是实现定义的。

char签名的假设下,这将是未定义的行为 ,否则它被很好地定义,因为CHAR_MIN将具有值0 。 更容易看出以下内容的意图和含义:

其值应表示为无符号字符或等于宏EOF的值

如果我们从国际标准 – 编程语言的基本原理 – C中读到第7.4字符处理强调我的未来 ):

由于这些函数通常主要用作宏,因此它们的域仅限于无符号字符中可表示的小正整数加上EOF的值 。 EOF传统上是-1,但可以是任何负整数,因此可以与任何有效的字符代码区分开。 因此,通过将参数用作小数组属性的索引,可以有效地实现这些宏。

所以有效值是:

  1. 正整数,可以放入unsigned char
  2. EOF是一些实现定义的负数

即使这是C99的基本原理,因为您所指的特定措辞不会从C99改为C11 ,因此理由仍然适用。

我们还可以找到为什么接口使用int作为参数而不是char ,从7.1.4使用库函数 ,它说:

所有库原型都是根据“加宽”类型指定的以前声明为char的参数现在写为int。 这确保了可以在范围内使用或不使用原型来调用大多数库函数 ,从而保持与C89之前代码的向后兼容性 。 但请注意,由于printf和scanf等函数使用可变长度参数列表,因此必须在原型范围内调用它们。

类型中可表示什么意思?

重新制定,类型是基础位模式意味着什么的约定。 因此,值可以在类型中表示,如果该类型指定了某种意义的位模式。

转换(可能需要转换)是从值(用特定类型表示)到目标类型中表示的值(可能不同)的映射。


在给定的假设下( char已签名), CHAR_MIN肯定是否定的,并且您引用的文本没有留下解释的余地​​:
是的,它是未定义的行为,因为unsigned char不能代表任何负数。

如果该假设不成立,那么您的程序将被很好地定义,因为CHAR_MIN将为0 ,这是unsigned char的有效值。

因此,我们有一个案例,它是实现定义的程序是未定义的还是定义良好的。


另外,不能保证sizeof(int)>1INT_MAX >= CHAR_MAX ,因此int可能无法表示unsigned char可能的所有值。

由于转换被定义为保留值,因此有符号的char总是可以转换为int
但如果它是否定的,那就不会改变将负值表示为unsigned char不可能性。 (定义转换,因为始终定义从任何整数类型到任何unsigned整数类型的转换,但缩小转换需要转换。)

揭示引言(对我来说)是§6.3.1.3/ 1:

如果值可以由新类型表示,则不会更改。

即,如果必须更改该值,则该值不能由新类型表示。

因此, unsigned类型不能表示负值。

回答标题中的问题:“可表示”是指“可以表​​示”来自§6.3.1.3,与“对象表示”无关,来自§6.2.6.1。

回想起来似乎微不足道。 我可能会因为习惯将b'\xFF'0xff255-1视为Python中的相同字节而感到困惑:

 >>> (255).to_bytes(1, 'big') b'\xff' >>> int.from_bytes(b'\xFF', 'big') 255 >>> 255 == 0xff True >>> (-1).to_bytes(1, 'big', signed=True) b'\xff' 

并且不相信将字符传递给字符分类函数(例如, isspace(CHAR_MIN) 是未定义的行为