C语言预处理,结构体
C语言预处理命令
1.宏定义
1.无参数宏
#define 标识符 字符串 #代表本行是编译预处理命名 习惯上,宏定义大写 代替一个字符串,介绍重复书写某个字符串的工作量 有意义的宏代表无规律的字符串,增强可读性 范围:宏定义开始到本源程序文件结束,可以使用#undef提前终止作用范围 宏定义允许嵌套,前面定义了的宏可以被后面的宏使用
2.有参数宏
#define 标识符(形参表) 字符串 #include<stdio.h> #define MAX(x, y) (x > y ? x : y) int main (){ , b = , max ; //MAX(a ,b)被宏替代 max = MAX(a , b); printf("max=%d",max); } 宏名与形参表的圆括号之间不能有空格 字符串内的形参最好用括号括起来 #define MUL(x, y) x*y c = MUL(a+,b+); ==> a+*y+ 应该为(a+)*(b+) 所以:#define MUL(x,y) (x)*(y) 有参数的宏的形参不是变量,不分配内存空间,不说明类型参数 预处理程序认为有参数宏的实参是字符串a+1先去替换x而不是先运算a+1再替换x 宏替换不会占用运行时间,只是编译时间长一些,而函数调用会占运行时间,一般用宏来代表一些比较简单的表达式。
2.文件包含#include
文件包含命令是把指定文件全部包含进来,插入到命令所在位置,取代原来的命令行,由当前文件和指定文件组成一个文件,一起编译。 一个#include只包含一个文件 #include<> 和 #include "" 区别查找指定文件的位置不同。 尖括号只在缺省目录里找文件,缺省目录由用户设置的编程环境所决定。 双引号先在 源程序文件所在的当前目录找指定文件,没有的话再在缺省目录里找。
3.条件编译
对一部份内容指定编译条件。
.范式一 #ifndef 标识符 ..... #endif eg: #ifndef _getkey_h #define _getkey_h #include<sys/types.h> #endif 如果没有定义常量 _getkey_h则定义_getkey_h然后把sys/types.h包含进来 .范式二 #ifndef 标识符 ...... #else ...... #endif 如果没有定义标识符,编译1,否则编译2 .范式三 #ifdef ...... #endif 定义了标识符,就编译 eg:#ifdef DEBUG printf("debug----"); #endif 在调试程序的时候在源程序头部加入 #define DEBUG 用于调试 .范式四 #ifdef 标识符 ...... #else ...... #endif .范式五 #if 表达式 ...... #endif 表达式成立,编译 .范式六 #if 表达式 ...... #else ...... #endif
4.结构体和共用体
1.声明和引用结构体
struct 结构体名 { 成员列表 }; 声明结构体也是一个C语言语句,分号来结束,相当于构造了一个新的数据类型 struct person { ]; int age; char sex; ]; }; struct person p1,p2; 系统为这个person结构体分配的内存为20+++=40字节 printf("%d",sizeof(p1)); 如果把char phone[]改为char phone[],结果不是41,而是44 //内存为了提高访问效率有一个规则:4字节对齐 申明结构体时也可以同时定义变量 struct person { ]; ...... }p1,p2; 另一种方式:没有声明结构体名,不能再定义其他结构体 struct { ]; ...... }p1,p2;
2.引用和初始化结构体变量
struct person p1; strcpy(p1.name,"fubin"); p1.age=; p1.sex='m'; strcpy(p1.name,"); printf("%s",p1.name); "."是成员运算符,在所有运算符中优先级最高
3.结构体和数组
] = {{,,"}}; eg: #include<stdio.h> #include<string.h> int main(){ struct student { int number; ]; char sex ; int age; ]; }; ] = {{,,,,"guangzhou"}}; s[].number=; s[].sex='m'; s[].age=; strcpy(s[].name,"fubin"); strcpy(s[].addr,"hunanchangsha"); int i; ; i < ]) ; i++){ printf("%d,%s,%c,%d,%s\n",s[i].number,s[i].name,s[i].sex,s[i].age,s[i].addr); } ; }
获得结构体数组的长度的方法:sizeof(s)/sizeof(s[0]);
4.结构体和指针
结构体中的成员是按顺序连续存放在内存中,一个结构体指针指向结构体变量,结构体指针保存的值是它所指向的结构体变量的内存首地址。 struct student s1; struct student *p; s1.number=; s1.sex='m'; s1.age=; strcpy(s1.name,"fubin"); strcpy(s1.addr,"); p=&s1; printf("%d,%s,%c,%d,%s\n",p->number,p->name,p->sex,p->age,p->addr); (*p).number ===== p->number 一般不用前者 p->number++ 得到number,使用之后再加1 ++p->number 先加1,再使用
5。指向结构体数组的指针
eg: #include<stdio.h> #include<string.h> int main(){ struct student { int number; ]; char sex ; int age; ]; }; ] = {{,,,,,,"dongguan"}}; struct student *p; ; p++){ printf("%d,%s,%c,%d,%s\n",p->number,p->name,p->sex,p->age,p->addr); } ; }
6.结构体指针做函数的参数
void print_struct(struct student *p){ p->age++; printf("%d,%s,%c,%d,%s\n",p->number,p->name,p->sex,p->age,p->addr); }
3.共用体
共用体把几种不同数据类型的变量存在同一块内存里。 union 共用体名 { 成员列表 }变量列表; 访问共用体的方式: union data { int i; char c; double d; }; union data a ; a.i = ; a.c='A';//此时i已经没有值了 共用体的最长长度取决于成员的最大长度 printf( 因为double是8字节存储 事实上,共用体和结构体一样,为了提高访问效率,要进行内存对齐,因此实际所占的空间有时还会大一些 不能把共用体变量作为函数的参数,也不能使函数返回共用体变量,但可以使用指向共用体变量的指针。
4.使用typeof
声明新的类型名替代已有类型名 type int _INT; 可以在声明结构体的时候使用typeof typeof struct { int year; int month; int day; }Date; Date birthday; ]; NUMBER n; n[]= ; typeof只为某类型变量声明一个别名,使用它不定义变量,不分配内存。
3.位运算
C语言可以直接对二进制进行操作,有效率,适合编写系统级程序。 位操作符:& , |,^ (异或),~,<<,>> 位域:C语言允许以位为单位来使用内存 含有位域的结构体: struct bit_data{ ;//6位 ;//4位 ;//4位 int d; //32位 }; 若某一段要从下一个存储单元开始存放,可以定义如下: struct bit_data{ ;//6位 ;//4位 ;//上边32个字节,下面从32之后开始存放 ;//4位 int d; //32位 }; struct bit_data{ ;//6位 ;//4位 ;//上边空闲8个bit ;//4位 int d; //32位 };
5.4.make的使用和makefile的编写
维护程序模块的关系和生成可执行代码的工具-----make
1.makefile文件的基本构成
makefile文件的基本单元是规则。一条规则指定一个或多个目标文件。
显式规则,隐含规则,使用变量,文件指示,注释。
1.显式规则指明了目标文件,目标文件的依赖文件,生成或更新目标文件所使用的命令。有些规则没有命令,只描述文件之间的依赖关系。
2.隐含规则:由make根据目标文件,如make文件更具目标文件名,自动产生目标的依赖文件和生成目标的命令。
3.使用变量
4.文件指示
5.注释