在网上看到一个"画吃豆人"的C程序,看到putchar的用法,觉得很奇怪,想着写这份代码的人应该是位高手。出于好奇,要把它弄懂。
int eye()
{
double x,y;
for (y = 1; y >= -1; y -= 0.05, putchar('\n'))
for (x = -1;x <= 1; x += 0.025)
putchar(" ."[x*x + y*y < 1 && /* 确定圆形的位置 */
fabs(atan2(y,x)) > 0.5 && /* fabs 求绝对值 画吃豆人的嘴巴 */
x*x+(y-0.5)*(y-0.5) > 0.02]); /* pow(x,y) x的y次幂 画吃豆人的眼睛 */
}
/* 自测代码 */
void test_putchar1()
{
putchar(" y"[1]); // y
}
void test_putchar2()
{
char *pos = "xy";
putchar(pos[1]); // y
}
void test_putchar3()
{
putchar("123"[0]); // 1
putchar(0xa);
putchar("123"[1]); // 2
putchar(0xa);
putchar("123"[2]); // 3
}
int main()
{
eye();
putchar(0xa);
test_putchar1();
putchar(0xa);
test_putchar2();
putchar(0xa);
test_putchar3();
putchar(0xa);
}
看一下反汇编,已经被编译器优化成值了。
0000000000001417 <test_putchar1>:
1417: f3 0f 1e fa endbr64
141b: 55 push %rbp
141c: 48 89 e5 mov %rsp,%rbp
141f: b8 79 00 00 00 mov $0x79,%eax // eax=y
1424: 0f be c0 movsbl %al,%eax // eax=y
1427: 89 c7 mov %eax,%edi // edi=y
1429: e8 32 fc ff ff callq 1060 <putchar@plt> // putchar('y');
142e: 90 nop
142f: 5d pop %rbp
1430: c3 retq
0000000000001431 <test_putchar2>:
1431: f3 0f 1e fa endbr64
1435: 55 push %rbp
1436: 48 89 e5 mov %rsp,%rbp
1439: 48 83 ec 10 sub $0x10,%rsp
143d: 48 8d 05 cf 0b 00 00 lea 0xbcf(%rip),%rax # 2013 <_IO_stdin_used+0x13> // 0x555555556013: 0x00007978
1444: 48 89 45 f8 mov %rax,-0x8(%rbp) // (rbp-0x8)=0x7fffffffe288:0x0000555555556013
1448: 48 8b 45 f8 mov -0x8(%rbp),%rax // rax=0x555555556013
144c: 48 83 c0 01 add $0x1,%rax // rax=0x555555556014
1450: 0f b6 00 movzbl (%rax),%eax // eax='y'
1453: 0f be c0 movsbl %al,%eax // eax='y'
1456: 89 c7 mov %eax,%edi // edi='y'
1458: e8 03 fc ff ff callq 1060 <putchar@plt> // putchar('y');
145d: 90 nop
145e: c9 leaveq
145f: c3 retq
0000000000001460 <test_putchar3>:
1460: f3 0f 1e fa endbr64
1464: 55 push %rbp
1465: 48 89 e5 mov %rsp,%rbp
1468: b8 31 00 00 00 mov $0x31,%eax // eax=1
146d: 0f be c0 movsbl %al,%eax // eax=1
1470: 89 c7 mov %eax,%edi // edi=1
1472: e8 e9 fb ff ff callq 1060 <putchar@plt> // putchar(0x31)
1477: bf 0a 00 00 00 mov $0xa,%edi // edi=0xa
147c: e8 df fb ff ff callq 1060 <putchar@plt> // putchar(0x0a)
1481: b8 32 00 00 00 mov $0x32,%eax // eax=0x32
1486: 0f be c0 movsbl %al,%eax // eax=0x32
1489: 89 c7 mov %eax,%edi // edi=0x32
148b: e8 d0 fb ff ff callq 1060 <putchar@plt> // putchar(0x32)
1490: bf 0a 00 00 00 mov $0xa,%edi // edi=0xa
1495: e8 c6 fb ff ff callq 1060 <putchar@plt> // putchar(0x0a)
149a: b8 33 00 00 00 mov $0x33,%eax // eax=0x33
149f: 0f be c0 movsbl %al,%eax // eax=0x33
14a2: 89 c7 mov %eax,%edi // edi=0x33
14a4: e8 b7 fb ff ff callq 1060 <putchar@plt> // putchar(0x33)
14a9: 90 nop
14aa: 5d pop %rbp
14ab: c3 retq