5007holic 发表于 2023-3-29 19:13

【C语言】无符号和有符号转换

最近做了个笔试题
int main(int argc, char const *argv[])
{
    unsigned int a = 6;
    int b = -20;

    char c;
    (a + b > 6 ) ? (c = 1) : (c = 0);
    return 0;
}
问:则c等于多少?
c = 1是毋庸置疑的,但我查阅大量资料,包括C99标准文档,都说是无符号整形和有符号整型相加时,有符号转为无符号运算。
这样算下来a+b是4294967282。
但我们老师这样说的无符号+有符号= 有符号,有符号数与无符号数(6)比较时会转成无符号,-14与6比较时会转换成14。
so,我就很迷惑。
请大佬解答

侃遍天下无二人 发表于 2023-3-29 19:23

本帖最后由 侃遍天下无二人 于 2023-3-29 19:47 编辑

这种咋实现要是C标准中没规定那就和具体的编译器有关了,你弄成反汇编看看,一会我上传我这边的结果

.text:0000000000401550                               ; int __cdecl main(int argc, const char **argv, const char **envp)
.text:0000000000401550                               public main
.text:0000000000401550                               main proc near                        ; CODE XREF: __tmainCRTStartup+242↑p
.text:0000000000401550                                                                     ; DATA XREF: .pdata:000000000040506C↓o
.text:0000000000401550
.text:0000000000401550                               c= byte ptr -9
.text:0000000000401550                               b= dword ptr -8
.text:0000000000401550                               a= dword ptr -4
.text:0000000000401550                               argc= dword ptr10h
.text:0000000000401550                               argv= qword ptr18h
.text:0000000000401550
.text:0000000000401550 55                            push    rbp
.text:0000000000401551 48 89 E5                      mov   rbp, rsp
.text:0000000000401554 48 83 EC 30                   sub   rsp, 30h
.text:0000000000401558 89 4D 10                      mov   , ecx
.text:000000000040155B 48 89 55 18                   mov   , rdx
.text:000000000040155F E8 EC 00 00 00                call    __main
.text:000000000040155F
.text:0000000000401564 C7 45 FC 06 00 00 00          mov   , 6
.text:000000000040156B C7 45 F8 EC FF FF FF          mov   , 0FFFFFFECh
.text:0000000000401572 8B 55 F8                      mov   edx,
.text:0000000000401575 8B 45 FC                      mov   eax,
.text:0000000000401578 01 D0                         add   eax, edx
.text:000000000040157A 83 F8 06                      cmp   eax, 6
.text:000000000040157D 76 06                         jbe   short loc_401585
.text:000000000040157D
.text:000000000040157F C6 45 F7 01                   mov   , 1
.text:0000000000401583 EB 04                         jmp   short loc_401589
.text:0000000000401583
.text:0000000000401585                               ; ---------------------------------------------------------------------------
.text:0000000000401585
.text:0000000000401585                               loc_401585:                           ; CODE XREF: main+2D↑j
.text:0000000000401585 C6 45 F7 00                   mov   , 0
.text:0000000000401585
.text:0000000000401589
.text:0000000000401589                               loc_401589:                           ; CODE XREF: main+33↑j
.text:0000000000401589 B8 00 00 00 00                mov   eax, 0
.text:000000000040158E 48 83 C4 30                   add   rsp, 30h
.text:0000000000401592 5D                            pop   rbp
.text:0000000000401593 C3                            retn
.text:0000000000401593
.text:0000000000401593                               main endp

重点关注这几行:
.text:0000000000401564 C7 45 FC 06 00 00 00          mov   , 6
.text:000000000040156B C7 45 F8 EC FF FF FF          mov   , 0FFFFFFECh
.text:0000000000401572 8B 55 F8                      mov   edx,
.text:0000000000401575 8B 45 FC                      mov   eax,
.text:0000000000401578 01 D0                         add   eax, edx
.text:000000000040157A 83 F8 06                      cmp   eax, 6

其中在 add   eax, edx之前,变量只在不同寄存器之间传递过,没有做任何处理,所以相加的时候也是两个数做补码运算,结果是 6-20=-14 的补码,自然不可能大于6了
另外无符号的意思不是把负号去掉,是把原有的符号位视为数

侃遍天下无二人 发表于 2023-3-29 19:48

给个建议,你们老师要是不能从反汇编证明自己的结论你就趁早换班,山寨的名师很多的

only998 发表于 2023-3-29 19:53

char在不同的平台有不同的规定,有些是有符号的,有些是无符号的。

飘零星夜 发表于 2023-3-29 20:00

我手头只有CPU12,编译代码如下,证明楼主是对的。
...
ldaa #$ec
ldab #6
psha
pshb
addb 1,sp
cmpb 0,sp
ldab #1
bcc pc+2
ldab #0
...

破凤凰 发表于 2023-3-29 20:12

这是不是垃圾题!?

okboy 发表于 2023-3-29 20:15

jokerkun 发表于 2023-3-29 20:56

正在学C,有问题还需要求助于各位大佬:lol

熊猫拍板砖 发表于 2023-3-30 02:38

基本的类型转换规则。
1.当类型转换出现在表达式时,无论是unsigned还是signed的char和short都会被自动转换成int,如有必要会被转换成unsigned int(如果short与int的大小相同,unsigned short就比int大。这种情况下,unsigned short会被转换成unsigned int)。在K&R那时的C中,float会被自动转换成double(目前的C不是这样)。由于都是从较小类型转换为较大类型,所以这些转换被称为升级(promotion)。
2.涉及两种类型的运算,两个值会被分别转换成两种类型的更高级别。
3.类型的级别从高至低依次是long double、double、float、unsignedlong long、long long、unsigned long、long、unsigned int、int。
页: [1] 2
查看完整版本: 【C语言】无符号和有符号转换