C语言常见问题.pdf

本文深入探讨了C语言中函数指针的调用方式、按引用传递的概念、枚举类型的特性、结构体内存偏移计算方法、内存分配函数calloc()与malloc()的区别,以及空指针的理解与使用技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 4.8 我看到了用指针调用函数的不同语法形式。到底怎么回事?
最初, 一个函数指针必须用* 操作符(和一对额外的括弧) “转换为” 一个“真
正的” 函数才能调用:
int r, func(), (*fp)() = func;
r = (*fp)();
而函数总是通过指针进行调用的, 所有“真正的” 函数名总是隐式的退化为指
针(在表达式中, 正如在初始化时一样。)。这个推论表明无论fp 是
函数名和函数的指针
r = fp();
ANSI C 标准实际上接受后边的解释, 这意味着* 操作符不再需要, 尽管依然
允许。

 

4.7 C 有“按引用传递” 吗?
真的没有。
严格地讲, C 总是按值传递。你可以自己模拟按引用传递, 定义接受指针的函
数, 然后在调用时使用& 操作符。事实上, 当你向函数传入数组(传入指针的情况
参见问题6.4 及其它) 时, 编译器本质上就是在模拟按引用传递。但是C 没有任何
真正等同于正式的按引用传递或C++ 的引用参数的东西。

 

 

 

2.16 枚举和一组预处理的#define 有什么不同?
只有很小的区别。C 标准中允许枚举和其它整形类别自由混用而不会出错。
(但是, 假如编译器不允许在未经明确类型转换的情况下混用这些类型,则聪明
地使用枚举可以捕捉到某些程序错误。)
枚举的一些优点: 自动赋值; 调试器在检验枚举变量时, 可以显示符号值; 它们
服从数据块作用域规则。(编译器也可以对在枚举变量被任意地和其它类型混用
时, 产生非重要的警告信息, 因为这被认为是坏风格。)一个缺点是程序员不能控
制这些对非重要的警告; 有些程序员则反感于无法控制枚举变量的大小。

 

 

2.12 如何确定域在结构中的字节偏移?
ANSI C 在<stddef.h> 中定义了offsetof() 宏, 用offsetof(struct s, f) 可以计
算出域f 在结构s 中的偏移量。如果出于某种原因, 你需要自己实现这个功能, 可
以使用下边这样的代码:
#define offsetof(type, f) ((size_t) /
((char *)&((type *)0)->f - (char *)(type *)0))
这种实现不是100% 的可移植; 某些编译器可能会合法地拒绝接受。

 

 

7.26 calloc() 和malloc() 有什么区别?利用calloc 的零填充功能安
全吗?free() 可以释放calloc() 分配的内存吗, 还是需要一个
cfree()?
calloc(m, n) 本质上等价于
p = malloc(m * n);
memset(p, 0, m * n);
填充的零是全零, 因此不能确保生成有用的空指针值或浮点零值(参见第5
章)。free() 可以安全地用来释放calloc() 分配的内存。

 

5.12 我很困惑。我就是不能理解这些空指针一类的东西。
有两条简单规则你必须遵循:
1. 当你在源码中需要空指针常数时, 用“0” 或“NULL”。
2. 如果在函数调用中“0” 或“NULL” 用作参数, 把它转换成被调函数需要的指
针类型

 

5.13 考虑到有关空指针的所有这些困惑, 难道把要求它们内部表达都必
须为0 不是更简单吗?
因为它会不必要地限制某些实
现, 阻止它们用特殊的非全零值表达空指针, 尤其是当那些值可以为非法访问引发
自动的硬件陷阱的时候。
况且, 这样的要求真正完成了什么呢?对空指针的正确理解不需要内部表达
的知识, 无论是零还是非零。假设空指针内部表达为零不会使任何代码的编写更
容易(除了一些不动脑筋的calloc() 调用; 参见问题7.26)。用零作空指针的内部表
达也不能消除在函数调用时的类型转换, 因为指针的大小可能和int 型的大小依然
不同。(如果象上文问题5.11 所述, 用“nil” 来请求空指针, 则用0 作空指针的内
部表达的想法都不会出现。)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值