将整数转换为字符的C语言公式

3
int num = 65537;
char p = (char)num; //char = 1;

这里在进行什么操作? 是 p=num%(127+128)-1 还是 p=num%256 或者其他操作? 我需要知道为什么 p 等于 1。 谢谢!


1
我的问题更多的是:为什么你的编译器没有报错?'i' 没有初始化! - Rizier123
乍一看,pnum毫无关系,而是一个未显示的值i。打错字了吗? - Edward Thomson
在这种情况下,很可能是“num%256”。 - Floris Velleman
2个回答

6

由于65537在二进制中是00000000 00000001 00000000 00000001,但char类型只有1个字节,因此最后一个字节被视为char值,即00000001=1


这个答案基本上是正确的(只需删除“不确定”并修复最左边的3个字节值)。 - barak manos
请注意,这是实现定义的(即C标准不强制规定此行为)。 - M.M

3
简短回答:在标准处理器上,实际上结果为1,因为65537 % 256 == 1。原因是ksmonkey123解释的。
注意:如果你正在写127 + 128是因为一个signed char的边界,这相当于目前典型编译器上的char,其值范围为-128到+127,请记住-128到+127之间的值数是(127-(-128)+1),也得到256,所以无论你使用signed char的边界(-128到127)还是unsigned char的边界(0到255),结果都不会发生改变。
挑剔一点:实际上,给一个不能被表示为有符号目标变量的值赋值会导致未定义行为,并且根据C标准,所有可能性都存在。
将一个不能容纳的正值赋给一个unsigned变量会产生“模范围”行为,例如如果字符具有8位,则对于unsigned chars为“%256”。将负值赋给unsigned变量将导致三种可能的行为,由标准定义。实现必须描述该实现所使用的行为。现在所有非嵌入式的C编译器都像将2的N次幂(其中N是目标类型的位数)的倍数添加到该值中一样。因此,将“-510”加2*256得到+2,然后将此+2存储在变量中。

1
第一:类型转换对生成的代码没有影响。编译器非常清楚目标是一个 char 变量,因此必须将值转换为 char。类型转换只是将隐式转换变为显式转换,而不改变行为。许多编译器会对隐式缩小转换发出警告(因为您可能会意外损失精度),而对于显式转换则保持沉默(因为您明确要求损失精度)。第二:关于未定义的事实,在 C11 的最终草案方面,我的说法实际上是错误的。 - Michael Karcher
1
C11最终草案的6.3.1.3节规定,在这种情况下,行为是一个实现定义的值(“算法”必须有文件记录并保持一致),或者导致实现定义的信号。这与C99没有改变(http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf)。 - Michael Karcher
所以它是已定义还是未定义的? - Xiobiq
1
使用强制类型转换或不使用强制类型转换是“实现定义”的。因此,标准兼容的C编译器的作者必须记录在这种情况下会发生什么,并且必须始终遵循该文档。例如,对于gcc,请查看此处:https://gcc.gnu.org/onlinedocs/gcc-4.7.3/gcc/Integers-implementation.html。他们明确指出,有符号变量中的值与原始存储值之间的差异是2 ^ N的倍数,其中N是目标变量中的位数。这就是他们所说的“模2 ^ N减少”。 - Michael Karcher
让我们在聊天中继续这个讨论 - Xiobiq
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接