鱼C论坛

 找回密码
 立即注册
查看: 2675|回复: 10

把*****处,分别替换成下面#if() #endif

[复制链接]
发表于 2015-4-1 11:52:04 | 显示全部楼层 |阅读模式
20鱼币
本帖最后由 haiouda 于 2015-4-1 12:17 编辑
#include<stdio.h>
#include<string.h>

int main()
{
        char * p="I love fishc.com!" ;

        int m,k;
        printf("input m:");
        scanf("%d",&m);


    k=strlen(p);
        
        *****************
        


        
        return 0;
}




#if(0)
        while( k-m<0   )
        {
                printf("input m:");
                scanf("%d",&m);

        }

#endif


#if(0)
        while( m-strlen(p)>0   )
        {
                printf("input m:");
                scanf("%d",&m);

        }

#endif



#if(0)
        while( strlen(p)-m<0   )
        {
                printf("input m:");
                scanf("%d",&m);

        }

#endif
把第15行*****处,分别替换成下面#if() #endif 中内容,为何结果不同?

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-4-1 20:39:01 | 显示全部楼层
导电性heart 发表于 2015-4-1 15:09
把#if和#endif复制进去,0改1之后都是正常循环

我上面的程序只是其中的一段,你可以试着把下面几上分别复制进去,再一步步调试,才能发现问题的哟;

下面三个,#if(0) #endif 之间的内容在数学上是完全相等的,在程序里确出问题了,所以想不明白才在这里发贴子的。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-4-1 15:09:53 | 显示全部楼层
把#if和#endif复制进去,0改1之后都是正常循环:lol:
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-4-3 12:48:11 | 显示全部楼层
{:1_1:}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-4-3 13:21:38 | 显示全部楼层
{:1_1:}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-4-3 17:38:16 | 显示全部楼层
本帖最后由 流行语 于 2015-4-3 17:39 编辑

#if(0)条件都不成立,怎么会运行呢,在C中非0即为true,否则为false。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2015-4-3 22:59:35 | 显示全部楼层
流行语 发表于 2015-4-3 17:38
#if(0)条件都不成立,怎么会运行呢,在C中非0即为true,否则为false。

你不会,用哪个时,就把哪个打开呀
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-4-8 08:22:09 | 显示全部楼层
{:1_1:}
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2015-8-23 00:25:54 | 显示全部楼层
不得不说 楼主你问了一个相当纠结的问题,这里的#if #endif 只是跑堂而已, 关键问题是 后面while中的几句话,咋看 我们从简单的逻辑上面看 这几句话其实是没有太大的区别的,但是 这些语句的执行结果就是不一样,这里面问题到底在哪呢?
想不明白的情况下我只能通过C的反汇编工具将几种情况的While中的 比较都转化成了汇编代码,这样我还是用了不上时间最后终于是想明白了其中的道理;
下面看看汇编的代码(当然其中还有一部分关于C在编译成机器码的处理方式,这些都只能是我个人的假设,没有实际的依据):

        while (k - m < 0)
001D7EE6  mov         eax,dword ptr [k]  
001D7EE9  sub         eax,dword ptr [m]  
001D7EEC  jns         main+89h (01D7F09h)


我们能看到此处的 减法结束后直接使用的跳转语句是 jns(s 代表sign 符号的意思):jns 飞负跳转
意思就是说 k-m的 结果如果是正数 那么就是说比0大也就是假 直接跳过while的循环代码;
这里我的 猜测是 在C 对 有符号整数结果与0 比较的时候 是直接 检测符号位是什么以确定是否执行循环;


        while (m - k > 0)
001D7F09  mov         eax,dword ptr [m]  
001D7F0C  sub         eax,dword ptr [k]  
001D7F0F  test        eax,eax  
001D7F11  jle         main+0AEh (01D7F2Eh)

这里的减法之后 有多出一句 test(结果为0 则 零标志位位1) 那么 jle(l 表示less小于,e是 equal 等于)小于等于跳转
个人 觉得 在sub中能检测到 小于  然后使用 test 来确认零标志 跳转使用不一样

那么前面的只是基本东西 重点是后面的东西

        while ((m - strlen(p))>0)
001D7F2E  mov         eax,dword ptr [p]  
001D7F31  push        eax  
001D7F32  call        _strlen (01D1159h)  
001D7F37  add         esp,4  
001D7F3A  mov         ecx,dword ptr [m]  
001D7F3D  sub         ecx,eax  
001D7F3F  je          main+0DCh (01D7F5Ch)  


        while (strlen(p) - m < 0)
00C9536C  mov         eax,dword ptr [p]  
00C9536F  push        eax  
00C95370  call        _strlen (0C91159h)  
00C95375  add         esp,4  
00C95378  sub         eax,dword ptr [m]  
00C9537B  jmp         main+108h (0C95398h)


在这两段代码中 我们可以看出相同的是 他们都是先计算了 strlen(p),然后做减法但是他们的 跳转指令却是很诡异

第一句 大于0的 跳转是 je(等于零跳转)完全不考虑小于0 的部分
第二句 小于0的 跳转是jmp(强制跳转)这个更是奇葩 直接不管结果就跳,这是为什么呢?

最终我有做了最后的实验 然后我就悟了(不止是否有大神在这里已经知道结果了!),请看下面的代码:

        while ((int)strlen(p) - m < 0)
00C95398  mov         eax,dword ptr [p]  
00C9539B  push        eax  
00C9539C  call        _strlen (0C91159h)  
00C953A1  add         esp,4  
00C953A4  sub         eax,dword ptr [m]  
00C953A7  jns         main+134h (0C953C4h)


这里我只是将 strlen的结果转化为int型即有符号整数,结果结合第一句是一样的了,跳转使用了 jns非负跳转;

到这里我想所有的迷已近解开, 其中的 关键就在一  函数strlen 的返回值是 无符号整数 unsigned int ,
同时 无符号整数在和有符号整数共同计算的时候 会被隐式转化为 无符号整数,所以 后两次的计算完全
不考虑为负数的情况
{
        unsigned int x, y;
        x = 5;
        y = 10;
        x -= y;
}x 的结果是一个奇大的正整数。。。。。。,个人猜测 C的编译器 会根据我们的 判断语句的 类型和
比较的方式 自行选择不同的跳转判定方式,故此 这里是因为对 C的了解不够深刻而出现的错误;

最后多谢楼主的题目,这一次我对C的一些理解又更近了一步! -------C无止境,以共勉!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-15 15:05:05 | 显示全部楼层
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2016-8-16 02:07:41 | 显示全部楼层
if(0)条件都不成立
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-27 08:42

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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