鱼C论坛

 找回密码
 立即注册
查看: 1610|回复: 9

[已解决]关于高级宏定义的问题

[复制链接]
发表于 2018-12-22 11:37:24 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #include <stdio.h>

  2. #define SQUARE(y) y*y

  3. int main()
  4. {
  5.     int x;

  6.     printf("请输入一个整数:");
  7.     scanf("%d",&x);

  8.     printf("%d的平方是%d",x,SQUARE(x--));
  9.    
  10.     return 0;
  11. }
复制代码


程序运行   输入 3

输出的结果为什么是   1的平方是6

???
求解答
最佳答案
2018-12-28 13:00:48
本帖最后由 人造人 于 2018-12-28 13:02 编辑
1809228982 发表于 2018-12-28 09:12
x--*x--    分解 是 x = x - 1 * x = x - 1;(还是 (x = x - 1 )* (x = x - 1))


答案是不确定,标准对这类代码行为的定义是“未定义”,也就是说编译器爱怎么搞就怎么搞
编译器可以先算x*x,然后把x的结果减2
或者... 嗯,我认为我描述不清楚,看下面的代码吧

例1.    x=10
int y = x-- * x--;
先算x*x,结果为100,y的最终结果为100,然后把x减2,x的最终结果为8

例2.    x=10
int y = x-- * x--;
这个不好解释
这个计算的是9 * 10,y的最终结果为90,x最终为8
看下面汇编代码吧,你也许现在看不懂,但是如果你要深入研究这些,你必须要学习汇编语言

  1. #include <stdio.h>

  2. int main(void)
  3. {
  4. 012C17A0 55                   push        ebp  
  5. 012C17A1 8B EC                mov         ebp,esp  
  6. 012C17A3 81 EC D0 00 00 00    sub         esp,0D0h  
  7. 012C17A9 53                   push        ebx  
  8. 012C17AA 56                   push        esi  
  9. 012C17AB 57                   push        edi  
  10. 012C17AC 8D BD 30 FF FF FF    lea         edi,[ebp-0D0h]  
  11. 012C17B2 B9 34 00 00 00       mov         ecx,34h  
  12. 012C17B7 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
  13. 012C17BC F3 AB                rep stos    dword ptr es:[edi]  
  14.         int x = 10;
  15. 012C17BE C7 45 F8 0A 00 00 00 mov         dword ptr [x],0Ah  
  16.         printf("%d\n", x-- * x--);
  17. 012C17C5 8B 45 F8             mov         eax,dword ptr [x]  
  18. 012C17C8 0F AF 45 F8          imul        eax,dword ptr [x]  
  19. 012C17CC 89 85 30 FF FF FF    mov         dword ptr [ebp-0D0h],eax  
  20. 012C17D2 8B 4D F8             mov         ecx,dword ptr [x]  
  21. 012C17D5 83 E9 01             sub         ecx,1  
  22. 012C17D8 89 4D F8             mov         dword ptr [x],ecx  
  23. 012C17DB 8B 55 F8             mov         edx,dword ptr [x]  
  24. 012C17DE 83 EA 01             sub         edx,1  
  25. 012C17E1 89 55 F8             mov         dword ptr [x],edx  
  26. 012C17E4 8B 85 30 FF FF FF    mov         eax,dword ptr [ebp-0D0h]  
  27. 012C17EA 50                   push        eax  
  28. 012C17EB 68 D0 7B 2C 01       push        offset string "%d\n" (012C7BD0h)  
  29. 012C17F0 E8 35 FB FF FF       call        _printf (012C132Ah)  
  30. 012C17F5 83 C4 08             add         esp,8  
  31.         return 0;
  32. 012C17F8 33 C0                xor         eax,eax  
  33. }
  34. 012C17FA 5F                   pop         edi  
  35. 012C17FB 5E                   pop         esi  
  36. 012C17FC 5B                   pop         ebx  
  37. 012C17FD 81 C4 D0 00 00 00    add         esp,0D0h  
  38. 012C1803 3B EC                cmp         ebp,esp  
  39. 012C1805 E8 18 F9 FF FF       call        __RTC_CheckEsp (012C1122h)  
  40. 012C180A 8B E5                mov         esp,ebp  
  41. 012C180C 5D                   pop         ebp  
  42. 012C180D C3                   ret  
复制代码


  1. seg000:0291 ; =============== S U B R O U T I N E =======================================
  2. seg000:0291
  3. seg000:0291 ; Attributes: bp-based frame
  4. seg000:0291
  5. seg000:0291 sub_10291       proc near               ; CODE XREF: start+155p
  6. seg000:0291                 push    bp
  7. seg000:0292                 mov     bp, sp
  8. seg000:0294                 push    si


  9. seg000:0295                 mov     si, 0Ah



  10. seg000:0298                 mov     ax, 291h
  11. seg000:029B                 push    ax
  12. seg000:029C                 mov     ax, 0AAh ; '
  13. seg000:029F                 push    ax
  14. seg000:02A0                 call    sub_10EEC
  15. seg000:02A3                 pop     cx
  16. seg000:02A4                 pop     cx



  17. seg000:02A5                 mov     ax, si
  18. seg000:02A7                 dec     si
  19. seg000:02A8                 mov     dx, si
  20. seg000:02AA                 dec     si
  21. seg000:02AB                 imul    dx
  22. seg000:02AD                 push    ax
  23. seg000:02AE                 mov     ax, 0B4h ; '
  24. seg000:02B1                 push    ax
  25. seg000:02B2                 call    sub_10EEC
  26. seg000:02B5                 pop     cx
  27. seg000:02B6                 pop     cx



  28. seg000:02B7                 xor     ax, ax
  29. seg000:02B9                 jmp     short $+2
  30. seg000:02BB ; ---------------------------------------------------------------------------
  31. seg000:02BB
  32. seg000:02BB loc_102BB:                              ; CODE XREF: sub_10291+28j
  33. seg000:02BB                 pop     si
  34. seg000:02BC                 pop     bp
  35. seg000:02BD                 retn
  36. seg000:02BD sub_10291       endp
  37. seg000:02BD
  38. seg000:02BE ; ---------------------------------------------------------------------------
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2018-12-22 11:51:50 | 显示全部楼层
  1. sh-4.4$ cat main.c
  2. //#include <stdio.h>

  3. #define SQUARE(y) y*y

  4. int main()
  5. {
  6.         int x;
  7.         printf("请输入一个整数:");
  8.         scanf("%d",&x);
  9.         printf("%d的平方是%d",x,SQUARE(x--));
  10.         return 0;
  11. }
  12. sh-4.4$ gcc -E main.c
  13. # 1 "main.c"
  14. # 1 "<built-in>"
  15. # 1 "<command-line>"
  16. # 1 "main.c"




  17. int main()
  18. {
  19. int x;
  20. printf("请输入一个整数:");
  21. scanf("%d",&x);
  22. printf("%d的平方是%d",x,x--*x--);
  23. return 0;
  24. }
  25. sh-4.4$
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-22 11:57:56 | 显示全部楼层
  1. _main:
  2.         pushl   %ebp
  3.         movl    %esp, %ebp
  4.         andl    $-16, %esp
  5.         subl    $32, %esp
  6.         call    ___main
  7.         movl    $LC0, (%esp)
  8.         call    _printf
  9.         leal    28(%esp), %eax
  10.         movl    %eax, 4(%esp)
  11.         movl    $LC1, (%esp)
  12.         call    _scanf
  13.         movl    28(%esp), %edx
  14.         leal    -1(%edx), %eax
  15.         movl    %eax, 28(%esp)
  16.         movl    28(%esp), %eax
  17.         leal    -1(%eax), %ecx
  18.         movl    %ecx, 28(%esp)
  19.         imull   %eax, %edx
  20.         movl    28(%esp), %eax
  21.         movl    %edx, 8(%esp)
  22.         movl    %eax, 4(%esp)
  23.         movl    $LC2, (%esp)
  24.         call    _printf
  25.         movl    $0, %eax
  26.         leave
  27.         ret
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-12-22 14:39:49 | 显示全部楼层

??怎么有两个main函数??
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-22 15:24:24 | 显示全部楼层
1809228982 发表于 2018-12-22 14:39
??怎么有两个main函数??

  1. #define SQUARE(y) y*y

  2. int main()
  3. {
  4.         int x;
  5.         printf("请输入一个整数:");
  6.         scanf("%d",&x);
  7.         printf("%d的平方是%d",x,SQUARE(x--));
  8.         return 0;
  9. }
复制代码


相当于


  1. int main()
  2. {
  3. int x;
  4. printf("请输入一个整数:");
  5. scanf("%d",&x);
  6. printf("%d的平方是%d",x,x--*x--);
  7. return 0;
  8. }
复制代码

小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2018-12-28 09:12:57 | 显示全部楼层

x--*x--    分解 是 x = x - 1 * x = x - 1;(还是 (x = x - 1 )* (x = x - 1))
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-28 13:00:48 | 显示全部楼层    本楼为最佳答案   
本帖最后由 人造人 于 2018-12-28 13:02 编辑
1809228982 发表于 2018-12-28 09:12
x--*x--    分解 是 x = x - 1 * x = x - 1;(还是 (x = x - 1 )* (x = x - 1))


答案是不确定,标准对这类代码行为的定义是“未定义”,也就是说编译器爱怎么搞就怎么搞
编译器可以先算x*x,然后把x的结果减2
或者... 嗯,我认为我描述不清楚,看下面的代码吧

例1.    x=10
int y = x-- * x--;
先算x*x,结果为100,y的最终结果为100,然后把x减2,x的最终结果为8

例2.    x=10
int y = x-- * x--;
这个不好解释
这个计算的是9 * 10,y的最终结果为90,x最终为8
看下面汇编代码吧,你也许现在看不懂,但是如果你要深入研究这些,你必须要学习汇编语言

  1. #include <stdio.h>

  2. int main(void)
  3. {
  4. 012C17A0 55                   push        ebp  
  5. 012C17A1 8B EC                mov         ebp,esp  
  6. 012C17A3 81 EC D0 00 00 00    sub         esp,0D0h  
  7. 012C17A9 53                   push        ebx  
  8. 012C17AA 56                   push        esi  
  9. 012C17AB 57                   push        edi  
  10. 012C17AC 8D BD 30 FF FF FF    lea         edi,[ebp-0D0h]  
  11. 012C17B2 B9 34 00 00 00       mov         ecx,34h  
  12. 012C17B7 B8 CC CC CC CC       mov         eax,0CCCCCCCCh  
  13. 012C17BC F3 AB                rep stos    dword ptr es:[edi]  
  14.         int x = 10;
  15. 012C17BE C7 45 F8 0A 00 00 00 mov         dword ptr [x],0Ah  
  16.         printf("%d\n", x-- * x--);
  17. 012C17C5 8B 45 F8             mov         eax,dword ptr [x]  
  18. 012C17C8 0F AF 45 F8          imul        eax,dword ptr [x]  
  19. 012C17CC 89 85 30 FF FF FF    mov         dword ptr [ebp-0D0h],eax  
  20. 012C17D2 8B 4D F8             mov         ecx,dword ptr [x]  
  21. 012C17D5 83 E9 01             sub         ecx,1  
  22. 012C17D8 89 4D F8             mov         dword ptr [x],ecx  
  23. 012C17DB 8B 55 F8             mov         edx,dword ptr [x]  
  24. 012C17DE 83 EA 01             sub         edx,1  
  25. 012C17E1 89 55 F8             mov         dword ptr [x],edx  
  26. 012C17E4 8B 85 30 FF FF FF    mov         eax,dword ptr [ebp-0D0h]  
  27. 012C17EA 50                   push        eax  
  28. 012C17EB 68 D0 7B 2C 01       push        offset string "%d\n" (012C7BD0h)  
  29. 012C17F0 E8 35 FB FF FF       call        _printf (012C132Ah)  
  30. 012C17F5 83 C4 08             add         esp,8  
  31.         return 0;
  32. 012C17F8 33 C0                xor         eax,eax  
  33. }
  34. 012C17FA 5F                   pop         edi  
  35. 012C17FB 5E                   pop         esi  
  36. 012C17FC 5B                   pop         ebx  
  37. 012C17FD 81 C4 D0 00 00 00    add         esp,0D0h  
  38. 012C1803 3B EC                cmp         ebp,esp  
  39. 012C1805 E8 18 F9 FF FF       call        __RTC_CheckEsp (012C1122h)  
  40. 012C180A 8B E5                mov         esp,ebp  
  41. 012C180C 5D                   pop         ebp  
  42. 012C180D C3                   ret  
复制代码


  1. seg000:0291 ; =============== S U B R O U T I N E =======================================
  2. seg000:0291
  3. seg000:0291 ; Attributes: bp-based frame
  4. seg000:0291
  5. seg000:0291 sub_10291       proc near               ; CODE XREF: start+155p
  6. seg000:0291                 push    bp
  7. seg000:0292                 mov     bp, sp
  8. seg000:0294                 push    si


  9. seg000:0295                 mov     si, 0Ah



  10. seg000:0298                 mov     ax, 291h
  11. seg000:029B                 push    ax
  12. seg000:029C                 mov     ax, 0AAh ; '
  13. seg000:029F                 push    ax
  14. seg000:02A0                 call    sub_10EEC
  15. seg000:02A3                 pop     cx
  16. seg000:02A4                 pop     cx



  17. seg000:02A5                 mov     ax, si
  18. seg000:02A7                 dec     si
  19. seg000:02A8                 mov     dx, si
  20. seg000:02AA                 dec     si
  21. seg000:02AB                 imul    dx
  22. seg000:02AD                 push    ax
  23. seg000:02AE                 mov     ax, 0B4h ; '
  24. seg000:02B1                 push    ax
  25. seg000:02B2                 call    sub_10EEC
  26. seg000:02B5                 pop     cx
  27. seg000:02B6                 pop     cx



  28. seg000:02B7                 xor     ax, ax
  29. seg000:02B9                 jmp     short $+2
  30. seg000:02BB ; ---------------------------------------------------------------------------
  31. seg000:02BB
  32. seg000:02BB loc_102BB:                              ; CODE XREF: sub_10291+28j
  33. seg000:02BB                 pop     si
  34. seg000:02BC                 pop     bp
  35. seg000:02BD                 retn
  36. seg000:02BD sub_10291       endp
  37. seg000:02BD
  38. seg000:02BE ; ---------------------------------------------------------------------------
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-28 13:04:46 | 显示全部楼层
vs2017

  1. #include <stdio.h>

  2. int main(void)
  3. {
  4.         int x = 10;
  5.         int y = x-- * x--;
  6.         printf("%d\n", x);
  7.         printf("%d\n", y);
  8.         return 0;
  9. }
复制代码

  1. 8
  2. 100
  3. 请按任意键继续. . .
复制代码
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-28 13:08:45 | 显示全部楼层
纯DOS,tc3.0

1.png
2.png
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-1-3 08:36:52 | 显示全部楼层

好的,谢谢
小甲鱼最新课程 -> https://ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-6-16 00:12

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表