一、字符和字符串

1. Q:为什么strcat(string, '!')不行?

A:strcat()用于拼接字符串,所以应该写成strcat(string, "!")。"!"实际上包含两个字符:'!'和'\0'。

2. Q:为什么不能这样检查一个字符串是否跟某个值匹配?

char *string;
...
if (string == "value") {
/* string matches "value"*/
}

A:C语言中的字符串用字符的数组表示,C语言不会把数组作为一个整体来操作(赋值、比较等)。上面代码段的==操作符实际上比较的是两个指针是否相等,要比较两个字符串,一般使用库函数strcmp()。

3. Q:我正开始考虑多语言字符集的问题,是否有必要担心sizeof(char)会被定义为2,以便表达16位的字符集呢?

A:就算char型被定义为16位,sizeof(char)依然是1(sizeof是以char的大小作为一个单位的),而<limits.h>中的CHAR_BIT会被定义为16,届时将不能声明(或用malloc分配)一个8位的对象。

二、布尔表达式和变量

1. Q:C语言中布尔值该用什么类型?为什么它不是一个标准类型?

A:C语言中没有提供标准的布尔类型,部分原因在于选择一个这样的类型设计最好有程序员来决定的空间/时间折中。(使用int型可能更快,使用char型可能更节省数据空间。然而,如果需要和int型反复转换,那么更小的类型也可能生成更大或更慢的代码。)可以使用#define或枚举常量定义真假,无伤大雅。

#define TRUE  1
#define FALSE 0 enum bool {false, true};

2. Q:我使用了来自两个不同的第三方库的头文件,它们都定义了相同的宏,如TRUE, FALSE, Min(), Max()等,但是它们的定义相互冲突,怎么办?

A:这是个典型的命名空间问题。理想状态下,第三方库的厂商在定义符号(预处理库、全局变量和函数名称)的时候应该尽责地确保不会发生命名空间冲突,最好的解决方案是让厂商修改他们的头文件。作为一种迂回措施,你也可以在发生冲突的#include指令之间解除或重新定义冲突的宏。

三、C预处理器

1. 如果一个参数在宏扩展中出现了多次,而实参是带副作用的表达式,则宏可能不能正确运行。

#define square(x) ((x) * (x))
square(i++); //会被扩展为((i++)*(i++)),而这是未定义的

2. Q:如何书写多语句宏?

A:通常的目标时能够像一个包含函数调用的表达式语句一样调用宏:MACRO(arg1, arg2); 这意味着“调用者”需要提供最终的分号,而宏体不需要。因此宏体不能为简单的括号包围的复合语句,因为这个宏可能会用于带else的if/else语句的if分支。传统的解决方法是使用do-while语句。

#define MACRO(arg1, arg2) {stmt1; stmt2;}
if (cond)
MACRO(arg1, arg2);
else /* some other code*/ /*宏展开后,用户提供的最终的分号就会成为语法错误*/
if (cond)
{stmt1; stmt2;};
else /* some other code */ /* 传统的解决方案 */
#define MACRO(arg1, arg2) do { \
stmt1;
stmt2;
...
} while()

如果宏体内的语句都是简单语句(没有声明或循环),那么还有一种技术,就是写一个使用一个或多个逗号操作符的表达式,放在括号中:

#define FUNC(arg1, arg2) (expr1, expr2. expr3)  // FUNC返回expr3

有些编译器(如gcc)可以使用非标准的“inline”关键字或其他扩展自动地或根据程序员的请求使用内联扩展小函数。

3. Q:应该把哪些内容放在.h文件?哪些内容放在.c文件?

A:作为一般规则,应该把下面所列的内容放入头文件:(a)宏定义;(b)结构、联合和枚举声明;(c)typedef声明;(d)外部函数声明;(e)全局变量声明。

另一方面,如果定义或声明为一个源文件私有,则最好留在该文件中(并声明为static)。最后,不能把实际的代码或全局变量放在头文件中。

4. Q:可以在一个头文件中包含另一个头文件吗?

A:这是个风格问题。反对者认为,“嵌套包含文件”应该避免,因为它让相关定义更难找到。如果一个文件被包含了两次,它会导致重复定义错误,同时它也会令Makefile的人工维护十分困难。支持者认为,“嵌套包含文件”使模块化使用头文件成为可能(一个头文件可以包含它所需要的一切,而不是让每个源文件都包含需要的头文件)。而自动的Makefile维护工具可以很容易地处理嵌套包含文件的依赖问题。一种流行的头文件定义技巧:

#ifndef __HFILENAME_H__
#define __HFILENAME_H__
...
#endif

5. Q:完整的头文件搜索规则是怎样的?

A:准确的行为是由实现定义的(一般应该有文档说明)。通常,用<>命名的头文件会先在一个或多个标准位置搜索,用""命名的头文件会首先在“当前目录”搜索,如果没有找到再在标准位置搜索。注意“当前目录”的定义不唯一:传统上当前目录是包含#include指令的文件所在的目录,而在其他编译器下,当前目录是编译器启动的目录。

6. Q:sizeof操作符可以用在#if预处理指令中吗?

A:不行。预处理在编译过程之前进行,此时尚未对类型名称进行分析。作为替代,可以考虑使用ANSI的<limits.h>中定义的常量,或者使用配置脚本。当然,更好的方法是编写与类型大小无关的代码。

7. Q:如何用#if表达式来判断机器是高字节在前还是低字节在前?

A:恐怕不能。判断机器字节顺序的代码技术通常都要用到字符数组或联合,但预处理运算仅仅使用长整型,而且没有寻址的概念。另外,通常写出与字节顺序无关的代码更好。

《你必须知道的495个C语言问题》读书笔记之第8-10章:字符串、布尔类型和预处理器的更多相关文章

  1. 你必须知道的495个c语言问题(笔记)

    1.1我该如何决定使用哪种整数类型? 用到较大的数用long:空间很重要(例如有很大的数组或很多的结构)用short:此外用int. win32: int 32bit    4byte char 8b ...

  2. 你必须知道的495个C语言问题,学习体会一

    C语言作为一门古老的语言,其灵活性和容易出错都让人 又爱又恨,书籍<你必须知道的495个C语言问题>,使用问答的形式,告诉读者 C语言使用的各个方面的知识,包括一些冷知识等.以下,我要摘录 ...

  3. C语言学习书籍推荐《你必须知道的495个C语言问题》

    萨米特 (Steve summit) (作者), 孙云 (译者), 朱群英 (译者) 下载地址:点我 <你必须知道的495个C语言问题>以问答的形式组织内容,讨论了学习或使用C语言的过程中 ...

  4. 《你必须知道的495个C语言问题》知识笔记及补充

    1. extern在函数声明中是什么意思? 它能够用作一种格式上的提示表明函数的定义可能在还有一个源文件里.但在 extern int f(); 和 int f(); 之间并没有实质的差别. 补充:e ...

  5. 《你必须知道的495个C语言问题》读书笔记之第11-14章:ANSI C标准、库函数、浮点数

    一.ANSI C标准 1. ANSI向C语言预处理器引入了几项新的功能,包括“字符串化”操作符(#).“符号粘贴”操作符(##).#pragma指令. 2. Q:char a[3] = "a ...

  6. 《你必须知道的495个C语言问题》读书笔记之第1-2章:声明和初始化

    1. C标准中并没有精确定义数值类型的大小,但作了以下约束: (1) char类型可以存放小于等于127的值: (2) short int和int可以存放小于等于32767的值: (3) long i ...

  7. 你必须知道的495个C语言问题,学习体会四

    本文,我们来学习下指针,这是个梦魇啊.无数次折磨着C语言学习者,无数次的内存泄露,无数次的访问失败,无数次的越界溢出, 这些错误造就的仅仅是一个 跟随者,真正的优秀者必须要正视语言的局限,同时在最大限 ...

  8. 你必须知道的495个C语言问题,学习体会三

    本文是 本系列的第三篇,本文主要对C语言的表达式做个小结 先从两个坑爹的表达式说起:i++ 与++i 上大学的时候,学长告诉我,这两个表达式,意义是一样的,后来老师纠正说,还是有区别的,于是让我们记住 ...

  9. 你必须知道的495个C语言问题,学习体会二

    这是本主题的第二篇文章,主要就结构体,枚举.联合体做一些解释 1.结构体 现代C语言编程 结构化的基石,diy时代的最好代言人,是面向对象编程中类的老祖宗. 我们很容易定义一个结构体,比如学生: st ...

随机推荐

  1. mybatis collection

    转自:http://blog.csdn.net/wj3319/article/details/9025349 在SQL开发过程中,动态构建In集合条件查询是比较常见的用法,在Mybatis中提供了fo ...

  2. Kafka 消息队列系列之分布式消息队列Kafka

    介绍 ApacheKafka®是一个分布式流媒体平台.这到底是什么意思呢?我们认为流媒体平台具有三个关键功能:它可以让你发布和订阅记录流.在这方面,它类似于消​​息队列或企业消息传递系统.它允许您以容 ...

  3. 富文本编辑器粘贴word内容

    很多时候我们用一些管理系统的时候,发布新闻.公告等文字类信息时,希望能很快的将word里面的内容直接粘贴到富文本编辑器里面,然后发布出来.减少排版复杂的工作量. 下面是借用百度doc 来快速实现这个w ...

  4. 【线性代数】7-3:对角化和伪逆(Diagonalization and the Pseudoinverse)

    title: [线性代数]7-3:对角化和伪逆(Diagonalization and the Pseudoinverse) categories: Mathematic Linear Algebra ...

  5. CF1153F Serval and Bonus Problem 【期望】

    题目链接:洛谷 作为一只沉迷数学多年的蒟蒻OIer,在推柿子和dp之间肯定要选推柿子的! 首先假设线段长度为1,最后答案乘上$l$即可. 对于$x$这个位置,被区间覆盖的概率是$2x(1-x)$(线段 ...

  6. element-ui遮罩层el-dialog的使用

    template <el-button type="text" @click="dialogVisible = true">点击打开 Dialog& ...

  7. Try-Catch-Finally代码块中的return

    测试类的原型是这样子的 public class TryCatchFinallyToReturn { public static void main(String[] args) { System.o ...

  8. 一、docker安装CentOS7

    一.安装步骤 前提条件 Docker运行在CentOS7上,要求系统64位.系统内核版本为3.10以上. Docker是一个进程,一启动就两个进程,一个服务,一个守护进程.占用资源就非常少,启动速度非 ...

  9. Reconnect due to socket error java.nio.channels.ClosedChannelException

    storm整合kafka后出现如下异常: 错误原因:有部分kafka服务器连接不上导致,检查一下是不是每个kafka都能连接到(有的kafka配置使用的是host,记得配置相同的环境) 造成异常代码段 ...

  10. zabbix :web 界面显示的监控项值为0或者空

    [参考文章]:[错误汇总]zabbix_get 的值一直为 0 1. 问题现象 zabbix 版本:3.4: server 端部署在 192.168.145.134 ,agent 节点部署在 192. ...