C 结构体的定义
#include <stdio.h>
struct student
{
int ID;
char name[10];
int age;
}; //注意这里的分号
int main()
{
// 初始化
struct student student1 = {1111,"Redhat",20};
struct student student2 = {.ID = 1111,.name = "Debian",.age = 20};//C99才有
struct student student3 = {1111,"BSD",.ID = 20,.age = 30}; //ID = 20
//使用
printf("%d,%s,%d \n",student1.ID,student1.name,student1.age);
printf("%d,%s,%d \n",student2.ID,student2.name,student2.age);
printf("%d,%s,%d \n",student3.ID,student3.name,student3.age);
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
1111,Redhat,20
1111,Debian,20
20,BSD,30
结构体内存分配情况
小的遵循大的数据类型,存在浪费内存的情况
#include <stdio.h>
#include <string.h>
struct student
{
unsigned char c1;
unsigned char c2;
unsigned int i1;
unsigned char c3;
unsigned char c4;
unsigned char c5;
unsigned char c6;
unsigned int i2;
};
int main()
{
printf("%ld \n",sizeof(struct student));
struct student student1;
memset(&student1,0x55,sizeof(struct student));
student1.i1 = 0x12345678;
student1.i2 = 0x23456789;
student1.c1 = 0x21;
student1.c2 = 0x22;
student1.c3 = 0x23;
student1.c4 = 0x24;
student1.c5 = 0x25;
student1.c6 = 0x26;
int *p = (int*) &student1;
for(int i = 0;i< sizeof(struct student)/4;i++)
{
printf("%p %x \n",p,*p);
p++;
}
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
16
0x7ffc7913b1c0 55552221
0x7ffc7913b1c4 12345678
0x7ffc7913b1c8 26252423
0x7ffc7913b1cc 23456789
可以看到内存初始化就是0X55,第一个的4个字节存在了浪费
结构体,自定义数据类型:
#include <stdio.h>
#include <string.h>
struct student
{
unsigned char c1:1;
unsigned char c2:3;
unsigned char c3:4;
};
int main()
{
printf("%ld \n",sizeof(struct student));
struct student student1;
student1.c1 = 1;
student1.c2 = 6;
student1.c3 = 14;
char *p = (char *)& student1;
printf("%x,%d,%d,%d \n",*p,student1.c1,student1.c2,student1.c3);
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
1
ffffffed,1,6,14
结构体嵌套:
#include <stdio.h>
#include <string.h>
struct man
{
unsigned char age;
};
struct student
{
unsigned char name[20];
struct man a_man;
};
int main()
{
printf("%ld \n",sizeof(struct student));
struct student student1;
student1.a_man.age = 10;
printf("student age = %d \n",student1.a_man.age);
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
21
student age = 10
结构体数组,结构体嵌套
#include <stdio.h>
#include <string.h>
struct man
{
char name[20];
unsigned char age;
unsigned char heiget;
};
struct human
{
struct man son;
int money;
};
int main()
{
printf("%ld \n",sizeof(struct human));
/* 结构体数组 */
struct man people[3]={
{"奥巴马",50,170},
{"金正恩",44,166},
{"朴槿惠",33,155},
};
/* 结构体嵌套 */
struct human a_human;
a_human.son.age = 10;
printf("son age = %d \n",a_human.son.age);
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
28
son age = 10
结构体赋值
#include <stdio.h>
#include <string.h>
struct man
{
char name[20];
unsigned char age;
unsigned char height;
};
int main()
{
struct man people1={"奥巴马",50,170};
struct man people2;
people2 = people1; //结构体的赋值,people1的内存赋值到了people2,二者相互独立!
//memcpy(&people2,&people1,sizeof(people1));
//相当于memcpy(&people2,&people1,sizeof(people1));
printf("%s,%d,%d \n",people2.name,people2.age,people2.height);
///////////////////////////////////////////////////////
/*区别于数组
char str1[10] = {"Hello!"};
char str2[20];
str2 = str1; //这是不允许的。数组的名仅是一个地址,不允许赋值。
//////////////////////////////////////////////////////
//这个不是赋值,这个只能是指向了那个地址
char str3[] = {"Hello !"};
char *p1 = str3;
char *p2 = p1;
*/
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
奥巴马,50,170
结构体赋值里面的指针变量
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct man
{
char *name;
unsigned char age;
unsigned char height;
};
int main()
{
struct man people1={"朴槿惠",40,170};
struct man people2;
people2 = people1;//结构体赋值
printf("%s,%d,%d \n",people2.name,people2.age,people2.height);
people2.name = "王麻子"; //指针指向常量"王麻子"
printf("%s,%d,%d \n",people2.name,people2.age,people2.height);
/*结构体指针*/
struct man people3;
people3.name = malloc(20);
strcpy(people3.name,"孙悟空");
printf("%s,%d,%d \n",people3.name,people3.age,people3.height);
//free(people3.name); //堆释放会对下面的strcpy(people4.name,people3.name);有影响
/*如果结构体里面有指针,不能通过简单赋值完成操作,因为指向的是一样的*/
struct man people4;
people4.name = malloc(strlen(people3.name)+1);
strcpy(people4.name,people3.name);
people4.age = people3.age;
people4.height = people3.height;
printf("%s,%d,%d \n",people4.name,people4.age,people4.height);
free(people3.name); //堆释放
free(people4.name); //堆释放
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
朴槿惠,40,170
王麻子,40,170
孙悟空,0,0
孙悟空,0,0
结构体指针 初步1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct man
{
char *name;
unsigned char age;
unsigned char height;
};
int main()
{
struct man people1;
struct man *people2 = &people1;
(*people2).name = malloc(10);
(*people2).age = 20;
(*people2).height = 170;
/* 上面的形式可以写成一下:*/
people2 -> name = malloc(10);
people2 -> age = 20;
people2 -> height = 170;
}
编译通过
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
chunli@ubuntu:~/pointer$
结构体指针 初步2
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct man
{
unsigned char id;
char name[20];
unsigned char height;
};
int main()
{
struct man people[3] = {
{1,"wang",181}, //wang属于常量
{2,"li",182},
{3,"zhang",189},
};
/* 定义一个结构体指针 */
struct man *people2 = &people[0];
printf("%d,%s,%d \n",people2->id,people2->name,people2->height);
/* 访问方式2,也可以方便for循环 */
printf("%d,%s,%d \n",people2[1].id,people2[1].name,people2[1].height);
people2++;//一次会移动一个结构体
printf("%d,%s,%d \n",people2->id,people2->name,people2->height);
/*
struct man people1 = {1,"wang",181};
struct man people2 = {2,"wang",181};
struct man people3 = {3,"wang",181};
不要尝试用循环来遍历这样的数据,因为您不知道编译器是怎么安排的
最好放在同一个数组里面
*/
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
1,wang,181
2,li,182
2,li,182
结构体的指针,初步3
#include <stdlib.h>
#include <string.h>
struct man
{
unsigned char id;
char *name;
unsigned char age;
};
int main()
{
struct man *sp = malloc(sizeof(struct man));
sp->id = 5;
sp->age = 10;
sp->name = malloc(10);
strcpy(sp->name,"zhang");
printf("%d,%s,%d \n",sp->id,sp->name,sp->age);
free(sp->name); // 一定先释放这个
free(sp); //要不然sp-name永远找不到了
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
5,zhang,10
动态获取用户输入,不会浪费内存空间
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct test
{
char *name; //指针哦
};
struct man
{
unsigned char id;
char *name;
unsigned char age;
//struct test *p; //有嵌套了一层,这是很难搞的
};
int main()
{
struct man *sp = malloc(sizeof(struct man) * 10);
memset(sp,0,sizeof(struct man) * 10);// 内存清零
for(int i = 0;i<10;i++)
{
sp[i].id = i;
sp[i].age = i;
char buf[999]={0};
scanf("%s",buf);
int len = strlen(buf);
sp[i].name =malloc(len+1) ;
sprintf(sp[i].name,"%s",buf);
}
for(int i = 0;i<10;i++)
{
printf("%d,%s,%d \n",sp[i].id,sp[i].name,sp[i].age);
}
for(int i = 0;i<10;i++)//循环释放
{
free(sp[i].name);
}
free(sp); //全部释放
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
12
1111111111111111111111111111111111111111111111111111111111111111111
2222222222222222222222222222222222222222222222222222222222222222222
a
s
wsswdwdwdwdwedfwefefvdvgdf,kvdfvdfvdvmdvm
mcsfdmcdsmc'nv vnvpmvpwvm[sdv
fsdv dvdf e fdf f
0,12,0
1,1111111111111111111111111111111111111111111111111111111111111111111,1
2,2222222222222222222222222222222222222222222222222222222222222222222,2
3,a,3
4,s,4
5,wsswdwdwdwdwedfwefefvdvgdf,kvdfvdfvdvmdvm,5
6,mcsfdmcdsmc'nv,6
7,vnvpmvpwvm[sdv,7
8,fsdv,8
9,dvdf,9
形参是结构体的函数
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct man
{
unsigned char id;
char *name;
unsigned char age;
};
void fun1(struct man a_man)
{
printf("id = %d,age = %d,name = %s \n",a_man.id,a_man.age,a_man.name);
strcpy(a_man.name,"haha"); //会影响传过来的数据,因为指向的是同一块内存
a_man.id = 99; //而id就不会发生变化
}
int main()
{
//struct man people1 = {0,"wang",100};
struct man people1;
people1.id = 0;
people1.age = 10;
people1.name = malloc(10);
strcpy(people1.name,"wang");
fun1(people1);
printf("id = %d,age = %d,name = %s \n",people1.id,people1.age,people1.name);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
id = 0,age = 10,name = wang
id = 0,age = 10,name = haha
结构体参数,地址与传值
chunli@ubuntu:~/pointer$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct man
{
unsigned char id;
char name[100];
unsigned char age;
};
void fun1(struct man a_man)//传值过来
{
printf("id = %d,age = %d,name = %s \n",a_man.id,a_man.age,a_man.name);
strcpy(a_man.name,"haha"); //无法修改
a_man.id = 99; //无法修改
}
void fun2(struct man *sp) //地址传过来
//void fun2(const struct man *sp) //保护起来,防止修改
{
printf("id = %d,age = %d,name = %s \n",sp->id,sp->age,sp->name);
strcpy(sp->name,"鲁智深"); //可以修改
sp->id = 66; //可以修改
}
int main()
{
struct man people1;
people1.id = 0;
people1.age = 10;
strcpy(people1.name,"wang");
fun1(people1);//fun1无法修改参数值
printf("id = %d,age = %d,name = %s \n",people1.id,people1.age,people1.name);
fun2(&people1);
printf("id = %d,age = %d,name = %s \n",people1.id,people1.age,people1.name);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
id = 0,age = 10,name = wang
id = 0,age = 10,name = wang
id = 0,age = 10,name = wang
id = 66,age = 10,name = 鲁智深
如何修改机构体内部的数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct str
{
char buf[100];
};
void fun1(struct str s)
{
strcpy(s.buf,"hello ");
}
void fun2(char s[])
{
strcpy(s,"hello");
}
int main()
{
struct str s={"world!"}; ;
fun1(s);//传结构体,相当于赋值过去了,不会改变变量 (会很消耗内存的性能)
printf("%s \n",s.buf);
char s1[100]="world!";
fun2(s1);//数组会把地址传过去,会修改变量
printf("%s \n",s1);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
world!
hello
结构体函数 初始化结构体
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct str
{
char buf[100];
};
struct str getstr()
{
struct str s;
strcpy(s.buf,"Hello World!");
return s;
}
char *getstr1()
{
char buf[100];//在栈区
strcpy(buf,"Hello World!");
//return buf;//无法返回有效数据
}
int main()
{
//char *tmp = getstr1(); 非法执行
struct str tmp = getstr();
printf("%s \n",tmp.buf);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
Hello World!
【指向结构体的指针】
返回结构体,消耗很大
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct str
{
char buf[100];
};
struct str getstr()
{
struct str s;
strcpy(s.buf,"Hello World!");
return s;
}
char *getstr1()
{
char buf[100];//在栈区
strcpy(buf,"Hello World!");
//return buf;//无法返回有效数据
}
int main()
{
//char *tmp = getstr1(); 非法执行
struct str tmp = getstr(); //内存拷贝,消耗很大
printf("%s \n",tmp.buf);
return 0;
}
返回结构体指针,消耗很小
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct str
{
char buf[100];
};
struct str *getstr()
{
struct str *s = malloc(sizeof(struct str));
printf("%p \n",s);
strcpy(s->buf,"Hello World!");
return s;//把指针返回去
}
int main()
{
struct str *tmp = getstr(); //内存拷贝,消耗很大
printf("%p \n",tmp);
printf("%s \n",tmp->buf);
free(tmp);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
0x8cc010
0x8cc010
Hello World!
联合体初步1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
union var
{
char c;
int i;
short d;
char *s;//很危险
};
struct str
{
char c;
int i;
short d;
};
int main()
{
/* 结构体与联合体元素地址区别 */
union var v;//联合体元素公用用一个地址
printf("%p \n" ,&(v.c));
printf("%p \n" ,&(v.i));
printf("%p \n" ,&(v.d));//小端对齐,高位放高位,低位放低位
struct str s;//结构体,元素分别独立
printf("%p \n" ,&(s.c));
printf("%p \n" ,&(s.i));
printf("%p \n" ,&(s.d));
/* 修改联合体元素 */
printf("%ld \n",sizeof(v));
v.c = 100;
printf("%d \n",v.c);
v.i = 1;
printf("%d \n",v.c);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
0x7ffc3f56e5d0
0x7ffc3f56e5d0
0x7ffc3f56e5d0
0x7ffc3f56e5e0
0x7ffc3f56e5e4
0x7ffc3f56e5e8
8
100
1
枚举
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum spectrum {red,yellow,green,blue,white,black};//申明一个枚举
enum number {zero=10,one=9,two,three};//申明一个枚举
void test(int i) {printf("test \n");}
void test1(int a,int b) {printf("test1\n");}
void test2(int a,int b,int c) {printf("test2\n");}
void *function_factory(enum number n)
{
if(n == zero) return test;
if(n == one) return test1;
if(n == two) return test2;
}
void getcolor(enum spectrum color)
{
if(color == red) printf("red \n");
if(color == yellow) printf("yellow \n");
if(color == green) printf("green \n");
if(color == blue) printf("blue \n");
}
int main()
{
enum number b = one;
void *p = function_factory(b);
printf("%p ,%p \n",p,test1);
enum spectrum color = red;
getcolor(color);
printf("%d,%d,%d \n",red,yellow,green);
printf("%d,%d,%d \n",zero,one,two);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
0x400594 ,0x400594
red
0,1,2
10,9,10
typedef 初步
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char BYTE;
#define mybyte unsigned char
typedef unsigned int UINT;//严格检查变量类型
#define MAX 100 //简单替换,不做变量类型检查,没有分号
struct student
{
int id;
char name[100];
};
int main()
{
BYTE b1 = 0xff;
printf("%x \n",b1);
UINT u1 = 0xFF00FF00;
printf("%x \n",u1);
//正常使用
struct student student1;
//typedef 来定义
typedef struct student STUDENT; //自定义 数据类型
STUDENT student2;
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
ff
ff00ff00
没有用typedef之前的代码,看着很晕
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
const char *func1(const char *str1,const char *str2)
{
char *p = malloc(strlen(str1) + strlen(str2) +1);
strcpy(p,str1);
strcat(p,str2);
return p;
}
const char *func2(const char *(*p)(const char *str1,const char *str2),const char *s1,const char *s2)
{
return p(s1,s2);
}
int main()
{
const char *tmp1 = "Hello";
const char *tmp2 = "world!";
const char *s = func2(func1,tmp1,tmp2);
printf("%s \n",s);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
Helloworld!
typedef优化 对比
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义一个指向这种函数类型的指针
typedef const char *(*FUNC1)(const char *str1,const char *str2);
const char *func1(const char *str1,const char *str2)
{
char *p = malloc(strlen(str1) + strlen(str2) +1);
strcpy(p,str1);
strcat(p,str2);
return p;
}
const char *func2(FUNC1 p,const char *s1,const char *s2)
{
return p(s1,s2);
}
int main()
{
const char *tmp1 = "Hello";
const char *tmp2 = "world!";
const char *s = func2(func1,tmp1,tmp2);
printf("%s \n",s);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
Helloworld!
typedef深入1
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//定义一个指向这种函数类型的指针 的数据类型
typedef const char *(*FUNC1)(const char *str1,const char *str2);
//这是函数的原始申明
const char *func1(const char *str1,const char *str2)
{
char *p = malloc(strlen(str1) + strlen(str2) +1);
strcpy(p,str1);
strcat(p,str2);
return p;
}
const char *func2(FUNC1 p,const char *s1,const char *s2)
{
return p(s1,s2);
}
FUNC1 test()
{
FUNC1 tmp = func1;
return tmp;
}
int main()
{
//定义10个FUNC1数据类型
FUNC1 f[10];
//定义一个数组10个元素,参数是const char *str1,const char *str2,返回值是 const char *
const char *(*p[10])(const char *str1,const char *str2);
const char *tmp1 = "Hello ";
const char *tmp2 = "world!";
const char *s = func2(func1,tmp1,tmp2);
printf("%s \n",s);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
Hello world!
超级复杂的typedef
chunli@ubuntu:~/pointer$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned char BYTE;
typedef unsigned int UINT;
#define MYBYTE unsigned char
#define MAX 100
//typedef 100 MYMAX;
struct student
{
int ID;
char name[MAX];
};
typedef struct student STUDENT;
typedef const char *(*FUNC1)(const char *str1, const char *str2);
const char *func1(const char *str1, const char *str2)
{
char *p = malloc(strlen(str1) + strlen(str2) + 1);
strcpy(p, str1);
strcat(p, str2);
return p;
}
/*
const char *(*)(const char *str1, const char *str2) test()
{
FUNC1 tmp = func1;
return tmp;
}
*/
const char *func2(const char *(*p[])(const char *str1, const char *str2), const char *s1, const char *s2)
{
return (p[0])(s1, s2);
}
int main()
{
FUNC1 f[10];//
const char *tmp1 = "hello ";
const char *tmp2 = "world";
f[0] = func1;
const char *s = func2(f, tmp1, tmp2);
printf("s = %s\n", s);
BYTE b;
b = 0x12;
UINT i;
i = 0xffff;
STUDENT st;
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
s = hello world
chunli@ubuntu:~/pointer$
【复习================================】
联合体的指针,很危险
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
union var
{
char c;
int i;
short d;
char *s;//很危险
};
int main()
{
union var v;
v.s = (char *)malloc(100);
v.c = 1;
free(v.s);//致命错误!
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
Segmentation fault (core dumped)
typedef 特别高级的用法
chunli@ubuntu:~/pointer$ cat main.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct student ST;
struct student
{
char name[200];
int id;
};
typedef const char *(*FUNC1)(const char *str1,const char *str2) ;
const char *funcl(const char *str1,const char *str2)
{
printf("%s,%s \n",str1,str2);
return NULL;
}
const char *func2(FUNC1 p, const char *str1,const char *str2)
{
return p(str1,str2);
}
int main()
{
ST student1;
strcpy(student1.name,"奥巴马");
student1.id = 1;
printf("%d,%s \n",student1.id,student1.name);
return 0;
}
chunli@ubuntu:~/pointer$ gcc -std=c99 main.c && ./a.out
1,奥巴马
不使用typedef

使用typedef
