c语言的头文件、宏、指针
#include命令
#include
是文件包含命令,主要用来引入对应的头文件。#include
的处理过程很简单,就是将头文件的内容插入到该命令所在的位置,从而把头文件和当前源文件连接成一个源文件,这与复制粘贴的效果相同。
#include有两种使用方式:
#include <stdio.h> #include "myHeader.h"
使用尖括号< >
和双引号" "
的区别在于头文件的搜索路径不同:包含标准库的头文件建议用尖括号,包含自定义的头文件建议用双引号。
- 一个#include命令只能包含一个头文件,多个头文件需要多个#include命令。
- 文件包含允许嵌套,也就是说在一个被包含的文件中又可以包含另一个文件。
宏定义
#define 宏名 字符序列
#
表示这是一条预处理命令,所有的预处理命令都以#开头。define
是预处理命令。宏名
是标识符的一种,命名规则和标识符相同。字符序列
可以是常数、表达式等。
宏定义的几点说明
- 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的替换。字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查,如有错误,只能在编译已被宏展开后的源程序时发现。
- 宏定义不是说明或语句,在行末不必加分号,如加上分号则连分号也一起替换。
- 宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用
#undef
命令。#define A 123 #undef A A只在从定义到undef之间有效
宏定义表示数据类型和用typedef定义数据说明符的区别。
宏定义只是简单的字符串代换,是在预处理完成的,而typedef是在编译时处理的,它不是作简单的代换,而是对类型说明符重新命名。被命名的标识符具有类型定义说明的功能。
#define PIN1 int * typedef int *PIN2; //也可以写作typedef int (*PIN2);
从形式上看这两者相似, 但在实际使用中却不相同。
下面用PIN1,PIN2说明变量时就可以看出它们的区别:
PIN1 a,b;
在宏代换后变成:
int *a,b;
表示a是指向整型的指针变量,而b是整型变量。然而:
PIN2 a,b;
表示a、b都是指向整型的指针变量。因为PIN2是一个类型说明符。
由这个例子可见,宏定义虽然也可表示数据类型, 但毕竟是作字符代换。在使用时要分外小心,以避出错。http://c.biancheng.net/cpp/html/65.html
int a = 100; a 是一个变量,用来存放整数,需要在前面加&
来获得它的地址;
char str[20] = "abcdefg"; str 本身就表示字符串的首地址,不需要加&
。
printf("%#X, %#X\n", &a, str); %#X
表示以十六进制形式输出,并附带前缀0X
。
定义指针变量
定义指针变量与定义普通变量非常类似,不过要在变量名前面加星号*
,格式为:
datatype *name; 或者 datatype *name = value;
*
表示这是一个指针变量,datatype
表示该指针变量所指向的数据的类型 。例如:
int *p1;
p1 是一个指向 int 类型数据的指针变量,至于 p1 究竟指向哪一份数据,应该由赋予它的值决定。再如:
int a = 100;
int *p_a = &a;
在定义指针变量 p_a 的同时对它进行初始化,并将变量 a 的地址赋予它,此时 p_a 就指向了 a。值得注意的是,p_a 需要的一个地址,a 前面必须要加取地址符&
,否则是不对的。
1 //定义普通变量 2 float a = 99.5, b = 10.6; 3 char c = '@', d = '#'; 4 //定义指针变量 5 float *p1 = &a; 6 char *p2 = &c; 7 //修改指针变量的值 8 p1 = &b; 9 p2 = &d;
*
是一个特殊符号,表明一个变量是指针变量,定义 p1、p2 时必须带*
。而给 p1、p2 赋值时,因为已经知道了它是一个指针变量,就没必要多此一举再带上*
,后边可以像使用普通变量一样来使用指针变量。
也就是说,定义指针变量时必须带*
,给指针变量赋值时不能带*
。
指针变量也可以连续定义,如:int *a, *b, *c; //a、b、c 的类型都是 int*。
每个变量前面都要带*
。如果写成int *a, b, c;,那么只有 a 是指针变量,b、c 都是类型为 int 的普通变量。
定义指针变量时的*
和使用指针变量时的*
意义完全不同。以下面的语句为例:
- int *p = &a;
- *p = 100;
第1行代码中*
用来指明 p 是一个指针变量,第2行代码中*
用来获取指针指向的数据。
需要注意的是,给指针变量本身赋值时不能加*
。修改上面的语句:
- int *p;
- p = &a;
- *p = 100;
第2行代码中的 p 前面就不能加*
。
关于 * 和 & 的谜题
假设有一个 int 类型的变量 a,pa 是指向它的指针,那么*&a
和&*pa
分别是什么意思呢?*&a
可以理解为*(&a)
,&a
表示取变量 a 的地址(等价于 pa),*(&a)
表示取这个地址上的数据(等价于 *pa),绕来绕去,又回到了原点,*&a
仍然等价于 a。&*pa
可以理解为&(*pa)
,*pa
表示取得 pa 指向的数据(等价于 a),&(*pa)
表示数据的地址(等价于 &a),所以&*pa
等价于 pa。
对星号*
的总结
在我们目前所学到的语法中,星号*
主要有三种用途:
- 表示乘法,例如
int a = 3, b = 5, c; c = a * b;
,这是最容易理解的。 - 表示定义一个指针变量,以和普通变量区分开,例如
int a = 100; int *p = &a;
。 - 表示获取指针指向的数据,是一种间接操作,例如
int a, b, *p = &a; *p = 100; b = *p;
。
int aa = 97;
int bb = 98;
int *paa = &aa;
printf("%c\n",*paa);
*paa = 99;
printf("%c\n",paa);
paa = bb;
printf("%c\n",paa);
运行结果 a c b