第十章 结构和联合体
结构基础知识
聚合数据类型struct {...}x;没有标签,直接创建了一个X结构体struct SIMPLE{...};创建了标签
结构体成员的访问
直接访问:a.p; 间接访问:a->p;(a是个结构体指针)警惕陷阱: typedef struct {int a;SELF_REF3 *b;int c;}SELF_REF3; 此时名称是在后面才被声明的,这样不行,解决方案: typedef struct SELF_REF3_TAG{int a;SELF_REF3_TAG *b;int c;}SELF_REF3;
不完整的声明
当两个结构体需要互相依赖的时候,则:
struct B;struct A {struct B *partner;};struct B {struct A *partner;}
这样即可
结构体的成员存储分配
struct ALIGN{char a;int b;char c;};struct ALIGN2{int b;char a;char c;};
此时的两种结构体的占用内存大小是不同的
位段
struct CHA{unsigned ch : 7;unsigned font:6;unsigned siz:19;}struct CHA ch1;
案例:
struct DISK_FOR{unsigned command :5;unsigned sector:5;...};
#define DISK_FOR_SIG \((DISK_FOR *)0xc0200142)DISK_FOR_SIG ->command = 12;...
联合体
联合体的所有成员引用的是内存中的相同位置。
struct VARIABLE{enum {INT,FLOAT,STRING} type;
union {int i;float f;char *s;}value;};
通过type去访问类型
第十一章 动态内存分配
为什么使用动态内存分配
动态的调整数组的大小,节省内存
malloc和free
void *malloc(size_t size)void free(void *pointer)
calloc和realloc
void *calloc(size_t num_elements,size_t element_size);参数1:元素大小参数2:字节数会初始化为0void realloc (void *ptr,size_t new_size);
第十二章 使用结构和指针
链表
单链表
双链表
第十三章 高级指针话题
int *f,g;此时的g是int类型,f则是一个指针
高级声明
函数指针 int (*f)(int ,float);指针函数 int *(*g[])(int ,float);
函数指针
常见的两个用途:转换表和作为参数传递使用方式如下:
int f(int);
int (*pf)(int) = &f;
int ans;
ans = f(25);
ans = (*pf)(25);
ans = pf(25);
回调函数
当有相同的逻辑,但是不同的数据类型则使用回调函数去执行:
int compare_inits(void const *a,void const *b)
{if(*(int*)a == *(int *)b)return 0;elsereturn 1;}
转移表
enum value{add,sub,mul,div};value v1= ...;
double (*oper_func[])(double,double) = {add,sub,mul,div,...}
result = oper_func[v1](double,double);
命令行参数
int main(int argc,char **argv)命令行参数可能只能处理一次,所以必须多次处理参数时,需要复制一份if (argc != 0){std::cout << argc << std::endl;}for (; *argv != nullptr; *argv++){std::cout << *argv << std::endl;}
字符串常量(实质上是指针)
字符串常量本质是一个指针 “xyz”+1此时的语句貌似是毫无意义的,实际上它会返回 y
*"xyz"此时,由于是指针被解引,所以是第一个字符
‘x'printf("%s\n","****************"+10-n);
//把后面的参数看成一个指针然后偏移 10-n 然后输出字符串
putchar("0123456789ABCDEF"[value % 16]);//10进制转换成16进制数
第十四章 预处理器
预定义符号
- FILE:表示进行编译的文件名;
- LINE:表示文件当前的行号;
- DATA:表示文件被编译的日期;
- TIME:表示文件被编译的时间;
- STDC:如果编译器遵循ANSI C,其值就为1,否则未定义。
#define
#define name value一般结合上面来使用:#define DEBUG_PRINT printf("File %s line %d:" "x=%d,y=%d,z= %d",FILE,LINE,x,y,z)
宏
- 注意:#define SQUART(X) ((X)*(X)) 一定要用括号封死
- #的用法
#define PRINT(FORMAT,VALUE) printf("The value of" #VALUE "is" FORMAT "\n",VALUE)
此时的#VALUE 会将VALUE 转换成字符串
- ##的用法
#define ADD_TO_SUM(sum_number,value)\sum ## sum_number += valueADD_TO_SUM(5,25)//sum5 = 25;
宏名称最后为全大写
#undef 移除宏定义
条件编译
#if ***...#endif //***嵌套指令#if define (OS_UNIX)#ifdef OPEN1...#endif#ifdef OPEN2...#elif define (OS_MSDOS)#ifdef OPEN1...#endif#endif
其它指令()
- #line #line number "string"//可以修改 LINE 的值
- #error define NUMBER#ifndef NUMBER#error No potion!#endif // !NUMBER
- #progma