关于C的未定义行为

作者: 编程技术  发布:2019-09-25

关于C的未定义行为

转自:

对此C的初学者的话,被必要做上面包车型地铁这种主题材料确实是脑残的不能够再脑残的一言一动。但是相当多C初级教程——居然都有那样的题。
最特异的事例正是

a+=a++;

这种地方下,a最后到底等于多少了?

编写翻译器应该什么晓得a+=a++呢?首先是扩充,a=a+a++;
然后分别总计a和a++的值,把它们相加,然后把结果赋给a。
但是此地有五个标题,就是试行完a++之后,a++的值等于a自身的值,不过a的值却成为了a+1。
进而首固然拍卖顺序。

比如说int a=3;
纵然编译器先计算赋值号+=侧边a的值为3,然后总结侧边a++的值为3,同一时候a变为4。
下一场总计3+3=6,赋给a,那么a以后的值就是6。
假设编写翻译器先总结赋值号侧面的a++,获得的结果为3,同一时候a变为4,然后总括左侧a=4。
继之计算4+3=7,于是7那一个数被赋值给了a。

相当于说,区别的知道方法,在这么些例子里面居然会获得不一致的答案?

自己怎么要用居然?难道那些结果不是不敢相信 无法相信的么?一样的表明式,只不过编写翻译器不平等,就搜查缉获了不一样的结果,那真是个喜剧啊。
难道未有啥标准供给编写翻译器选用同一的精通格局么?C语言的职业遵循ANSI C标准。不过很不好,ANSI C标准里面,并不曾有关蒙受这种景色应什么管理的规定,反而是建议,编译器你望着办吧。
那正是C语言的“未定义行为”。

话说本身只是有在用二个GCD函数的时候被某大神狠狠的吐槽了,那么些GCD函数如下:

int GCD(int a,int b){    while (a %= b ^= a ^= b ^= a);    return b;}

就疑似下边深入分析的那么,这段程序在编写翻译进度中,会现出哪些顺序,那也是明媒正娶里面未有明确的,属于未定义行为。
故而用那些函数并不一定能担保收获不错的结果。

这种事情嘛。。。既然是付出编写翻译器的。
本人想这一个实际上应该是为了代码优化。人所共知,C是三个足够重视效能的语言,并且有这种为了功能甩掉全体的感觉,不评说这么些好倒霉,反正人家在最受应接的言语排名的榜单第一人的宝座上坐了不精通某个年了。
给编译器更大的任性,编写翻译器就会更加好的优化转移的二进制代码。
还应该有任何的方面,比如越界数组。
就好像那样

char str1[]="myworld";str1[18]='';

数组str1哪儿来的第19项啊!!!这种东西仍可以经过编写翻译!!!
采取越界数组也是C的三个“未定义行为”。C的规范未有规定编写翻译器在蒙受这种场合应当如何是好。那年编写翻译器的主见应该是——多一事不比少一事,小编也不检讨这里究竟是或不是其一数组的限定了,反正你都叫小编写了,小编就写啊。

再有三个一级的操作正是允许三个随意指的指针的读写。
比如笔者申请了一个动态区域,然后释放掉了:

int *p;p=(int *)malloc(4*sizeof(int));/*各种对p的操作*/free(p);p[0]=0;printf("%d%d%d%d",p[0],p[1],p[2],p[3]);

不要夸张的说,作者要好的次序往往死在这种地方,正是free未来再print。。。
再比如:

int *p;p=0x1e642a80;p[8]=24;

这种指针操作依旧也给通过????

更不行的是,上面的这几个都属于C的“未定义行为"正是说,即使那一个操作能够拓宽,可是编写翻译器并不保障实施结果。
实属这种事物不仅仅不报错给通过了,而且还不遵照大家想像的样板执行,而是由着编写翻译器的性子随意来?

从那几个角度看,真的是太苦逼了。
本身还赶过过一段脑残代码,类似那样:

char tips[]="No";if(condition){    strcpy(tips,"Yes");}

对这种东西。。。。。呵呵。在Windows下运转就等着被中断吧。。
再有使用未初阶化的变量也是一种“未定义行为”,比方:

int x;printf;

一般性你也不了解您会在显示屏上旁观如何。。。。
GCC的率先版编写翻译器在遇见这种情景的时候,会在您荧屏上初步二个小游戏。(这是支付组满满的恶心啊!!嗯,一定是!!)
C的变量并不会在宣称时被最早化,那么些特点受到人们诟病。
不过ANSI C本身自然是想通过轻松这几个初叶化操作,来提高一点周转速度。
归根结蒂要初步化三个大数组或是用malloc分配的一大堆空间,照旧挺艰巨的。。。

不过好处是……
不反省数组边界,不检讨指针指向地址的状态,不检讨强制类型调换是还是不是足以拓宽。全靠技士程序的自觉,那一点使得C的代码效能会变得异常高。

因此说,C即便大量用来供给程序安全的场子,不过由于“未定义行为”的存在——C相对不是贰个康宁的言语!!

可是越多的情状是,之所以这么,所以才会更希望用C来完毕。

还会有一点亟待表达的是。。
最早阶这段:

int a=3;a+=a++;

差相当的少全体的今世编写翻译器的结果都为7。

特别GCD的一行算法,差非常少全部的今世编写翻译器都能健康运营。
纵然是“未定义算法”,那些也算默默的达到了一种合同了吗。
尽管,使用它们依然是非常惊险的。

正文由飞翔的鱼授权发布,文章作品权为原来的书文者全数。

【转】关于C的未定义行为,未定义行为

至于C的未定义行为

转自:

对于C的初学者的话,被供给做下边包车型大巴这种难题实在是脑残的不可能再脑残的一举一动。然则众多C初级教程——居然都有与上述同类的题。
最卓越的例证便是

a+=a++;

这种气象下,a最终毕竟等于多少了?

编译器应该怎么掌握a+=a++呢?首先是开展,a=a+a++;
接下来分别计算a和a++的值,把它们相加,然后把结果赋给a。
而是这里有几个主题素材,正是施行完a++之后,a++的值等于a本人的值,可是a的值却产生了a+1。
于是最重要是拍卖顺序。

比如说int a=3;
一经编写翻译器先总计赋值号+=左边a的值为3,然后总结左边a++的值为3,同一时候a变为4。
下一场计算3+3=6,赋给a,那么a以后的值正是6。
即使编写翻译器先总括赋值号侧边的a++,获得的结果为3,同有时候a变为4,然后总结左侧a=4。
随之总计4+3=7,于是7以此数被赋值给了a。

也正是说,区别的接头方法,在那几个例子里面竟然会获得分化的答案?

作者何以要用居然?难道那些结果不是不敢相信 无法相信的么?相同的表明式,只但是编写翻译器不均等,就搜查缉获了差别的结果,那真是个喜剧啊。
莫非未有何标准供给编写翻译器选用同样的知晓方式么?C语言的正儿八经遵循ANSI C标准。可是很不佳,ANSI C标准里面,并未关于蒙受这种情状应什么管理的明确,反而是提出,编写翻译器你望着办吧。
那正是C语言的“未定义行为”。

话说自个儿只是有在用四个GCD函数的时候被某大神狠狠的捉弄了,那几个GCD函数如下:

int GCD(int a,int b){
    while (a %= b ^= a ^= b ^= a);
    return b;
}

就疑似下边深入分析的那样,这段程序在编写翻译进程中,会并发什么样顺序,这也是专门的学业里面未有鲜明的,属于未定义行为。
据此用那几个函数并不一定能确认保证收获精确的结果。

 

这种业务嘛。。。既然是交给编译器的。
本身想以此实际上应该是为着代码优化。家谕户晓,C是三个极度另眼相待作用的言语,並且有这种为了效用舍弃一切的痛感,不评说那一个好不佳,反正人家在最受接待的言语排名的榜单第一人的宝座上坐了不亮堂有个别年了。
给编写翻译器越来越大的随便,编写翻译器就能够更加好的优化转移的二进制代码。
还会有其他的地点,比如越界数组。
就好像这么

char str1[]="myworld";
str1[18]='';

数组str1哪个地方来的第19项啊!!!这种事物居然能透过编写翻译!!!
运用越界数组也是C的多少个“未定义行为”。C的科班尚未确定编写翻译器在蒙受这种气象应该怎么做。那个时候编写翻译器的主张应该是——多一事不比少一事,笔者也不反省这里毕竟是或不是那些数组的限制了,反正你都叫本身写了,小编就写吧。

还应该有三个卓绝的操作就是同意二个随意指的指针的读写。
比如本身申请了贰个动态区域,然后释放掉了:

int *p;
p=(int *)malloc(4*sizeof(int));
/*各种对p的操作*/
free(p);
p[0]=0;
printf("%d%d%d%d",p[0],p[1],p[2],p[3]);

绝不夸张的说,笔者要好的前后相继往往死在这种地点,就是free未来再print。。。
再比如:

int *p;
p=0x1e642a80;
p[8]=24;

这种指针操作依旧也给通过????

更非常的是,上边包车型大巴那个都属于C的“未定义行为"正是说,尽管这么些操作能够扩充,不过编写翻译器并不保证试行结果。
正是说这种事物不仅仅不报错给通过了,并且还不依照大家想像的旗帜推行,而是由着编写翻译器的心性随意来?

从那么些角度看,真的是太苦逼了。
本人还超越过一段脑残代码,类似那样:

char tips[]="No";
if(condition){
    strcpy(tips,"Yes");
}

对这种东西。。。。。呵呵。在Windows下运作就等着被中断吧。。
还大概有使用未初叶化的变量也是一种“未定义行为”,比方:

int x;
printf("%d",x);

普通你也不精晓您会在荧屏上看看什么样。。。。
GCC的第一版编写翻译器在遇见这种状态的时候,会在你荧屏上开头二个小游戏。(那是付出组满满的恶心啊!!嗯,一定是!!)
C的变量并不会在注脚时(或第二遍采取前)被开始化,那么些特点受到大家诟病。
不过ANSI C本身自然是想经过轻巧那几个开始化操作,来进步一点周转速度。
到底要先导化三个大数组或是用malloc分配的一大堆空间,依然挺坚苦的。。。

可是好处是……
不检讨数组边界,不检讨指针指向地址的意况,不检查强制类型转变是不是足以扩充。全靠技术员程序的自愿,那点使得C的代码成效会变得异常高。

因而说,C尽管一大波用以要求程序安全的场面,然而由于“未定义行为”的存在——C相对不是一个平安的言语!!

唯独更加多的景观是,之所以如此,所以才会更愿意用C来贯彻。

还也是有有个别亟需验证的是。。
最开端那段:

int a=3;
a+=a++;

大致具备的当代编写翻译器的结果都为7。

非凡GCD的一整套算法,差非常少具备的今世编写翻译器都能正常运作。
虽说是“未定义算法”,这一个也算默默的达成了一种合同了啊。
虽说,使用它们依然是危险的。

本文由飞翔的鱼授权(和讯)发表,小说作品权为原来的文章者全部。

关于C的未定义行为 转自: 对于C的初学者的话,被须要做下边包车型地铁这种标题...

本文由贝博体育app发布于编程技术,转载请注明出处:关于C的未定义行为

关键词:

上一篇:没有了
下一篇:没有了