12个滑稽的C语言面试问答——《12个有趣的C语言问答》评析(5)

前文链接:http://www.cnblogs.com/pmer/archive/2013/09/17/3327262.html

A,局部变量的返回地址

Q:下面的代码有问题吗?如果有,如何修改?

#include<stdio.h>
 
int* inc(int val)
{
  int a = val;
  a++;
  return &a;
}
 
int main(void)
{
    int a = 10;
 
    int *val = inc(a);
 
    printf("\n Incremented value is equal to [%d] \n", *val);
 
    return 0;
}

A:虽然上面的代码有时运行会很好,但是在方法 inc() 中有很严重的隐患。当inc()方法执行后,再次使用局部变量的地址就会造成不可估量的结果。解决之道就是传递变量a的地址给main()。

Answer: Though the above program may run perfectly fine at times but there is a serious loophole in the function ‘inc()’. This function returns the address of a local variable. Since the life time of this local variable is that of the function ‘inc()’ so after inc() is done with its processing, using the address of its local variable can cause undesired results. This can be avoided by passing the address of variable ‘a’ from main() and then inside changes can be made to the value kept at this address.

评:

  这个主要是翻译的问题。对照一下原文就会发现,译文不但漏掉了很多内容没有翻译,最严重的是把“by passing the address of variable ‘a’ from main()”给翻译成了“传递变量a的地址给main()”,彻底颠覆了原文的意思。原意是传递main()中变量a的地址,即调用形式为int(&a),而译文的意思依然是代码中那种错误写法的描述。

B,处理 printf() 参数

Q:以下代码输出请问是什么?

#include<stdio.h>
 
int main(void)
{
    int a = 10, b = 20, c = 30;
 
    printf("\n %d..%d..%d \n", a+b+c, (b = b*2), (c = c*2));
 
    return 0;
}

A:输出将是

1 110..40..60

这是因为参数都是从右向左处理的,然后打印出来却是从左向右。

Answer: The output of the above code would be :

110..40..60

This is because the arguments to the function are processed from right to left but are printed from left to right.

评:

  这个问题和解答都很狗血!

  “参数都是从右向左处理的”是无中生有。C标准规定

  The order of evaluation of the function designator, the actual arguments, and subexpressions within the actual arguments is unspecified, but there is a sequence point before the actual call.

  也就是说实参的求值次序没做规定(unspecified),编译器可以自己安排计算次序,无论怎样安排都不违背标准。从右向左或从右到左都可以。断言“参数都是从右向左处理”,是这个解答中第一个错误。

  前面引用条文中还提到了在实际调用前存在一个序点(sequence point),对于代码中

printf("\n %d..%d..%d \n", a+b+c, (b = b*2), (c = c*2))

这个函数调用来说,前一个序点就是之前的“;”。

  C语言的另一个规定是:

  Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression.Furthermore, the prior value shall be read only to determine the value to be stored.

  这两句话是什么意思呢?前一句说的是两个相邻序点之间,一个数据对象的值最多可以改变一次。如果改变多次,就是未定义行为。譬如写出下面代码

printf("%d,%d,%d,%d\n", ++i, --i, i++, i--);

就是出于典型的对未定义行为的无知。而津津乐道、煞有介事地讨论这种根本没有意义的代码(i++和++i作为参数时的编译器处理方式分析~) ,就如同谭浩强津津乐道地讨论a+=a-=a*a一样荒唐(参见“牙里长嘴”和“a+=a-=a*a” ),我擦,岂不是滑天下之大稽?只有根本没有技术能力又缺乏自知之明的怨妇,才可能无聊到做这种荒谬无价值的事情。

  标准条文中的后面一句有些晦涩,它的意思是数据对象中先前的值只能是用来确定数据对象中后来存储的值,例如:

int i = 1;
i = i + 1 ;

  i只改变了一次,且i的原值(1)用来确定i后来存储的值(2)。

  如果数据对象的值在两个序点之间只改变一次,且数据对象的原值不是用来确定数据对象后来的值,例如:

int i = 1 , j ;
j = i + (i = 2) ;

则属于未定义行为。因为表达式中第一个i的值不是为了确定i将要存储的值。没人说的清这个i + (i = 2) 这个表达式的值应该是4还是3。

  回过头再看问答代码中的

printf("\n %d..%d..%d \n", a+b+c, (b = b*2), (c = c*2));

b和c都被改变一次,但由于在表达式a+b+c中,b和c的值不是用来确定b和c最终的值,因此这段代码属于没有意义的未定义行为。

  因此,这个问答一共错了两处。一处是说“参数都是从右向左处理的”,另一处就是代码行为未定义。

(全文完)

 
 
 
标签: C语言面试

C语言面试问答5的更多相关文章

  1. C语言面试问答(3)

    12个滑稽的C语言面试问答——<12个有趣的C语言问答>评析(3) 前文链接:http://www.cnblogs.com/pmer/p/3322429.html 5,atexit wit ...

  2. 12个滑稽的C语言面试问答——《12个有趣的C语言问答》评析(5)

    前文链接:http://www.cnblogs.com/pmer/archive/2013/09/17/3327262.html A,局部变量的返回地址 Q:下面的代码有问题吗?如果有,如何修改? # ...

  3. .NET面试问答集锦

    程序员级别鉴定书(.NET面试问答集锦) 提供避免元素命名冲突的方法 DOM适合的使用场景是什么?是否有尺寸限制? DOM是一种与浏览器,平台,语言无关的接口,使你可以访问页面其他的标准组件. DOM ...

  4. .net面试问答

    转载自:https://www.cnblogs.com/dingfangbo/p/5768991.html .net面试问答(大汇总)   原文://http://blog.csdn.net/weny ...

  5. 电话面试问答Top 50 --[伯乐在线]

    今年是2015年,在过去几年中,电面(电话面试)是筛选程序员职位候选人的最流行的方式.它让雇佣双方很容易互相了解对方,候选人不需要去未来雇主的所在地,面试官也不用做额外的安排.这是我介绍程序员面试问题 ...

  6. 常见的25个python面试问答

    常见的25个python面试问答 说到好用简洁的大数据技术,除了Hadoop.R等等,Python也是其中熠熠生辉的一员,因而广受企业和商家的青睐.求职季,不少应聘者在面试相关职业时都被要求掌握Pyt ...

  7. 面试宝典之基本的C#面试问答

    下文是100个基本的C#面试问答清单.这些面试问题简单.直接了当,涵盖了C#最基本的概念,大部分和面向对象的概念相关.所以如果你在准备C#面试,我建议你必须掌握这100个基本的C#面试问答来复习你的C ...

  8. JAVA多线程和并发基础面试问答(转载)

    JAVA多线程和并发基础面试问答 原文链接:http://ifeve.com/java-multi-threading-concurrency-interview-questions-with-ans ...

  9. 10个经典的C语言面试基础算法及代码

    10个经典的C语言面试基础算法及代码作者:码农网 – 小峰 原文地址:http://www.codeceo.com/article/10-c-interview-algorithm.html 算法是一 ...

随机推荐

  1. 6天通吃树结构—— 第三天 Treap树

    原文:6天通吃树结构-- 第三天 Treap树 我们知道,二叉查找树相对来说比较容易形成最坏的链表情况,所以前辈们想尽了各种优化策略,包括AVL,红黑,以及今天 要讲的Treap树. Treap树算是 ...

  2. CSS hack 如何区分所有IE浏览器和非IE浏览器

    网上方法很多,例如,测试后得出以下结论,多余的话不说了,直入主题: 1.所有的推理IE浏览器 正解:此写法仅仅被lE浏览器识别,非IE浏览器不识别. <!--[if IE]> <st ...

  3. Net社区虚拟大会

    微软“.Net社区虚拟大会”dotnetConf2015:关键词:.NET 创新.开源.跨平台 去年 11 月的时候,微软开源了 .NET CoreFX,然后是今年 2 月份的 .NET CoreCL ...

  4. 【剑指offer】Q32:从1至n整1出现的次数(python)

    def q32(n, len): if n < 0: return 0 elif n <= 1: return n total = 0 while n > 0: if n >= ...

  5. c#登录时保存账号密码到cookie

    登陆界面有用户名.密码输入框,一个’记住账号密码‘的复选框. 1.登录时,勾选‘记住账号密码‘复选框,则会把用户名密码保存在客户端cookie里,保存时间为最大值(直到用户清除浏览器缓存或者取消勾选’ ...

  6. C#JSON序列化与反序列化

    原文:C#JSON序列化与反序列化 windows phone学习也有一段时间了,想要做一个新闻客户端练练手,于是就在网上找看有没有接口之类.在天狗播客找到了热点热词新闻资讯API开放接口,接口提供的 ...

  7. SSRS (SQL Server Report Service) 在IE9, IE10下显示不全的解决办法

    原文:SSRS (SQL Server Report Service) 在IE9, IE10下显示不全的解决办法 在做项目的过程中遇到SSRS与IE9, IE10不兼容的情况,具体表现为报表页面在IE ...

  8. MVC 分页1 标准的url分页

    一. 将mvcpager ddl 引用到web服务项目中. 二. 在view加入 <%@ Import Namespace="Webdiyer.WebControls.Mvc" ...

  9. asp.net如何实现word文档在线预览

    原文:asp.net如何实现word文档在线预览 实现方式:office文档转html,再在浏览器里面在线浏览 1.首先引入com组件中office库,然后在程序集扩展中引入word的dll 2.将M ...

  10. 手工配置Service的过程中。

    正在使用srvctl创建service时间,需要注意TAF政策选择必须是dbms_service套餐配置.下面的例子演示了如何创建一个服务felix_ora: 1.查看现有的创建之前系统service ...