目录
指针
自定义类型之结构体
指针
概念:就是一个地址(内存编号——本身是个数字),是一种类型,也是一个变量
类型:分两种,指针本身自己的类型和指针指向的类型;
指针类型占4个字节,而指针指向的类型所占字节由指向的类型决定;
指针指向空间的类型决定了能够访问多大的空间,以及对空间中的数据如如何解释;
运算:加减运算,
指针的加减并不是简单的加减,而是指针的偏移,即指针的加减不是以字节为单位, 而是以指向空间的类型大小为单位。
不同类型的指针:
基础类型指针:char* ,int* ,long* ,float* ,double* ,void*
char*:字符型指针,通产可以指向一个人字符串空间的首地址,模仿字符串操作 (因为在C语言中,没有字符串类型,只能用char来模仿),从首字符开始访问直到遇到 为止;
void*:无指向类型的指针,因此无法解引用,通常作为通用指针使用;
指针数组:一个数组,元素都是指针 例:int *arr[10]
数组指针:一个指针,指向一个数组 例:int (*p) [10]
数组名和&数组名:
数组名:通常表示一个数组的首元素的地址,指针步长是首元素的大小;
&数组名:数组的空间起始地址,与首元素地址在数值上相同,但是指向类型不同,&数组名指向的是数组,指针偏移步长是数组;
函数指针:一个指针,指向一个函数 例:int (*p) (int a, int b)
回调函数:定义一个函数之后不直接调用,而是把函数当作参数传递给其他函数,在 合适的时候被调用;
函数指针数组:一个数组,元素都是函数指针 例:int (*arr[10]) (int a, int b)
自定义类型之结构体
概念:是一种复杂的数据类型,其中可以包括多种基础的数据类型
当要描述的对象复杂时,用基础的数据类型比较麻烦,就选择使用结构体;
声明结构体类型:
struct dog_t
{
int size;
int weight;
char name[32];
char voice[32];
};
结构体变量中的成员变量,只有在初始化的时候可以通过赋值进行初始化,定义完毕后就不能使用赋值进行整体的成员变量初始化了。
结构体变量定义:
typedef struct dog_t
{
int size;
int weight;
char name[32];
char voice[32];
struct dog_t *dog2;//只能嵌套结构体指针或者已经定义的结构体,因为指针的大小是确定的
}_dog_t,*pdog_t;
//分三种:第一种,通过结构体的类型定义
_dog_t dog3[20]={{120, 20, "大黄", "汪汪汪"}};
pdog_t dog4 = dog3;
//第二种,通过结构体变量定义
struct dog_t dog1={120, 20, "大黄", "汪汪汪"};
//第三种,通过.操作符定义
struct dog_t dog2;
dog2.size=60;
dog2.weight=20;
strcpy(dog2.name,"旺仔");//不能直接赋值,所以用strcpy拷贝
strcpy(dog2.voice,"汪汪");
结构体内存对齐:
为什么需要内存对齐?
1.不是所有的硬件平台都支持随意地址访问;
2.提高结构体成员的访问效率;
(在CPU从内存中读取数据时,数据总线位数是32位,则一次可以读出4字节的数据,但是 如果从一个颗粒中读取的话是串行操作,为了提高效率,增加颗粒的个数,从每个存储颗 粒中取出1个字节,就可以并行地取出4个字节的数据。因此有些硬件平台CPU只能从指 定地址处取出指定大小的数据。)
内存对齐规则:
1.任何平台都有一个默认对齐数,vs的默认对齐数是8
(默认对齐数的修改:#pragma pack(n) //将默认对齐数设置为n
#pragma pack //还原默认对齐数
修改原因:网络通信将一个结构体变量(一块连续的内存数据)发送给了另一个主 机,如果两个平台的对齐数不同,在进行内存中数据解释的时候就会出现问题,换句 话说修改默认对齐数是为了统一)
2.结构体每个成员变量都有自己的一个独立的对齐数,就是成员变量的类型大小;
3.实际成员变量的对齐数是成员自己独立的对齐数与默认对齐数中小的那个;
4.每个成员变量都应该对齐到这个对齐数的整数倍处;
5.结构体的总大小应该是实际最大对齐数的整数倍大小,不足则在最后补位;
6.如果成员变量也是结构体变量,则这个结构体变量的对齐数是自己结构体中成员的最 大对齐数,大小为该结构体变量的大小。
例:
//32位平台下
struct tmp_t
{
char a;//0~3 1+补位3
int b;//4~7 4
double c;//8~15 8
char d;//16~23 1+补位7
};
结构体的位段:
一个结构体类型中可以有多个基础数据类型,但是在某些情况下,实际用到的字节并没有给的那么多,这个时候就用到了位段。
例:
struct student_t
{
int sn;
char sex:1;//0-男 1-女
char pos:2;//0-无 1-班长 2-学委 3-团支书
float score;
};
这个结构体大小是12个字节,但是实际上sex和pos分别占1、2个比特位就够了,所以这时候使用位段:member:n,表示使用指定空间的n个比特位存储数据。
使用位段需要注意:
1.共同使用一个字节是,在vs平台下,从地位开始存储;
2.多个位段使用同一块内存空间时,如果比特位不够则申请一个新的空间来存储数据;
3.位段进行数据存储时,不管数据的大小,只会在规定的位数上进行存储,所以当数据 过大时,会出现数据截断的情况。例如,用3个比特位存储10(二进制为1010)时,会截 取010进行存储;
4.位段的类型只能用整形,不能用浮点型;



