根据C11 WG14 draft version N1570:
标题
<ctype.h>
声明了几个对分类有用的函数 和映射字符。在所有情况下,参数都是int
其价值应表示为unsigned char
或应当 等于宏EOF
的值。如果参数有任何其他值, 行为未定义。
是不确定的行为?:
#include <ctype.h>
#include <limits.h>
#include <stdlib.h>
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()
(char
到int
)?换句话说,转换为char
可表示后int
是unsigned char
吗?
以下是wiktionary defines "representable":
的方式能够被代表。
char
是否能够表示为unsigned char
? 是即可。 §6.2.6.1/ 4:
存储在任何其他对象类型的非位字段对象中的值 由 n
×
CHAR_BIT
位组成,其中 n 是该对象的大小 type,以字节为单位。该值可以复制到类型的对象中 unsigned char [ n ](例如, memcpy );得到的字节集是 称为值的对象表示。
sizeof(char) == 1
因此其对象表示为unsigned char[1]
,即char
能够表示为unsigned char
。我哪里错了?
具体示例,我可以将[-2, -1, 0, 1]
表示为[0, 1, 2, 3]
。如果我不能为什么呢?
相关:根据§6.3.1.3isspace((unsigned char)c)
INT_MAX >= UCHAR_MAX
是可移植的,否则它是实现定义的。
答案 0 :(得分:10)
类型中可表示什么意思?
重新表述,类型是底层位模式的含义。因此,值可以在类型中表示,如果该类型指定了某种意义上的位模式。
转换(可能需要转换)是从值(用特定类型表示)到目标类型中表示的值(可能不同)的映射。
根据给定的假设(char
已签名),CHAR_MIN
肯定是否定的,您引用的文字不会留下解释的余地:
是的,它是未定义的行为,因为unsigned char
不能代表任何负数。
如果该假设不成立,您的程序将被明确定义,因为CHAR_MIN
将是0
,unsigned char
的有效值。
因此,我们有一个案例,它是实现定义的程序是未定义的还是定义良好的。
另外,我们无法保证sizeof(int)>1
或INT_MAX >= CHAR_MAX
,因此int
可能无法代表unsigned char
可能的所有值。
由于转化被定义为保留价值,因此签名的char
始终可以转换为int
。
但如果它是否定的,那就不会改变将负值表示为unsigned char
的不可能性。 (定义转换,因为始终定义从任何整数类型到任何unsigned
整数类型的转换,但缩小转换需要转换。)
答案 1 :(得分:4)
假设 char 是签名,那么这将是undefined behavior,否则它定义得很好,因为CHAR_MIN
将具有值{ {1}}。更容易看出:
其值应表示为unsigned char或shall 等于宏EOF的值
如果我们从Rationale for International Standard—Programming Languages—C中读到0
字符处理&lt; ctype.h&gt; ,那么(强调我的前进):
由于这些功能通常主要用作宏,他们的域 仅限于可表示的小正整数 unsigned char,加上EOF的值。 EOF传统上是-1,但可能 是任何负整数,因此可以区别于任何有效 字符代码。因此,可以有效地实现这些宏 使用参数作为一小部分属性的索引。
所以有效值是:
答案 2 :(得分:1)
揭示性引用(对我来说)是§6.3.1.3/ 1:
如果值可以用新类型表示,则不变。
即,如果必须更改该值,则该值不能用新类型表示。
因此,unsigned
类型不能代表负值。
回答标题中的问题:“可表示”是指“可以用§6.3.1.3表示”,与§6.2.6.1中的“对象表示”无关。
回想起来似乎微不足道。我可能会对将b'\xFF'
,0xff
,255
,-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)
。