Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/69.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 将整型截断为字符-是否定义了整型?_C_Bitwise Operators_Integer Promotion - Fatal编程技术网

C 将整型截断为字符-是否定义了整型?

C 将整型截断为字符-是否定义了整型?,c,bitwise-operators,integer-promotion,C,Bitwise Operators,Integer Promotion,静态分析器抱怨最后一行被截断,可能是因为b在其位翻转之前被提升为int,结果将是int类型 我只对提升的int的最后一个字节感兴趣-如果b是0x55,我需要a是0xAA。我的问题是,C规范是否说明了截断是如何发生的,或者它是实现定义的/未定义的?是否保证a始终被分配我期望的值,或者在一致性平台上是否会出错 当然,在分配之前强制转换结果将使静态分析器静音,但我想知道,首先忽略此警告是否安全。它将按照您希望的方式运行。可以安全地转换值。以Win32机器为例。 整数是4个字节,将其转换为字符的结果将与

静态分析器抱怨最后一行被截断,可能是因为
b
在其位翻转之前被提升为int,结果将是int类型

我只对提升的int的最后一个字节感兴趣-如果
b
是0x55,我需要
a
是0xAA。我的问题是,C规范是否说明了截断是如何发生的,或者它是实现定义的/未定义的?是否保证
a
始终被分配我期望的值,或者在一致性平台上是否会出错


当然,在分配之前强制转换结果将使静态分析器静音,但我想知道,首先忽略此警告是否安全。

它将按照您希望的方式运行。可以安全地转换值。

以Win32机器为例。
整数是4个字节,将其转换为字符的结果将与删除了剩余的3个字节的结果完全相同

当您将一个字符转换为另一个字符时,它被提升为什么并不重要。
~b将在左侧添加3个字节,将0更改为1,然后删除。。。它不会影响您的一个右字节。

相同的概念将适用于不同的体系结构(无论是16位还是64位机器)


假设它是little endian,C标准为无符号类型指定了这一点:

涉及无符号的计算 操作数永远不会溢出,因为 无法用表示的结果 生成的无符号整数类型为 一个数的约化模 大于指定的最大值 可以由结果 类型

在这种情况下,如果
无符号字符
为8位,则意味着结果将以256模减少,这意味着如果
b
0x55
a
将最终成为
0xAA

但是请注意,如果
unsigned char
大于8位(这是完全合法的),您将得到不同的结果。为了确保您将可移植地获得
0xAA
,您可以使用:

unsigned char a, b;
b = something();
a = ~b;
(应在
无符号字符
为8位的平台上优化按位和)


还请注意,如果使用有符号类型,则结果是实现定义的。

截断操作如本手册6.3.1.3/2所述

。。。如果新类型是无符号的,则通过重复地将新类型中可以表示的最大值加上或减去一个值来转换该值,直到该值在新类型的范围内


字符位==8,sizeof(无符号字符)==1,sizeof(int)==4的示例

因此,0x55转换为
int
,再转换为0x00000055,然后求反为0xffffaa,并且

0xFFFFA +0x00000100/*UCHAR_最大值+1*/ ------------ 0xFFFFFEAA ... 重复很多很多次。。。 0x000000AA
或者,正如您所期望的那样,这个特定的代码示例是安全的。但是有理由警告不要不小心使用~operator

这背后的原因是,在更复杂的表达式中,~on小整数变量是一个潜在的bug,因为C中有隐式整数提升。想象一下,如果您有一个类似

a=~b>>4

它不会像预期的那样在零中移动


如果您的静态分析器设置为包含MISRA-C,例如,您将为每个~运算符收到此警告,因为在这种情况下,MISRA强制将小整数类型上的任何操作的结果显式类型转换为预期类型,即无符号字符

我担心的不是溢出(因为这里的运算符是
~
)-将0xFFFFA截断为字符会导致0xFF(msb)而不是0xAA(lsb)?不,缩减总是“模2^n”操作,其中n是字符中的位数。Endianness没有matter@Amarghosh否,它将使用无尾数的最低有效字节。@Amarghosh:“因为无法表示结果…”中的引号部分仍然相关。由于值
0xFFFFAA
不能表示为8位
无符号字符
,它将被减少为256模-这将导致
0xAA
。使用
uint8\u t
实际上没有帮助,因为除非
字符位
为8,否则它不存在。只要使用
#if
#error
就可以了。我想在这里写下这个概念。。。假设它是32位机器。。。就概念而言,64位机器或不同的架构不会有任何区别。3@Mayank:为了将来可能阅读您答案的其他SO用户的利益,重要的是它不包含misinformation@Paul:谢谢你的评论。我以后会处理的future@Mayank:您可以编辑以上答案,使其更准确、更全面applicable@Mayank当前位置这样好一点-我会删除关于小端点的最后一行,因为它不相关。我会说这是一个虚假的警告。我刚刚通过铿锵静态分析器运行了您的代码,它没有抱怨。
something()
@Jeremy的返回类型是什么?这是一个示例代码来说明该场景。真正的代码类似于
mask1[0]=~mask2[0]其中两个都是类型为unsigned char的数组。显然,我的静态分析器没有叮当声那么聪明:)呃。。。这个例子是相当错误的LOL,但你得到的想法:)
a = ~b & 0xff;
0xFFFFFFAA + 0x00000100 /* UCHAR_MAX + 1 */ ------------ 0xFFFFFEAA ... repeat lots and lots of times ... 0x000000AA