12个滑稽的C语言面试问答——《12个有趣的C语言问答》评析(3)
前文链接:http://www.cnblogs.com/pmer/p/3322429.html
5,atexit with _exitQ:在以下代码,atexit()方法并没有被调用,你知道为什么吗?
#include<stdio.h>
void
func(
void
)
{
printf
(
"\n Cleanup function called \n"
);
return
;
}
int
main(
void
)
{
int
i = 0;
atexit
(func);
for
(;i<0xffffff;i++);
_exit(0);
}
A:这是因为使用了 _exit() 方法。此方法并没有调用清除数据相关的方法,比如 atexit()等。
Answer: This behavior is due to the use of function _exit(). This function does not call the clean-up functions like atexit() etc. If atexit() is required to be called then exit() or ‘return’ should be used.
评:
这个Answer没什么问题。不过_exit()函数只是一个系统函数而非编译器提供的库函数。C99之后增加了这个库函数,名为_Exit()。【感谢madoldman网友指正】
这里稍微解释一下atexit()。这个函数的功能是注册在程序结束时自动调用的函数。一旦程序调用exit()函数或main()通过renturn语句结束程序,通过atexit()注册的函数将得到调用执行。可以注册多个函数,最后调用的次序与注册次序是相反的。
与_Exit()类似,调用abort()函数结束程序时,atexit()注册的函数同样也不会被调用执行。
6,void* 与 C 结构体
Q:能否设计一个方法接受任意类型的参数然后返回整数?同时是否有办法传递多个这样的参数?
A:一个能接受任意类型参数的方法像下面这个样子:
int
func(
void
*ptr)
如果需要传递多个参数,那么我们可以传递一个包含这些参数的结构体
Answer: A function that can accept any type of argument looks like :
int func(void *ptr)
if more than one argument needs to be passed to this function then this function could be called with a structure object where-in the structure members can be populated with the arguments that need to be passed.
评:
接受“任意类型的参数”( 原文:Can you design a function that can accept any type of argument and returns an integer? )的函数在C语言中是不存在的,这个问题的要求本身就很扯蛋。
从后面的Answer看,问题的意思是任意种类的指针类型,但是从实用的角度来说,int func(void *ptr)这种函数基本没有任何意义,几乎不可能存在。因为函数仅仅接受一个void *类型的参数,根本就不可能对这个参数做什么有实际意义的操作(唯一有意义的例外是free() )。理由很简单,void *类型的指针只有赋值和类型转换这两种运算。
正因为如此,所以凡是接受void *类型参数的函数,通常必定还要有一个size_t类型的参数。例如
至于“如果需要传递多个参数,那么我们可以传递一个包含这些参数的结构体”,则更是一种异想天开的天方夜谭,没有半点可操作性。
7,* 与 ++ 操作符
Q:以下代码将输出什么?为什么?
#include<stdio.h>
int
main(
void
)
{
char
*ptr =
"Linux"
;
printf
(
"\n [%c] \n"
,*ptr++);
printf
(
"\n [%c] \n"
,*ptr);
return
0;
}
A:以上的输出将是:
因为++与 * 的优先级一样,所以 *ptr++ 将会从右向左操作。按照这个逻辑,ptr++ 会先执行然后执行*ptr。所以第一个结果是’L'。也因为 ++ 被执行了,所以下一个printf() 结果是’i'。
Answer: The output of the above would be :
[L]
[i]
Since the priority of both ‘++’ and ‘*’ are same so processing of ‘*ptr++’ takes place from right to left. Going by this logic, ptr++ is evaluated first and then *ptr. So both these operations result in ‘L’. Now since a post fix ‘++’ was applied on ptr so the next printf() would print ‘i’.
评:
中译本这回漏掉了原文中的一些东西——程序的输出。
Answer中解释说 ++ 和 * 的优先级一样是错误的。后缀++运算符的优先级高于一元*运算符。
“ptr++ 会先执行然后执行*ptr”这个解释同样荒唐,无法自圆其说。因为既然先执行ptr++,那么ptr应该指向了L后面的i,然后执行*ptr应该得到i,但实际上得到的却是L。显然,这个推理过程中有毛病,作者自己都没搞清楚究竟是怎么回事。这个推理过程中的毛病就是所谓的“先执行”、“后执行”的说法。
(未完待续)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架