鱼C论坛

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

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

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

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

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

x
#include <stdio.h>

#define SQUARE(y) y*y

int main()
{
    int x;

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

    printf("%d的平方是%d",x,SQUARE(x--));
    
    return 0;
}

程序运行   输入 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
看下面汇编代码吧,你也许现在看不懂,但是如果你要深入研究这些,你必须要学习汇编语言
#include <stdio.h>

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

seg000:0291 ; =============== S U B R O U T I N E =======================================
seg000:0291
seg000:0291 ; Attributes: bp-based frame
seg000:0291
seg000:0291 sub_10291       proc near               ; CODE XREF: start+155p
seg000:0291                 push    bp
seg000:0292                 mov     bp, sp
seg000:0294                 push    si


seg000:0295                 mov     si, 0Ah



seg000:0298                 mov     ax, 291h
seg000:029B                 push    ax
seg000:029C                 mov     ax, 0AAh ; '
seg000:029F                 push    ax
seg000:02A0                 call    sub_10EEC
seg000:02A3                 pop     cx
seg000:02A4                 pop     cx



seg000:02A5                 mov     ax, si
seg000:02A7                 dec     si
seg000:02A8                 mov     dx, si
seg000:02AA                 dec     si
seg000:02AB                 imul    dx
seg000:02AD                 push    ax
seg000:02AE                 mov     ax, 0B4h ; '
seg000:02B1                 push    ax
seg000:02B2                 call    sub_10EEC
seg000:02B5                 pop     cx
seg000:02B6                 pop     cx



seg000:02B7                 xor     ax, ax
seg000:02B9                 jmp     short $+2
seg000:02BB ; ---------------------------------------------------------------------------
seg000:02BB
seg000:02BB loc_102BB:                              ; CODE XREF: sub_10291+28j
seg000:02BB                 pop     si
seg000:02BC                 pop     bp
seg000:02BD                 retn
seg000:02BD sub_10291       endp
seg000:02BD
seg000:02BE ; ---------------------------------------------------------------------------
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

#define SQUARE(y) y*y

int main()
{
        int x;
        printf("请输入一个整数:");
        scanf("%d",&x);
        printf("%d的平方是%d",x,SQUARE(x--));
        return 0;
}
sh-4.4$ gcc -E main.c
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "main.c"




int main()
{
 int x;
 printf("请输入一个整数:");
 scanf("%d",&x);
 printf("%d的平方是%d",x,x--*x--);
 return 0;
}
sh-4.4$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-22 11:57:56 | 显示全部楼层
_main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $32, %esp
        call    ___main
        movl    $LC0, (%esp)
        call    _printf
        leal    28(%esp), %eax
        movl    %eax, 4(%esp)
        movl    $LC1, (%esp)
        call    _scanf
        movl    28(%esp), %edx
        leal    -1(%edx), %eax
        movl    %eax, 28(%esp)
        movl    28(%esp), %eax
        leal    -1(%eax), %ecx
        movl    %ecx, 28(%esp)
        imull   %eax, %edx
        movl    28(%esp), %eax
        movl    %edx, 8(%esp)
        movl    %eax, 4(%esp)
        movl    $LC2, (%esp)
        call    _printf
        movl    $0, %eax
        leave
        ret
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

??怎么有两个main函数??
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

int main()
{
        int x;
        printf("请输入一个整数:");
        scanf("%d",&x);
        printf("%d的平方是%d",x,SQUARE(x--));
        return 0;
}

相当于

int main()
{
int x;
printf("请输入一个整数:");
scanf("%d",&x);
printf("%d的平方是%d",x,x--*x--);
return 0;
}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

x--*x--    分解 是 x = x - 1 * x = x - 1;(还是 (x = x - 1 )* (x = x - 1))
想知道小甲鱼最近在做啥?请访问 -> 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
看下面汇编代码吧,你也许现在看不懂,但是如果你要深入研究这些,你必须要学习汇编语言
#include <stdio.h>

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

seg000:0291 ; =============== S U B R O U T I N E =======================================
seg000:0291
seg000:0291 ; Attributes: bp-based frame
seg000:0291
seg000:0291 sub_10291       proc near               ; CODE XREF: start+155p
seg000:0291                 push    bp
seg000:0292                 mov     bp, sp
seg000:0294                 push    si


seg000:0295                 mov     si, 0Ah



seg000:0298                 mov     ax, 291h
seg000:029B                 push    ax
seg000:029C                 mov     ax, 0AAh ; '
seg000:029F                 push    ax
seg000:02A0                 call    sub_10EEC
seg000:02A3                 pop     cx
seg000:02A4                 pop     cx



seg000:02A5                 mov     ax, si
seg000:02A7                 dec     si
seg000:02A8                 mov     dx, si
seg000:02AA                 dec     si
seg000:02AB                 imul    dx
seg000:02AD                 push    ax
seg000:02AE                 mov     ax, 0B4h ; '
seg000:02B1                 push    ax
seg000:02B2                 call    sub_10EEC
seg000:02B5                 pop     cx
seg000:02B6                 pop     cx



seg000:02B7                 xor     ax, ax
seg000:02B9                 jmp     short $+2
seg000:02BB ; ---------------------------------------------------------------------------
seg000:02BB
seg000:02BB loc_102BB:                              ; CODE XREF: sub_10291+28j
seg000:02BB                 pop     si
seg000:02BC                 pop     bp
seg000:02BD                 retn
seg000:02BD sub_10291       endp
seg000:02BD
seg000:02BE ; ---------------------------------------------------------------------------
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2018-12-28 13:04:46 | 显示全部楼层
vs2017
#include <stdio.h>

int main(void)
{
        int x = 10;
        int y = x-- * x--;
        printf("%d\n", x);
        printf("%d\n", y);
        return 0;
}
8
100
请按任意键继续. . .
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

1.png
2.png
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

好的,谢谢
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-10-3 04:38

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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