C++ 实现定义的行为和读取unicode到缓冲区
我有两个问题,一个小问题,所以我会一起问。 实现定义的行为是否与未定义的行为一样危险 我使用以下代码从文件中读取了一些unicode字符串:C++ 实现定义的行为和读取unicode到缓冲区,c++,c,C++,C,我有两个问题,一个小问题,所以我会一起问。 实现定义的行为是否与未定义的行为一样危险 我使用以下代码从文件中读取了一些unicode字符串: char buff[1000]; while (fgets(buf,1000, ptr_file) != NULL) printf("line: %s",buf); 我相信文件中的unicode字符是以UTF8编码保存的。 但当我检查时,每个UTF8值都超过128。然而 如您所见,该数组为char类型(表示范围-127128)。 但字
char buff[1000];
while (fgets(buf,1000, ptr_file) != NULL)
printf("line: %s",buf);
我相信文件中的unicode字符是以UTF8编码保存的。
但当我检查时,每个UTF8值都超过128。然而
如您所见,该数组为char
类型(表示范围-127128)。
但字符串打印正确。怎么搞的?我调用UB了吗?当标准声明某个东西具有实现定义的行为时,这意味着编译器编写器必须记录该东西将发生什么。该行为未定义,但在不同的实现中,该行为可能有所不同
char
的有符号性就是这样一个例子。它是由实现定义的,不管它是有符号的还是无符号的,但是编译器实现应该记录它(通常,它会提供一个开关,让您选择想要它的方式)
请注意,char
本身是一种不同于signed char
和unsigned char
的类型(与int
同义的int
)
交叉参考:
C.11:{62.5} 15和C++. 11:〈3.91} 1 . < /P> < P>回答第二个问题.我认为UTF-8编码中没有任何代码点的UB,因为参照C99最新草案<代码> 2.2.5/code >,P.3(强调雷): 声明为type
char
的对象足够大,可以存储
基本执行字符集。如果是基本执行的成员
字符集存储在char
对象中,其值保证为
必须是非负的。如果任何其他字符存储在字符
对象中,则
结果值是实现定义的,但应在
可以在该类型中表示的值的范围
这可能有助于添加fgets
函数的原型:
char*fgets(char*restrict s,int n,FILE*restrict stream)
例如,变音符号ś
在UTF-8中被编码为两个字节:C5
(197
十进制,因此它在-128..127
范围之外,假设char
的有符号变体)和9B
。它的实现定义为C5
实际上存储在char
对象中。由于UTF-8编码“产生”字节表示,因此在任何单字节范围内存储值都没有实际问题
第一个问题检查:.字符可以是有符号的,也可以是无符号的。@ShafikYaghmour:我不明白你的意思,但我认为在我的第二个问题上,它是简单的。定义的行为(在某处读取)无符号字符到有符号字符的通常转换是从大于127的每个值中减去256。这保留了两个补码机器的位模式。只要位模式保持不变,就会得到预期的行为。“实现定义”通常只是保留一个奇怪的架构以不同方式做事的权利;你不太可能遇到奇怪的架构。那么我们可以说impl定义的行为没有UB危险吗?是的,因为行为是确定性的。但是,依赖于实现定义的行为的代码不是最大可移植的。您将字节读入字符,然后将字节作为字符写出。你搞不懂什么?我写的字节是unicode,值>128。我的缓冲区是字符类型的。char的范围为:-127128只有在执行算术运算时才会发生有符号整数溢出。你不是在做算术。