有趣的C,有趣的编译器 [英] Amusing C, amusing compiler

查看:80
本文介绍了有趣的C,有趣的编译器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个函数

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆