- 函数声明 void func();
返回类型 名称 (参数);
- 函数指针:void (*pfunc)();
类型 (*函数名) (参数)
- 赋值:pfunc = &func; 或者简写为pfunc=func;
- 函数名是地址,是执行函数代码的起始位置
- 调用1:解引用 (*pfunc)();//前面必须加括号,因为后面括号优先级高,要把*和pfunc打包成整体才是函数指针解引用
调用2:pfunc(); - 函数指针可以作为函数参数,这叫回调函数
- 指针函数:void* func(){};//返回值是一个指针类型
示例:
#includevoid func(); int main(){ printf("%p %pn",func,&func); func(); int n; int* p; int** pp; void(*pfunc)();//函数指针 pfunc = &func;//赋值 pfunc=func (*pfunc)();//pfunc() //解引用 解出来也是func的地址 } void func(){ printf("hello worldn"); }
重要示例!!!
#includeint add(int a,int b){ return a+b; } int subtract(int a,int b){ return a-b; } int multipy(int a,int b){ return a*b; } int divide(int a,int b){ return a/b; } //int(*pfunc)(int,int)函数指针作为参数,便于调用样式统一的add,subtract,multipy,divide作为回调函数 int operation(int arr[],int n,int(*pfunc)(int,int)){ int* p=arr; int res = *p; while(++p 示例(整型比较):
#include#include void print_array(int arr[],int n){ int* p =arr; while(p *q为正值,改变顺序,从而是升 序,如果*p<*q返回为负值,是升序 } int main(){ int n; scanf("%d",&n); int arr[n]; for(int i=0;i 示例(浮点型比较):
#include#include void print_array(float arr[],int n){ float* p =arr; while(p *(float*)q?1:-1;//如果*p>*q为正值,改变顺序>,从而是升序,如果*p<*q返回为负值,是升序 } int main(){ int n; scanf("%d",&n); float arr[n]; for(int i=0;i 示例(字符串排序)
#include//printf() #include //qsort() #include //strcmp() void print_array(char* arr[],int n){ char** p =arr; while(p C初阶7:结构体 struct Point{ int x; int y; int z; };//占3*4=12个字节
- 结构体定义对象 struct Point p ={1,3,6};
- 结构体地址是它第一个成员的地址
- 结构体指针:struct Point* q =&p;
p->x等同于(*q).x 注意:->自带解引用
3.1 访问结构体对象成员用. 如:p.x=100
3.2 访问结构体指针成员用-> 如:q->x=1000;- c语言中定义结构体对象时 struct不可省略 ,如struct Point q;
示例:
#includestruct Point{ int x; int y; int z; };//占3*4=12个字节 void Point_Print(struct Point p){ printf("(%d,%d,%d)n",p.x,p.y,p.z); } void PointPtr_Print(struct Point* p){ printf("(%d,%d,%d)n",p->x,p->y,p->z); } int main(){ struct Point p ={1,3,6}; Point_Print(p); printf("%dn",sizeof(p)); struct Point* q=&p;//q是个指针,在64位中占8个字节,32位占4个字 节 printf("%dn",sizeof(q)); Point_Print(*q); q->x=100; q->y=300; q->z=600; Point_Print(p); PointPtr_Print(q); }
- 结构体数组struct Point Points[] = {{1,2,3},{3,3,3},{2,3,4},{7,7,7}};
- 结构体嵌套结构体
struct Line{ struct Point p1; struct Point p2; }示例:
#include#include //sqrt() pow(a,b) 编译时要链接库用-lm struct Point{ int x; int y; int z; };//占3*4=12个字节 //结构体嵌套结构体 struct Line{ struct Point p1; struct Point p2; }; float GetDistance(struct Line line){ return sqrt( pow(line.p1.x-line.p2.x,2)+ pow(line.p1.y-line.p2.y,2)+ pow(line.p1.z-line.p2.z,2)//pow(a,b)表示a的b>次方 ); } float GetDistance2(struct Line* line){//参数是结构体指针,访问其对 象line成员时要用-> 调用是传参要传结构体的地址 return sqrt( pow(line->p1.x-line->p2.x,2)+ pow(line->p1.y-line->p2.y,2)+ pow(line->p1.z-line->p2.z,2)//pow(a,b)表示a的 b次方 ); } void Point_Print(struct Point p){ printf("(%d,%d,%d)n",p.x,p.y,p.z); } void PointPtr_Print(struct Point* p){ printf("(%d,%d,%d)n",p->x,p->y,p->z); } int main(){ struct Point p ={1,3,6}; Point_Print(p); printf("%dn",sizeof(p)); struct Point* q=&p;//q是个指针,在64位中占8个字节,32位占4个字 节 printf("%dn",sizeof(q)); Point_Print(*q); q->x=100; q->y=300; q->z=600; Point_Print(p); PointPtr_Print(q); //结构体数组,遍历如同数组遍历 struct Point points[] = {{1,2,3},{3,3,3},{2,3,4},{7,7,7}}; for(int i=0;i<4;i++){ Point_Print(points[i]); PointPtr_Print(points+i); } //结构体嵌套结构体 struct Line line = {{0,0,0},{3,4,5}}; Point_Print(line.p1); Point_Print(line.p2); printf("%fn",GetDistance(line)); printf("%fn",GetDistance2(&line)); }
- 结构体包含结构体数组:
struct Triangle{ struct Point p[3]; };struct Triangel t = {{{1,2,2},{1,1,1},{8,0,0}}};
- 遍历:
for(int i=0;i<3;i++){ Point_Print(t.p[i]); }示例:
#includeC初阶8:联合体#include //struct tm* time() ... int main(){ time_t now = time(NULL); struct tm* utc = gmtime(&now);//格林时间 struct tm* local = localtime(&now);//本地时间 比格林世界多8个小时 char temp[20]={' '};// YYYY/MM/DD HH:mm:SS //把struct tm*类型的结构体指针对象的内容,以%F年 %T时间的格式(strftime里面定义的),放入大小为20 的temp数组空间中 strftime(temp,20,"%F %T",local); printf("%sn",temp); struct tm test; //把时间字符串以%F %T格式放入到 struct tm类型的结构体对象test中 strptime("2020-01-01 21:03:10","%F %T", &test); printf("%d/%d/%d %d:%d:%dn",test.tm_year+1900,test.tm_mon+1,test.tm_hour,test.tm_min,test.tm_sec); } 示例:
#includeC初阶:枚举struct SPoint{ int x; int y; int z; };//占3个*4字节=12字节内存 union UPoint{ int x; int y; int z; };//联合体成员共享内存,所占空间为最大的成员所占空间 这里占4个字节,因为int类型占4字节 union Integer{ int data; char bytes[4]; }; int main(){ printf("%dn",sizeof(struct SPoint)); printf("%dn",sizeof(union UPoint)); union UPoint up; up.x = 100;//给联合体一个成员赋值,因为成员之间共享一块内存,所以其余成员也被赋同样的值 printf("(%d,%d,%d)n",up.x,up.y,up.z); union Integer n; n.data = 10113234; printf("%#xn",n.data);//%#x以十六进制输出 for(int i=0;i<4;++i){ printf("%#hhxn",n.bytes[i]);//%x默认整型 //单个h是把int(4个字节)扩展成short(2个字节) //两个h是把int扩展成char(1个字节) }
- 魔术数字:程序中含义不明的数字。
- 通常用符号来表示,解决方式:const和#define
const int SUN = 0;//SUM是常量1 用等号
#define SUN 0;//把SUN在预处理时替换成0,用空格 -E可以看预处理- const和#define(宏定义)区别:
No. 比较项 #define const 1 编译处理 预处理阶段 编译、运行阶段 2 工作原理 简单的字符串替换 有对应的数据类型 3 存储方式 展开,在内存中有若干个备份 只读变量在内存中只有一份 4 类型检查 没有类型安全检查 在编译阶段进行类型检查 5 作用域 从定义开始,任何位置都可访问 只能在变量作用域内 #define MON 1;在编译预处理时把所有的MON替换成1
4. 宏定义无类型
const在编译运行阶段编译处理
- 枚举:enum 枚举名{名字0,名字1,名字2,...}
5.1. 类型为int 值一次从0到n
5.2. 枚举可看作一堆宏定义放一起(但不是) 就是给一些常量值,规定一个名字
5.3. 枚举量可以直接作为值使用
5.4. 枚举类型可以直接作为类型使用,用类型定义时只能用枚举值里的有限个常量
5.5. 声明时可以指定值 如:enum R{Bin=2,Oct=8,Dec=10,Hex=16};如确定一个值后续依次加一 如:
enum M{Jan=1,Feb,Mar,Apr,May,Jun,Jul,Aug,Sept,Oct,Nov,Dec};即:Feb=2,Mar=3



