文章目录
1、结构体的定义以及初始化
①定义结构体
②对结构体变量进行初始化
2、结构体在内存中的分配以及字节大小
①存储空间如何分配?
②结构体所占字节大小如何计算?
3、结构体指针和结构体变量的区别
①结构体指针如何进行访问?
②结构体指针和结构体变量的区别
4、易搞混的结构体指针运算顺序举例
1、结构体的定义以及初始化
①定义结构体
首先简单定义一个结构体:
struct point {
int x;
int y;
};
//当然你可以写成struct point{int x; int y;}; 都是一样的,缩进不同罢了
以上代码中,关键字 struct 引入结构声明,结构声明由包含在花括号内的一系列声明组成。
struct后面的名字是可选的,被称为 结构标记 (这里是point)。 结构标记用于为结构命名,在定义之后,结构标记就代表花括号内的声明,可以用它作为该声明的简写形式。比如在后面定义结构体变量的时候,就可以写成:
struct point pt; //定义了一个结构体变量pt
如果你不想使用结构标记,那么定义变量时你需要把花括号内的声明也写上,写成:
struct{
int x;
int y;
}pt;
//当然你可以写成struct{int x; int y;}pt; 都是一样的,缩进不同罢了
②对结构体变量进行初始化
接下来对结构体变量进行初始化,比如将x赋值为10,y赋值为20:
struct{
int x = 10;
int y = 20;
}pt;
也可以这样写:
struct point pt = {10, 20};
2、结构体在内存中的分配以及字节大小
①存储空间如何分配?
当你定义了一个结构体,且未定义结构体变量时:
struct{
int x;
int y;
};
则不需要为它分配存储空间,因为它仅仅描述了一个结构的模板或轮廓。结构体变量才包含了实实在在的数据、需要存储空间。
像下面那样,其中的 struct point pt 就表示声明了一个结构体变量:
②结构体所占字节大小如何计算?
关于结构体所占的字节大小,需要注意,千万不要认为结构体的长度等于各成员长度的和,因为不同的对象有不同的对齐要求(可以查下关于字节对齐的资料,这里不展开),因此,结构中可能会出现未命名的“空穴”(hole)。例如以下代码:
#include<stdio.h>
struct point
{
char x; //char占1个字节
int y; //int占4个字节
};
int main() {
struct point pt;
printf("%d", sizeof pt); //输出8而不是5
return 0;
}
这里的存储空间需要8个字节而不是5个。
3、结构体指针和结构体变量的区别
①结构体指针如何进行访问?
如果传递给函数的结构很大,使用指针方式的效率通常比复制整个结构的效率要高。结构体指针类似于普通变量指针:
struct point *pp
以上一句,将pp定义为一个指向struct point类型对象的指针,注意上述定义只说明了pp指针指向的对象类型是struct point类型,并未指向point这个结构,所以还访问不了point结构里的成员。那么想要正确访问point中的成员,得记得让指针指向point结构,比如下面这样:
#include<stdio.h>
struct point
{
int x = 10;
int y = 20;
};
int main() {
struct point pt; //声明一个结构体变量
struct point *pp; //声明一个结构体指针
pp = &pt; //让指针指向point结构,这样才能进行后续对结构体成员的访问
printf("%d", (*pp).x); //输出10
return 0;
}
下面来解释下访问方式 (*pp).x ,其中圆括号是必需的,因为结构成员运算符“.”的优先级比“*”的优先级高,表达式*pp.x的含义等价于*(pp.x),因为x不是指针,所以该表达式是非法的。
当然还有其它访问方式,如下:
//p->结构成员
printf("%d", pp->x); //输出10
②结构体指针和结构体变量的区别
现在来说下结构体指针和结构体变量的区别:
1.内存空间上面的差别
假设有如下代码:
struct Stu
{
int age;
}*p, q;
结构体指针p是指向一个结构体的,如果需要使用这个结构体就必须malloc一个空间出来或者将一个具有空间的结构体的首地址赋予它;如果你不给它分配空间代表这是一个野指针,访问的时候会出错;而结构体变量q,在定义变量的时候,编译器就自动给变量分配了合适的储存空间。
2.访问上的差别
结构体指针访问成员变量的操作符是 “->”,结构体变量访问成员变量的操作符是“.”
指针想用“.”操作符,得写成(*p).age <=> p->age;
4、易搞混的结构体指针运算顺序举例
比如以下代码,重点关注下其中的 ++pp->x 的输出:
#include<stdio.h>
struct point
{
int x = 10;
int y = 20;
} *pp;
int main() {
struct point pt;
pp = &pt;
printf("%d", ++pp->x); //输出11
return 0;
}
表达式
++pp->x;
将增加x的值,而不是增加pp的值,这是因为,“->”的优先级比自增“++”更高!所以这里的隐含关系相当于++(pp->x)。
补充一张运算符优先级参考截图(1级比2级先执行):