有趣的C,有趣的编译器 [英] Amusing C, amusing compiler
问题描述
一个函数
int foo(struct T * x)
{
return(x + 1)-x;
}
应始终返回1,无论T是如何定义的。 (对于你的学生来说,int可以用ptrdiff_t取代
。)
首先,看看我的编译器(着名的IAR
EWARM for ARM)跳过箍来得到这个答案。
[对于sizeof(struct T)== 6,
00000000 061080E2 ADD R1,R0,#+ 6
00000004 18209FE5 LDR R2,?? foo_0 ;; 0xaaaaaaab
00000008 92318CE0 UMULL R3,R12,R2,R1
0000000C 2CC1A0E1 LSR R12,R12,#+ 2
00000010 0210A0E1 MOV R1, R2
00000014 912083E0 UMULL R2,R3,R1,R0
00000018 2331A0E1 LSR R3,R3,#+ 2
0000001C 03004CE0 SUB R0, R12,R3
00000020 0EF0A0E1 MOV PC,LR ;;返回
?? foo_0:
00000024 ABAAAAAA DC32 0xaaaaaaab
]
你的编译器怎么样?票价?
[MSVC说得对:
mov eax,1
ret 0
]
另一件事是逻辑上,因为实际类型没关系,
它可能是一个不完整的类型。但是,如果我只是在foo的正文之前说
struct T;
,则编译失败。是好还是有道理?
- 方舟
A function
int foo(struct T *x)
{
return (x+1)-x;
}
should always return a 1, no matter how T is defined. (And int could be
replaced with ptrdiff_t for you pedants.)
For one thing, it was amusing to watch how my compiler (the famed IAR
EWARM for ARM) jumps through hoops to arrive at this answer.
[ For sizeof(struct T)==6,
00000000 061080E2 ADD R1,R0,#+6
00000004 18209FE5 LDR R2,??foo_0 ;; 0xaaaaaaab
00000008 92318CE0 UMULL R3,R12,R2,R1
0000000C 2CC1A0E1 LSR R12,R12,#+2
00000010 0210A0E1 MOV R1,R2
00000014 912083E0 UMULL R2,R3,R1,R0
00000018 2331A0E1 LSR R3,R3,#+2
0000001C 03004CE0 SUB R0,R12,R3
00000020 0EF0A0E1 MOV PC,LR ;; return
??foo_0:
00000024 ABAAAAAA DC32 0xaaaaaaab
]
How does your compiler fare?
[MSVC gets it right:
mov eax, 1
ret 0
]
Another thing is that, logically, since the actual type doesn''t matter,
it could be an incomplete type. However, if I just say
struct T;
before the foo''s body, compilation fails. Is it good and/or justified?
- Ark
推荐答案
Ark写道:
Ark wrote:
一个函数
int foo(struct T * x)
{
return(x +1)-x;
}
应始终返回1,无论T是如何定义的。 (对于你的学生来说,int可以用ptrdiff_t取代
。)
首先,看看我的编译器(着名的IAR
EWARM for ARM)跳过箍来得到这个答案。
[对于sizeof(struct T)== 6,
00000000 061080E2 ADD R1,R0,#+ 6
00000004 18209FE5 LDR R2,?? foo_0 ;; 0xaaaaaaab
00000008 92318CE0 UMULL R3,R12,R2,R1
0000000C 2CC1A0E1 LSR R12,R12,#+ 2
00000010 0210A0E1 MOV R1, R2
00000014 912083E0 UMULL R2,R3,R1,R0
00000018 2331A0E1 LSR R3,R3,#+ 2
0000001C 03004CE0 SUB R0, R12,R3
00000020 0EF0A0E1 MOV PC,LR ;;返回
?? foo_0:
00000024 ABAAAAAA DC32 0xaaaaaaab
]
你的编译器怎么样?票价?
[MSVC说得对:
mov eax,1
ret 0
]
另一件事是逻辑上,因为实际类型没关系,
它可能是一个不完整的类型。但是,如果我只是在foo的正文之前说
struct T;
,则编译失败。它是好的和/或合理的吗?
- Ark
A function
int foo(struct T *x)
{
return (x+1)-x;
}
should always return a 1, no matter how T is defined. (And int could be
replaced with ptrdiff_t for you pedants.)
For one thing, it was amusing to watch how my compiler (the famed IAR
EWARM for ARM) jumps through hoops to arrive at this answer.
[ For sizeof(struct T)==6,
00000000 061080E2 ADD R1,R0,#+6
00000004 18209FE5 LDR R2,??foo_0 ;; 0xaaaaaaab
00000008 92318CE0 UMULL R3,R12,R2,R1
0000000C 2CC1A0E1 LSR R12,R12,#+2
00000010 0210A0E1 MOV R1,R2
00000014 912083E0 UMULL R2,R3,R1,R0
00000018 2331A0E1 LSR R3,R3,#+2
0000001C 03004CE0 SUB R0,R12,R3
00000020 0EF0A0E1 MOV PC,LR ;; return
??foo_0:
00000024 ABAAAAAA DC32 0xaaaaaaab
]
How does your compiler fare?
[MSVC gets it right:
mov eax, 1
ret 0
]
Another thing is that, logically, since the actual type doesn''t matter,
it could be an incomplete type. However, if I just say
struct T;
before the foo''s body, compilation fails. Is it good and/or justified?
- Ark
愚蠢的机器是多么有趣。
你知道吗?你忘记了一个半冒号,他们搞砸了。
愚蠢不是吗?
1)如果x是双倍的话。如果x是NAN或INFinity,
结果不是一个而是NAN。
2)对于x == INTMAX,x + 1-x取决于操作的方式是由编译器订购的
。如果它使(x-1)+ x然后是1,
否则它会溢出并且存在未定义的行为。
如果INTMAX + 1回绕为负,结果是不是一个
3)如果x是无符号且等于UINT_MAX,则结果是-x。
4)这种优化的数量无限多
x + 1-x
x + 2-x
x + 3-x
x + 4-x + 2 * xxx
x + 5-x + 3 * xxxx + 5765 * x-5000 * x-765 * x
对于最后一个应该是5 Microsoft生成的表达式:
mov eax,DWORD PTR _x
It is amusing how stupid machines are.
You know? You forget a semi colon and they get all screwed up.
Stupid isn''t it?
1) If x is double. If x is a NAN or INFinity,
the result is not one but NAN.
2) For x == INTMAX, x+1-x depends on how the operations are
ordered by the compiler. If it makes (x-1)+x then is 1,
otherwise it overflows and there is undefined behavior.
If INTMAX+1 wraps around to negative the result is not one
either
3) If x is unsigned and equal to UINT_MAX, the the result is -x.
4) There is an infinite number of this kind of optimizations
x+1-x
x+2-x
x+3-x
x+4-x+2*x-x-x
x+5-x + 3*x-x-x-x + 5765*x-5000*x-765*x
For that last expression that should be 5 Microsoft generates:
mov eax, DWORD PTR _x
[ebp ]
添加eax,5
sub eax,DWORD PTR _x
[ebp]
add eax, 5
sub eax, DWORD PTR _x
[ebp]
mov ecx,DWORD PTR _x
[ebp]
mov ecx, DWORD PTR _x
这篇关于有趣的C,有趣的编译器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!