C和指针day4

102 阅读3分钟

第十章 结构和联合体

结构基础知识

聚合数据类型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;}

 

图片1.png

字符串常量(实质上是指针)

字符串常量本质是一个指针 “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