C++ 实现定义的行为和读取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)。 但字

我有两个问题,一个小问题,所以我会一起问。 实现定义的行为是否与未定义的行为一样危险

我使用以下代码从文件中读取了一些unicode字符串:

 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只有在执行算术运算时才会发生有符号整数溢出。你不是在做算术。