C 转换为‘;无符号字符’;从‘;int’;可能会改变它的价值

C 转换为‘;无符号字符’;从‘;int’;可能会改变它的价值,c,gcc,casting,C,Gcc,Casting,在没有显式(=丑陋)强制转换的情况下,如何删除以下代码中由gcc-Wconversion生成的警告: 有没有办法告诉编译器,显然强制转换是在(%65536)/256或%256期间隐式完成的 供参考 $ gcc -Wconversion w.c w.c: In function ‘main’: w.c:4:36: warning: conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion] w.c:5:36

在没有显式(=丑陋)强制转换的情况下,如何删除以下代码中由
gcc-Wconversion
生成的警告:

有没有办法告诉编译器,显然强制转换是在
(%65536)/256
%256
期间隐式完成的

供参考

$ gcc -Wconversion w.c
w.c: In function ‘main’:
w.c:4:36: warning: conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
w.c:5:36: warning: conversion to ‘unsigned char’ from ‘int’ may alter its value [-Wconversion]
使用静态强制转换(或将结果强制转换为无符号字符)

这将减少警告,因为它本质上告诉编译器,“等等,我是有意这么做的”

如果您不打算真正使用带符号的值,那么您应该从以下几点开始:

unsigned int val;
而不是:

int val;

即使这样做,您也需要将unsigned int转换为unsigned char,因为编译器最终仍会认为您并不是有意按原来的方式进行下转换。

这是因为int是有符号的,char不是,如果int是负值,这可能会导致混淆。只需在文本附近添加U并将unsigned添加到int,您还可以修复代码,因为实际上val从-32768变为32767(有符号),而不是从0变为65536(无符号)

听起来您需要这些结果:

c1 = (val >> 8) & 0xff;
c2 = val & 0xff;
编辑

从gcc维基:
Wconversion

警告可能改变值的隐式转换。这包括实数和整数之间的转换,如x为双精度时的abs(x);有符号和无符号之间的转换,如无符号ui=-1;以及转换为更小的类型,如sqrtf(M_-PI)。对于诸如abs((int)x)和ui=(unsigned)-1之类的显式强制转换,或者如果值没有像abs(2.0)中那样通过转换进行更改,则不要发出警告。使用-Wno sign conversion可以禁用有关有符号整数和无符号整数之间转换的警告。对于C++,还警告NULL和非指针类型之间的转换;混淆用户定义转换的重载解析;以及永远不会使用类型转换运算符的转换:转换为void、相同类型、基类或对它们的引用。在C++中默认情况下禁用关于符号和无符号整数之间的转换的警告,除非明确启用了-WSCONE转换。p>
如果val是未签名的,则不会出现警告,但您必须确定要获得负值的值。

警告告诉您,并非所有情况下都定义了您要执行的操作。如果
val
为负数,''%1!'可能返回负数结果,并且未定义将其指定为
无符号字符。另见


请确保
val
永远不为负值,并与警告保持一致(每次未更改时都进行检查!),或者声明它为
unsigned int

,顺便说一句,
unsigned char c2=val%256在第二种情况下就足够了。此警告的全部目的是警告您,您已经执行了一个有风险的隐式强制转换,所以要消除此警告,请使用显式强制转换。当然仍然有潜在的风险,但编译器会耸耸肩,认为您知道得最好。:)它们都很重要,但是:
正确性>清晰性>风格
“没有难看的演员阵容:“@janisz”没有难看的演员阵容”将比“难看的”演员阵容更难看。这是向知情的读者和编译器解释这种类型变化所需要的。@janisz-我愿意接受一些建议,你认为在某个时间点,如果不使用强制转换,这将如何实现。事实上,C是一种相当强类型的语言,因此,如果您要从一个更高的位宽度的数字转换为一个更小的位宽度的数字,则需要一个强制转换。@rubenvb我同意,它的可读性可能会降低,问题是如何在没有casting@janisz-我也明白你的意思,但我认为“没有演员阵容”是在我回答:-)之后添加的,在这种情况下,Kiwi的答案可能是最正确的,并且使用“-Wno符号转换”编译器开关。这将在数学上给出相同的结果,但是我不确定它本身是否会消除警告。由于val仍然是int,编译器将把常量8和0xff视为int值,而不是无符号字符。在这些情况下,它将始终默认为最大的位宽度类型,而不是最小的。事实上,我将确保使用unsigned int。如果您想阅读自己的文章和引用,它实际上会声明将抛出警告“并转换为较小的类型”。我仍然无法识别这是如何回答OPs问题的,您的代码仍然会抛出警告。简单地将其更改为unsigned仍然不能消除从32位值到8位值的转换。@trumpetlicks我尝试过,但没有得到警告,这就是使用
0xff
@trumpetlicks进行掩蔽的全部意义-这也会抑制带有
叮当声的警告,即使使用非常严格的
-Weverything
标志。这完全正确,但我还是觉得奇怪。我更希望演员阵容的确定性。这不是书法。在C语言中,普通的
char
可以是有符号的,也可以是无符号的,这取决于实现的随意性。和有符号整数也不能保证用2的补码表示。分配给无符号类型不是未定义的。
int val;
c1 = (val >> 8) & 0xff;
c2 = val & 0xff;