- 论坛徽章:
- 2
|
回复 118# sacry
我只列关键的,更详细的你去看原文吧。
------ C89 ------
i) 6.3.6 Additive operators
If both operands have arithmetic type, the usual arithmetic conversions are performed on them.
char+char符合两个操作数都是arithmetic type,执行usual arithmetic conversions。
ii) 6.2.1.5 Usual arithmetic conversions
Many binary operators that expect operands of arithmetic type cause
conversions and yield result types in a similar way. The purpose is
to yield a common type, which is also the type of the result.
usual arithmetic conversion选择一个common type —— C被说成是弱类型的缘由之一 —— 作为操作数与结果的类型。
Otherwise, the integral promotions are performed on both operands.
Then the following rules are applied:
...
Otherwise, both operands have type int.
第1个Otherwise之前是针对有一个操作数是long double/double/float的情况。
Then 之后的又有一长串是针对有一个操作数是unsigned long,long,unsigned int说的。
iii) 6.2.1.1 Characters and integers
integral promotion:
A char, a short int, or an int bit-field, or their signed or
unsigned varieties, or an object that has enumeration type, may be
used in an expression wherever an int or unsigned int may be used. If
an int can represent all values of the original type, the value is
converted to an int; otherwise it is converted to an unsigned int.
These are called the integral promotions.
------ C99 ------
i) 6.5.6 Additive operators
4 If both operands have arithmetic type, the usual arithmetic conversions are performed on them.
ii) 6.3.1.8 Usual arithmetic conversions
Otherwise, the integer promotions are performed on both operands. Then the following rules are applied to the promoted operands:
Otherwise之前同样是说浮点。具体规则与C89不同,因为C99有个rank。
iii) 6.3.1.1 Boolean, characters, and integers
2 The following may be used in an expression wherever an int or unsigned int may be used:
— An object or expression with an integer type whose integer conversion rank is less
than the rank of int and unsigned int.
...
If an int can represent all values of the original type, the value is converted to an int;
otherwise, it is converted to an unsigned int.
These are called the integer promotions.4 All other types are unchanged by the integer promotions.
char的rank比int低。
------ 最后再来野路子 ------
我在75楼贴的代码,这里再重复贴一次:
- #include <limits.h>
- #include <string.h>
- #include <stdio.h>
- int main(int argc, char* argv[])
- {
- printf("[%d,%d]\n", CHAR_MIN, CHAR_MAX);
- if (argc>1 && strlen(argv[1])>=2)
- {
- char* p = argv[1];
- printf("%d + %d\n", p[0], p[1]);
- printf("%d\n", p[0]+p[1]);
- return 0;
- }
- return -1;
- }
复制代码 3种编译器,6种参数组合产生的汇编代码 —— 先列关键处,详细的附在后面供检阅。
- cl -W3 -O2 -FAs
- ; 12 : printf("%d\n", p[0]+p[1]);
- movsx eax, BYTE PTR [esi] ; 提升
- movsx ecx, BYTE PTR [esi+1] ; 提升
- add eax, ecx ; int + int
- push eax
- push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
- call _printf
复制代码 - cl -W3 -O2 -J -FAs
; 12 : printf("%d\n", p[0]+p[1]);
movzx eax, BYTE PTR [esi] ; 提升,符号扩展方式不同
movzx ecx, BYTE PTR [esi+1]
add eax, ecx ; int + int
push eax
push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
call _printf
[/code] - gcc -Wall -O2 -S -o -
- LC2:
- .ascii "%d\12\0" ; 最后一个printf所用的literal
- call _printf ; 中间那个printf
- movsbl (%ebx),%eax ; 提升
- movsbl 1(%ebx),%edx ; 提升
- movl $LC2, (%esp) ; 传入 "%d\n"
- addl %edx, %eax ; int + int
- movl %eax, 4(%esp) ; 传入和
- call _printf ; 最后一个printf调用
复制代码 - gcc -Wall -O2 -S -funsigned-char -o -
- LC2:
- .ascii "%d\12\0"
- call _printf
- movzbl (%ebx), %eax ; 其他同上,只有符号扩展方式不同
- movzbl 1(%ebx), %edx
- movl $LC2, (%esp)
- addl %edx, %eax
- movl %eax, 4(%esp)
- call _printf
复制代码 - clang -Wall -O2 -S -o -
- L_.str2: # @.str2
- .asciz "%d\n" ; 最后一个printf所用的literal
- calll _printf ; 中间那个printf
- movsbl (%esi), %eax ; 提升
- movsbl 1(%esi), %ecx ; 提升
- addl %eax, %ecx ; int + int
- movl %ecx, 4(%esp) ; 传入和
- movl $L_.str2, (%esp); 传入 "%d\n"
- calll _printf ; 最后一个printf调用
复制代码 - clang -Wall -O2 -funsigned-char -S -o -
L_.str2: # @.str2
.asciz "%d\n"
calll _printf
movzbl (%esi), %eax ; 其他同上,只有符号扩展方式不同
movzbl 1(%esi), %ecx
addl %eax, %ecx
movl %ecx, 4(%esp)
movl $L_.str2, (%esp)
calll _printf
详细代码:
- cl -W3 -O2 -FAs
- CONST SEGMENT
- ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ DB '%d', 0aH, 00H ; `string'
- CONST ENDS
- ; COMDAT ??_C@_08MEPLLFOL@?$CFd?5?$CL?5?$CFd?6?$AA@
- CONST SEGMENT
- ??_C@_08MEPLLFOL@?$CFd?5?$CL?5?$CFd?6?$AA@ DB '%d + %d', 0aH, 00H ; `string'
- CONST ENDS
- ; COMDAT ??_C@_08HEBOGADK@?$FL?$CFd?0?$CFd?$FN?6?$AA@
- CONST SEGMENT
- ??_C@_08HEBOGADK@?$FL?$CFd?0?$CFd?$FN?6?$AA@ DB '[%d,%d]', 0aH, 00H ; `string'
- ; Function compile flags: /Ogtpy
- CONST ENDS
- ; COMDAT _main
- _TEXT SEGMENT
- _argc$ = 8 ; size = 4
- _argv$ = 12 ; size = 4
- _main PROC ; COMDAT
- ; 6 : {
- push esi
- ; 7 : printf("[%d,%d]\n", CHAR_MIN, CHAR_MAX);
- push 127 ; 0000007fH
- push -128 ; ffffff80H
- push OFFSET ??_C@_08HEBOGADK@?$FL?$CFd?0?$CFd?$FN?6?$AA@
- call _printf
- add esp, 12 ; 0000000cH
- ; 8 : if (argc>1 && strlen(argv[1])>=2)
- cmp DWORD PTR _argc$[esp], 1
- jle SHORT $LN1@main
- mov eax, DWORD PTR _argv$[esp]
- mov esi, DWORD PTR [eax+4]
- mov eax, esi
- lea edx, DWORD PTR [eax+1]
- $LL4@main:
- mov cl, BYTE PTR [eax]
- add eax, 1
- test cl, cl
- jne SHORT $LL4@main
- sub eax, edx
- cmp eax, 2
- jb SHORT $LN1@main
- ; 9 : {
- ; 10 : char* p = argv[1];
- ; 11 : printf("%d + %d\n", p[0], p[1]);
- movsx ecx, BYTE PTR [esi+1]
- movsx edx, BYTE PTR [esi]
- push ecx
- push edx
- push OFFSET ??_C@_08MEPLLFOL@?$CFd?5?$CL?5?$CFd?6?$AA@
- call _printf
- ; 12 : printf("%d\n", p[0]+p[1]);
- movsx eax, BYTE PTR [esi]
- movsx ecx, BYTE PTR [esi+1]
- add eax, ecx
- push eax
- push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
- call _printf
- add esp, 20 ; 00000014H
- ; 13 : return 0;
- xor eax, eax
- pop esi
- ; 16 : }
- ret 0
- $LN1@main:
- ; 14 : }
- ; 15 : return -1;
- or eax, -1
- pop esi
- ; 16 : }
- ret 0
- _main ENDP
- _TEXT ENDS
- END
复制代码 - cl -W3 -O2 -J -FAs
- CONST SEGMENT
- ??_C@_03PMGGPEJJ@?$CFd?6?$AA@ DB '%d', 0aH, 00H ; `string'
- CONST ENDS
- ; COMDAT ??_C@_08MEPLLFOL@?$CFd?5?$CL?5?$CFd?6?$AA@
- CONST SEGMENT
- ??_C@_08MEPLLFOL@?$CFd?5?$CL?5?$CFd?6?$AA@ DB '%d + %d', 0aH, 00H ; `string'
- CONST ENDS
- ; COMDAT ??_C@_08HEBOGADK@?$FL?$CFd?0?$CFd?$FN?6?$AA@
- CONST SEGMENT
- ??_C@_08HEBOGADK@?$FL?$CFd?0?$CFd?$FN?6?$AA@ DB '[%d,%d]', 0aH, 00H ; `string'
- ; Function compile flags: /Ogtpy
- CONST ENDS
- ; COMDAT _main
- _TEXT SEGMENT
- _argc$ = 8 ; size = 4
- _argv$ = 12 ; size = 4
- _main PROC ; COMDAT
- ; 6 : {
- push esi
- ; 7 : printf("[%d,%d]\n", CHAR_MIN, CHAR_MAX);
- push 255 ; 000000ffH
- push 0
- push OFFSET ??_C@_08HEBOGADK@?$FL?$CFd?0?$CFd?$FN?6?$AA@
- call _printf
- add esp, 12 ; 0000000cH
- ; 8 : if (argc>1 && strlen(argv[1])>=2)
- cmp DWORD PTR _argc$[esp], 1
- jle SHORT $LN1@main
- mov eax, DWORD PTR _argv$[esp]
- mov esi, DWORD PTR [eax+4]
- mov eax, esi
- lea edx, DWORD PTR [eax+1]
- $LL4@main:
- mov cl, BYTE PTR [eax]
- add eax, 1
- test cl, cl
- jne SHORT $LL4@main
- sub eax, edx
- cmp eax, 2
- jb SHORT $LN1@main
- ; 9 : {
- ; 10 : char* p = argv[1];
- ; 11 : printf("%d + %d\n", p[0], p[1]);
- movzx ecx, BYTE PTR [esi+1]
- movzx edx, BYTE PTR [esi]
- push ecx
- push edx
- push OFFSET ??_C@_08MEPLLFOL@?$CFd?5?$CL?5?$CFd?6?$AA@
- call _printf
- ; 12 : printf("%d\n", p[0]+p[1]);
- movzx eax, BYTE PTR [esi]
- movzx ecx, BYTE PTR [esi+1]
- add eax, ecx
- push eax
- push OFFSET ??_C@_03PMGGPEJJ@?$CFd?6?$AA@
- call _printf
- add esp, 20 ; 00000014H
- ; 13 : return 0;
- xor eax, eax
- pop esi
- ; 16 : }
- ret 0
- $LN1@main:
- ; 14 : }
- ; 15 : return -1;
- or eax, -1
- pop esi
- ; 16 : }
- ret 0
- _main ENDP
- _TEXT ENDS
- END
复制代码 - gcc -Wall -O2 -S -o -
- .section .rdata,"dr"
- LC0:
- .ascii "[%d,%d]\12\0"
- LC1:
- .ascii "%d + %d\12\0"
- LC2:
- .ascii "%d\12\0"
- .text
- .p2align 4,,15
- .globl _main
- .def _main; .scl 2; .type 32; .endef
- _main:
- pushl %ebp
- movl $16, %eax
- movl %esp, %ebp
- pushl %ebx
- subl $20, %esp
- andl $-16, %esp
- call __alloca
- call ___main
- movl $LC0, (%esp)
- movl $127, %edx
- movl $-128, %eax
- movl %edx, 8(%esp)
- movl %eax, 4(%esp)
- call _printf
- cmpl $1, 8(%ebp)
- jle L2
- movl 12(%ebp), %eax
- movl 4(%eax), %ebx
- movl %ebx, (%esp)
- call _strlen
- cmpl $1, %eax
- ja L4
- L2:
- movl -4(%ebp), %ebx
- movl $-1, %eax
- leave
- ret
- .p2align 4,,7
- L4:
- movsbl 1(%ebx),%eax
- movl %eax, 8(%esp)
- movsbl (%ebx),%eax
- movl $LC1, (%esp)
- movl %eax, 4(%esp)
- call _printf
- movsbl (%ebx),%eax
- movsbl 1(%ebx),%edx
- movl $LC2, (%esp)
- addl %edx, %eax
- movl %eax, 4(%esp)
- call _printf
- movl -4(%ebp), %ebx
- xorl %eax, %eax
- leave
- ret
- .def _strlen; .scl 2; .type 32; .endef
- .def _printf; .scl 2; .type 32; .endef
复制代码 - gcc -Wall -O2 -S -funsigned-char -o -
- LC0:
- .ascii "[%d,%d]\12\0"
- LC1:
- .ascii "%d + %d\12\0"
- LC2:
- .ascii "%d\12\0"
- .text
- .p2align 4,,15
- .globl _main
- .def _main; .scl 2; .type 32; .endef
- _main:
- pushl %ebp
- movl $16, %eax
- movl %esp, %ebp
- pushl %ebx
- subl $20, %esp
- andl $-16, %esp
- call __alloca
- call ___main
- movl $LC0, (%esp)
- xorl %eax, %eax
- movl $255, %edx
- movl %edx, 8(%esp)
- movl %eax, 4(%esp)
- call _printf
- cmpl $1, 8(%ebp)
- jle L2
- movl 12(%ebp), %eax
- movl 4(%eax), %ebx
- movl %ebx, (%esp)
- call _strlen
- cmpl $1, %eax
- ja L4
- L2:
- movl -4(%ebp), %ebx
- movl $-1, %eax
- leave
- ret
- .p2align 4,,7
- L4:
- movzbl 1(%ebx), %eax
- movl %eax, 8(%esp)
- movzbl (%ebx), %eax
- movl $LC1, (%esp)
- movl %eax, 4(%esp)
- call _printf
- movzbl (%ebx), %eax
- movzbl 1(%ebx), %edx
- movl $LC2, (%esp)
- addl %edx, %eax
- movl %eax, 4(%esp)
- call _printf
- movl -4(%ebp), %ebx
- xorl %eax, %eax
- leave
- ret
- .def _strlen; .scl 2; .type 32; .endef
- .def _printf; .scl 2; .type 32; .endef
复制代码 - clang -Wall -O2 -S -o -
- _main: # @main
- # BB#0:
- pushl %ebp
- movl %esp, %ebp
- pushl %esi
- subl $12, %esp
- movl $127, 8(%esp)
- movl $-128, 4(%esp)
- movl $L_.str, (%esp)
- calll _printf
- cmpl $2, 8(%ebp)
- jl LBB0_3
- # BB#1:
- movl 12(%ebp), %eax
- movl 4(%eax), %esi
- movl %esi, (%esp)
- calll _strlen
- cmpl $2, %eax
- jb LBB0_3
- # BB#2:
- movsbl (%esi), %eax
- movsbl 1(%esi), %ecx
- movl %ecx, 8(%esp)
- movl %eax, 4(%esp)
- movl $L_.str1, (%esp)
- calll _printf
- movsbl (%esi), %eax
- movsbl 1(%esi), %ecx
- addl %eax, %ecx
- movl %ecx, 4(%esp)
- movl $L_.str2, (%esp)
- calll _printf
- xorl %eax, %eax
- jmp LBB0_4
- LBB0_3:
- movl $-1, %eax
- LBB0_4:
- addl $12, %esp
- popl %esi
- popl %ebp
- ret
- .data
- L_.str: # @.str
- .asciz "[%d,%d]\n"
- L_.str1: # @.str1
- .asciz "%d + %d\n"
- L_.str2: # @.str2
- .asciz "%d\n"
复制代码 - clang -Wall -O2 -funsigned-char -S -o -
- _main: # @main
- # BB#0:
- pushl %ebp
- movl %esp, %ebp
- pushl %esi
- subl $12, %esp
- movl $255, 8(%esp)
- movl $0, 4(%esp)
- movl $L_.str, (%esp)
- calll _printf
- cmpl $2, 8(%ebp)
- jl LBB0_3
- # BB#1:
- movl 12(%ebp), %eax
- movl 4(%eax), %esi
- movl %esi, (%esp)
- calll _strlen
- cmpl $2, %eax
- jb LBB0_3
- # BB#2:
- movzbl (%esi), %eax
- movzbl 1(%esi), %ecx
- movl %ecx, 8(%esp)
- movl %eax, 4(%esp)
- movl $L_.str1, (%esp)
- calll _printf
- movzbl (%esi), %eax
- movzbl 1(%esi), %ecx
- addl %eax, %ecx
- movl %ecx, 4(%esp)
- movl $L_.str2, (%esp)
- calll _printf
- xorl %eax, %eax
- jmp LBB0_4
- LBB0_3:
- movl $-1, %eax
- LBB0_4:
- addl $12, %esp
- popl %esi
- popl %ebp
- ret
- .data
- L_.str: # @.str
- .asciz "[%d,%d]\n"
- L_.str1: # @.str1
- .asciz "%d + %d\n"
- L_.str2: # @.str2
- .asciz "%d\n"
复制代码
|
|