PPC的C/C++和人工智能学习笔记
每一篇学习笔记,都只是为了更好地掌握和理解

C语言基础(14)_结构体

今天学习C语言的结构体。

 

结构体:由若干个成员(基本数据成员/或者构造类型)组成

struct 结构体名

{

成员列表;

}; //注意;不能省略

 

几种定义结构体变量的方法:

一:在结构体定义的过程中定义结构体变量,如:

struct student{

char name[20];

int age;

}myStu; //直接跟在后面 定义变量

二:先定义结构体,再定义结构体变量

struct student{

char name[20];

int age;

};

struct student myStu; //myStu是变量名,前面的struct student 是结构体类型

三:用typedef

typedef struct student{

char name[20];

int age;

}student,*pstudent; //这里student是 struct student 的别名,pstudent 是 struct student *的别名,是个指针类型的别名。

student myStu; //后面定义就只要这样写了,习惯用这种

Pstudent pmyStu=&mystu; //这里 pmyStu已经是指针变量了。

 

当然,结构体变量也区分全局变量和局部变量。

 

结构体变量的初始化:

一:可以在定义的同时初始化:

student myStu={“王十三”,22};

注意,{ } 里面的内容次序必须和结构体的成员次序和类型一致,后面的成员可以不初始化,但是不能跳跃。比如 studeng myStu={“王十三”}; 这样是可以的,而且后面的成员会以0初始化。

还要注意:结构体变量一旦定义好,就不能用这样的方法初始化了。比如:studeng myStu; myStu = {“xxx”,20}; 这样的写法是错误的。

二:使用 结构体变量.成员 的方式进行赋值和读取

student myStu;

myStu.age = 20;

strcpy(myStu.name,”王大”);

printf(“%s,%d\n”, myStu.name, myStu.age);

 

结构体数组:有多个结构体变量连续存储的一种结构,和普通数组一样的。

student myStu[4];

myStu[0].age = 20;

myStu[1].age = 30;

用法和数组一样,只不过多了个访问成员变量。

 

结构体指针:指向结构体的指针

定义的时候, struct student * pmyStu; //这个是没有 typedef 的定义

按照我们前面写的 typedef的定义,可以直接写 pstudent pmyStu;

操作方法:

(*pmyStu).age,这个是用指针表达的常规写法

习惯上,我们用这个:pmyStu->age

 

结构体的嵌套:

结构体的内部成员,也可以是结构体。

比如:

struct score{

int math_score;

int english_score;

};

struct student{

char name[20];

int age;

struct score stscore; //这里是结构体

};

 

共用体:共用体也叫做联合体,变量存放在一段内存的单元中的一种结构叫做共用体。

union: 联合。(共用体)

多个成员共用一个地方。

union IP{

char i4[4];

int net;

};

sizeof(union IP) 是4。因为是共用的。取最大的。

一般union不用初始化,一定要初始化的话,就是初始化第一个成员。

union IP myip={192,168,1,20};

printf(“%x\n”,myip.net); ==> 输出 类似 20 1 168 192

所以,int整数在内存中的存放,低位在前面,高位在后面。(但是不同的cpu可能不同)。小的在前面(低位在前面)称为:小端。 大的在前面(高位在前面)称为:大端。

共用体(联合体)的使用,除了成员共用内存外,其他的类似结构体。

 

枚举类型:包含一组相关的标识符,每个标识符对应一个整数值(枚举常量)。

例子:enum Colors{ Red, Green, Blue }; //这里默认的情况,Red=0,Green=1,Blue=2

enum Colors{ Red=10, Green=15, Blue =25}; //也可以自己指定

enum Colors{ Red=1, Green, Blue }; //局部指定,那么后面的自动+1

enum ss {Left,Right=10,Down,Up=20};//对应0 10 11 20

printf(“%d,%d,%d,%d\n”, Left, Right, Down, Up); //输出0,10,11,20

 

结构体和联合体的对齐与补齐:

typedef struct Goods{

char name[18]; //18

double price;  // 8

//char special;  // 1

int num;    //4

//short saled;   //2

}gs;

int main(){

printf(“%d\n”,sizeof(gs)); //结果是32,如果把special前面的注释去掉,结果是36

}

 

一个变量的地址,是这个变量本身占的字节数的倍数。(编译器这样做)

主要目的是,访问速度快。

 

char 类型,因为是1个字节,所以地址是随意的。

short类型,因为是2个字节,地址是2的倍数。

int,地址是4的倍数。

double, 8字节,有的编译器是严格按照8的倍数,但是有些编译器,超过4字节的,就以4的倍数来定义地址。

 

有了上面的知识,来分析上面的那个结构体:

char name[18]; –>从 0开始,17结束。

double price;  –>不是从18开始,要从20开始(4的倍数),28结束。(或者有的编译器要从24开始(8的倍数))

char special;  –>28开始,29结束。

int num;       –>32开始,到35结束。

short saled;   –>36开始,37结束。 –>但是这里sizeof(gs)就是40了,不是38!(这里是补齐的概念)

 

因为要对齐,所以才会造成上面的结果。

 

补齐是为了解决,接下去需要存放的其他数据的起始地址问题。

同类型的变量,内部结构(内存存放)必须是一样的。

所以,结构变量的总长度,要补成最大成员类型长度的倍数(超过4就按4来计算)

 

所以,上面的38,就变为40了。称为“补齐”。

 

所以,可以适当调整成员的次序,来减少整个结构变量的占内存大小。

(比如,上面,把 short saled 放在第2个位置,结构变量sizeof 从40减少为36了)

 

位段: 需要按位处理的(不是按照字节来处理)

struct mode{ //处理权限 rwxrwxrwx

unsigned char userread:1;

unsigned char userwrite:1;

unsigned char userexecute:1;

unsigned char groupread:1;

unsigned char groupwrite:1;

unsigned char groupexecute:1;

unsigned char otherread:1;

unsigned char otherwrite:1;

unsigned char otherexecute:1;

};

 

struct mode m={1,1,0,1,0,0,1,0,0}; //644权限

上面这个是9位,sizeof(struct mode) 就是2, 结构中成员的最大字节数(超过4取4).

 

超过8位的话,用:unsigned int aaa:10; //这样的话 sizeof(struct mode) 就要以 int 的4位作为最小倍数了。

 

位段,在嵌入式开发中用得比较多。

 

 

(2017-02-26 www.vsppc.com)

学习笔记未经允许不得转载:PPC的C/C++和人工智能学习笔记 » C语言基础(14)_结构体

分享到:更多 ()

评论 83

评论前必须登录!