预处理练习题

文章目录

    • 1.预处理指令
    • 2.预定义符号
    • 3.C程序-->可执行程序
      • 1.预处理:只处理#开头语句
      • 2.编译:只校验语法
      • 3.链接:链接时找实体
    • 4.#define与typedef
    • 5.C语言头文件中ifndef/define/endif
    • 6.宏定义
    • 7.宏和函数
    • 8.条件编译指令与宏
    • 9.头文件
    • 10.交换奇偶位
    • 11.offsetof宏
      • 用途:
      • 原型:
      • 应用:

1.预处理指令

#define执行查找替换
#if区分是否编译
#undef反定义,取消#define宏定义的东西
只有#endif没有#end

2.预定义符号

FILE 打印所在文件
TIME 打印编译时间
__DATE__打印编译日期
LINE 行号
FUNCTION 函数名
__MAIN__不存在

3.C程序–>可执行程序

编辑—预处理—编译—链接

1.预处理:只处理#开头语句

根据预处理指令组装新C/C++程序。产生一个没有头文件(被展开)、宏定义(被替换),没有条件编译指令(被屏蔽),没有特殊符号的输出文件,这个文件的含义同原本的文件无异,只是内容有所不同。***总结: ***将源程序文件进行处理,生成中间文件,编译系统对其进行编译生成目标代码。

2.编译:只校验语法

将预处理完文件逐一进行一系列词法分析、语法分析、语义分析及优化后,产生相应汇编代码文件。编译是针对单个文件编译的,只校验本文件语法是否有问题,不负责寻找实体。

3.链接:链接时找实体

通过链接器将一个个目标文件(或许还会有库文件)链接在一起生成一个完整的可执行程序。 链接程序的主要工作就是将有关的目标文件彼此相连接,也就是将在一个文件中引用的符号同该符号在另外一个文件中的定义连接起来,使得所有的这些目标文件成为一个能够被操作系统装入执行的统一整体。在此过程中会发现被调用的函数未被定义。需要注意的是,链接阶段只会链接调用了的函数/全局变量,如果存在一个不存在实体的声明(函数声明、全局变量的外部声明),但没有被调用,依然是可以正常编译执行的。

4.#define与typedef

#define P int*
typedef int* p;
P a,b;//int *a,b;
p c,d;//int *c,*d;

故b不是指针类型

5.C语言头文件中ifndef/define/endif

防止头文件重复引用

6.宏定义

#define N 4
#define Y(n) ((N+2)*n) 
/*这种定义编程规范中严格禁止*/
z = 2 * (N + Y(5+1));
//Y----( (N+2)*5+1 )
z==70;

7.宏和函数

  1. 函数可以递归,宏不能递归
  2. 函数参数有类型检查,宏参数无类型检查
  3. 宏通过替换完成,操作符优先级影响宏求值,使用括号明确优先级
  4. 函数的执行速度更快,宏的执行速度慢(×) 宏不存在执行速度

8.条件编译指令与宏

  • 条件编译指令:

#if、#ifdef,#ifndef,#else,#elif、#endif
#if defined(xxx)

  • #define:宏定义
  • #pragma:一个复杂的预编译语句
  • #error:报错

9.头文件

  1. #include“filename.h”,编译器寻找头文件从当前编译的源文件所在目录去找(先从当前目录找,再去库里找)
  2. #include”,编译器寻找头文件从通过编译选项指定的库目录去找
  3. 大型项目开发,把所有自定义数据类型、函数声明放在一个头文件中,各个源文件只需要包含这个头文件,省去写很多#include语句麻烦,是好的编程习惯。//分类放在不同的头文件并根据特点命名是更好选择,方便代码管理和维护.
  4. 多个源文件同时用到的全局整数变量,它的声明和定义都放在头文件中,是好的编程习惯(×)

头文件不能定义全局变量,否则如果有多个文件,那链接时会冲突

10.交换奇偶位

写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。

#define Swap(n) 
(((n) & 0x55555555) << 1 | ((n) & 0xaaaaaaaa) >> 1)

此宏只能完成32位以内整形,完成64位将5和a的数量翻倍

11.offsetof宏

offsetof-宏

用途:

计算结构体成员相对于起始位置的偏移量

原型:

#include

size_t offsetof(structName,member name);

应用:

struct S3
{          //偏移量(所放位置)
double d;  //0-7
char c;    //8
int i;     //12-15      //最大对齐数为8
}s3;//16
printf("%u",offsetof(struct S3,d));//0  8  12

写一个宏,计算结构体中某变量相对于首地址的偏移,并给出说明

typedef struct Stu
{
    char name;
}S;
#define offsetof(S, name) (size_t)&( ( (S *)0 ) ->name   )

1、0转换为结构体类型指针—>某个结构体首地址是0。此时每一个成员偏移量成了相对0偏移量,这样不需要减去首地址
2、对该指针访问其成员,取出地址,由于结构体起始地址为0,此时成员偏移量直接相当于对0的偏移量,所以得到的值直接就是对首地址的偏移量。
3、取出该成员的地址,强转成size_t打印,求出偏移量。

你可能感兴趣的:(C语言经典题目,c++,开发语言,c语言)