一、有参宏定义
#include <stdio.h>
#define PRINT(N) printf(#N"=%d\n", N) //定义打印整形术的宏函数
#define ID(N) id##N
int main(void)
{
int a = 20 , b = 30;
PRINT(a); //替换结果:printf("a""=%d\n",a)等价于 printf("a = %d\n", a);
PRINT(b); //替换结果:printf("b""=%d\n",b)等价于 printf("a = % d\n", b);
//先把宏值中的参数N用1,2替换,替换之后将id##1/2前后粘连,结果就是id1、id然后吧ID宏名用id1、id2替换
int ID(1) = 100, ID(2) = 200; //替换结果:int id1=100;id2=200;
printf("%d, %d\n", ID(1), ID(2)); //替换结果:printf(“%d %d,id1,id2”);
return 0;
}
#include <stdio.h>
#define PRINT(N) printf(#N"=%d\n", N) //定义打印整形术的宏函数
#define ID(N) id##N
#define PI (3.1415926)
int main(void)
{
int a = 20 , b = 30;
PRINT(a); //替换结果:printf("a""=%d\n",a)等价于 printf("a = %d\n", a);
PRINT(b); //替换结果:printf("b""=%d\n",b)等价于 printf("a = % d\n", b);
//先把宏值中的参数N用1,2替换,替换之后将id##1/2前后粘连,结果就是id1、id然后吧ID宏名用id1、id2替换
int ID(1) = 100, ID(2) = 200; //替换结果:int id1=100;id2=200;
printf("%d, %d\n", ID(1), ID(2)); //替换结果:printf(“%d %d,id1,id2”);
//优秀代码:如果将来3.14精度不够,只需修改宏PI的值即可,将来预处理阶段自动替换
double r = 10;
printf("面积: %lf\n",PI*r*r);
//$undef PI //取消PI定义
printf("周长:%lf\n",PI*2*r);
//预定义宏演示:注意:前后都是两个下划线
int *p = NULL;
if (!p)
{
printf("这是一个非法的指针不允许访问:%s, %s, %s, %s, %d\n",
__DATE__, __TIME__,__FILE__,__FUNCTION__,__LINE__); //将来软件调试的LOG日志
return -1;
}
return 0;
}
//gcc的-D选项的妙用,通过-D选项可以给程序传递常量宏
//gcc -DSIZE=5 -DEND=\"TARENA\" -o define define.c
#include <stdio.h>
int main(void)
{
int a[SIZE]={0};
//初始化数组
for(int i = 0; i < SIZE; i++)
a[i] = i + 1;
//打印数组
for(int i = 0; i < SIZE ;i++)
printf("%d ", a[i]);
printf("\n");
printf("%s\n", END);
return 0;
}
//条件编译预处理指令
#include <stdio.h>
int main(void)
{
//#if演示
//编译命令:gcc -E -o if.i if.c;vim if.i;gcc -o if if.i; ./if
//编译命令:gcc -DA=1 -E -o if.i if.c; vim if.i; gcc -o if if.i; ./if
#if A == 1
printf("1.\n");
#endif //和#if配对
//#if.....#else演示
//编译命令:gcc -E -o if.i if.c; vim if.i;gcc -o if if.i; ./if
//编译命令:gcc -DB=1 -E -o if.i if.c; vim if.i;gcc -o if if.i; ./if
#if B==1
printf("2.\n");
#else
printf("3.\n");
#endif
//#ifdef或者#ifndef...#else演示
//编译命令:gcc -E -o if.i if.c; vim if.i;gcc -o if if.i; ./if
//编译命令:gcc -DC -E -o if.i ;vim if.i ;gcc -o if if.i; ./if
//#ifdef C
#ifndef C
printf("4.\n");
#else //可以不加
printf("5.\n");
#endif
//#if defined....#else
//编译命令:gcc -E -o if.i if.c; vim if.i ; if -o if if.i; ./if
//编译命令:gcc -DD -E -o if.i if.c; vim if.i ; if -o if if.i; ./if
//编译命令:gcc -DE -E -o if.i if.c; vim if.i ; if -o if if.i; ./if
//编译命令:gcc -DD -DE -E -o if.i if.c; vim if.i ;gcc -o if if.i; ./if
//编译命令:gcc -DE -DD -E -o if.i if.c; vim if.i ; if -o if if.i; ./if
#if defined(D)
printf("6.\n");
#elif !defined(D) && !defined(E)
printf("7.\n");
#else
printf("8.\n");
#endif
return 0;
}
复合类型与高级指针
//结构体玩法1:直接定义结构体变量(很少用)
#include <stdio.h>
#include <string.h>
int main(void)
{
//直接定义结构体变量stul并且初始化
struct
{
char name[32];
int age;
}stu1 = {"feifei",18};
//打印学生信息
printf("%s, %d\n",stu1.name, stu1.age);
stu1.age++;
strcpy(stu1.name, "feifeiya");
//
printf("%s, %d\n", stu1.name, stu1.age);
return 0;
}
//结构体玩法2:先声明一个结构体变量(好比自己做一个自信的 int类型)
//然后用结构类型定义变量分配内容
#include<stdio.h>
#include<string.h>
//先声明结构体类型描述学生的信息,类似造一个自己的int类型一样
struct student{
char name[32];
int age;
};//好比把Struct student当成Int类型来看
int main(void)
{
//用自己造的结构体类型定义结构体变量分配内存转储学生信息
//struct student stu1 = {"feifei",18};
struct student stu1 = {.age = 18,.name = "feifei"};
printf("%s, %d\n",stu1.name, stu1.age);
stu1.age++;
strcpy(stu1.name, "feifeiya");
printf("%s, %d\n",stu1.name, stu1.age);
struct student *pstu = &stu1;
printf("%s, %d\n", pstu->name, pstu->age);
pstu->age++;
strcpy(pstu->name,"feifei");
printf("%s, %d\n", pstu->name, pstu->age);
return 0;
}
//结构体数据的玩法3:数组中每个成员是一个结构体
#include <stdio.h>
//声明结构体类型来描述学生信息
struct student{
char name[32];
int age;
};
//后给声明的结构体函数取别名
typedef struct student stu_t; //给struct student取别名叫stu_t,好比把stu_t当成Int来看
int main(void)
{
//定义初始化三个学生信息
stu_t stu_info[3] = {
{.name = "刘备", .age = 20},
{.name = "关于", .age = 19},
{.name = "张飞", .age = 18},
};
int len = sizeof(stu_info)/sizeof(stu_info[0]);//换算元素个数
//打印
for(int i = 0; i < len ;i++)
printf("%s, %d\n", stu_info[i].name, stu_info[i].age);
for(int i = 0; i < len ;i++)
printf("%s, %d\n", stu_info[i].name, stu_info[i].age);
for(int i = 0; i < len ;i++)
printf("%s, %d\n", stu_info[i].name, stu_info[i].age);
return 0;
}
```c
//结构体作为函数的形参和返回值
//切记:以后函数操作结构体,函数的形参一律是结构体指针
#include <stdio.h>
//声明结构体类型描述学生信息并且取别名
typedef struct {
char name[32];
int age;
}stu_t;
void show(stu_t st){ //st=stu=内存拷贝自己
printf("%s, %d\n", st.name, st.age);
}
void grow(stu_t st){ //st=stu=内存拷贝自己
st.age++; //仅仅修改了形参st.age,并没有修改实参stu.age
}
void show1(stu_t *pst){ //pst=&stu.pst指向实参
printf("%s, %d\n", pst->name, pst->age);
}
void grow1(stu_t *pst) { //pst=&stu
pst->age++; //直接修改实参stu.age
}
//定义返回学生信息数的函数
stu_t return_stu(void){
stu_t stu = {"张三", 20};
return stu; //返回结构体变量的值
}
stu_t *return_pstu(void){
stu_t stu = {"张三", 20};
return &stu; //不能返回局部结构体变量的指针
}
int main(void)
{
stu_t stu = {"feifei", 15};
show(stu); //传递实参结构体stu
grow(stu); //传递实参结构体stu
show(stu); //传递实参结构体stu
show1(&stu); //传递实参结构体stu的地址
grow1(&stu);
show1(&stu);
stu_t stu2 = return_stu();
printf("%s, %d\n", stu2.name, stu2.age);
stu_t *pstu = return_pstu();
printf("%s, %d\n",pstu->name,pstu->age);
return 0;
}
![在这里插入图片描述](https://img-blog.csdnimg.cn/cee46535f5634d37b4a2f3e20f914329.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBASnVzdE1vbmlrYWE=,size_20,color_FFFFFF,t_70,g_se,x_16)
```c
#include <stdio.h>
//声明描述学生出生日期的结构体变量
typedef struct birthday{
int year;
int month;
int day;
}birth_t;
//声明描述学生信息的结构体类型
typedef struct student{
char name[32];
int age;
birth_t birth;
}stu_t;
int main(void)
{
stu_t stu1 = {.birth = {.year = 2002, .month = 2, .day = 2}, .name = "shabi", .age = 18};
stu_t *pstu = &stu1;
printf("%s, %d, %d-%d-%d\n", stu1.name, stu1.age, stu1.birth.year, stu1.birth.month, stu1.birth.day);
printf("%s, %d, %d-%d-%d\n", pstu->name, pstu->age, pstu->birth.year, pstu->birth.month, pstu->birth.day);
stu1.age++;
pstu->birth.year = 2001;
pstu->birth.month =3;
printf("%s, %d, %d-%d-%d\n", stu1.name, stu1.age, stu1.birth.year, stu1.birth.month, stu1.birth.day);
printf("%s, %d, %d-%d-%d\n", pstu->name, pstu->age, pstu->birth.year, pstu->birth.month, pstu->birth.day);
return 0;
}
//结构体嵌套结构体变量
#include <stdio.h>
//声明描述学生出生日期的结构体变量
typedef struct birthday{
int year;
int month;
int day;
}birth_t;
//声明描述学生信息的结构体类型
typedef struct student{
char name[32];
int age;
birth_t *pbirth; //嵌套birth_t结构体指针变量来存储学生的出生日期的信息
}stu_t;
int main(void)
{
//stu_t stu1 = {"shabi", 18, NULL}; 传统初始化
stu_t stu1 = {.pbirth = NULL, .name = "shabi", .age = 18};
stu_t *pstu = &stu1;
//初始化pbirth成员让它指向有效的内容
birth_t birth = {2002, 2, 2}; //定义初始化birth变量存储关于学生的出生日期
stu1.pbirth = &birth; //让pbirth指向birth
//等价于pstu->pbirth = &birth;
//打印
printf("%s, %d, %d-%d-%d\n", stu1.name, stu1.age, stu1.pbirth->year, stu1.pbirth->month, stu1.pbirth->day);
printf("%s, %d, %d-%d-%d\n", pstu->name, pstu->age, pstu->pbirth->year, pstu->pbirth->month, pstu->pbirth->day);
//修改
stu1.age++;
pstu->pbirth->year = 2001;
pstu->pbirth->month =3;
printf("%s, %d, %d-%d-%d\n", stu1.name, stu1.age, stu1.pbirth->year, stu1.pbirth->month, stu1.pbirth->day);
printf("%s, %d, %d-%d-%d\n", pstu->name, pstu->age, pstu->pbirth->year, pstu->pbirth->month, pstu->pbirth->day);
return 0;
}
//结构体内存对齐和补齐
#include <stdio.h>
struct A{
char buf[2]; //CCXX
int a; //IIII
};
struct B{
char c; //CX
short s[2];//SSSS
int i;
};
#pragma pack(1) //让gcc编译器强制从代码的这个位置开始往后所有代码> 按照1字节对齐方式
struct C{
char c;
short s[2];
int Ii;
};
#pragma pack() //让gcc编译器从这里开始往后重新恢复到原先的补齐和对
齐方式
struct D{
int i;
char c;
};
struct E{
double d;
char c;
};
int main(void){
printf("sizeof(struct A) = %lu\n", sizeof(struct A));
printf("sizeof(struct B) = %lu\n", sizeof(struct B));
printf("sizeof(struct C) = %lu\n", sizeof(struct C));
printf("sizeof(struct D) = %lu\n", sizeof(struct D));
printf("sizeof(struct E) = %lu\n", sizeof(struct E));
return 0;
}
//枚举类型演示
#include<stdio.h>
//声明枚举数据类型
enum Color{
RED, //好比给0这个整形数字取了个别名叫RED
GREEN, //好比给1这个这个整形数组取别名
BLUE, //好比给2这个整形数字取别名叫BLACK
BLACK = 10, //好比给10取别名叫BLACK
WHITE,//好比给11取别名
}; //默认都是INT类型
int main(void){
//单次显然比数字可读性好
printf("%d, %d, %d, %d, %d\n", RED, GREEN, BLUE, BLACK, WHITE);
return 0;
}
在这里插入代码片