首先简单定义一个结构体:
- 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};
当你定义了一个结构体,且未定义结构体变量时:
- struct{
- int x;
- int y;
- };
则不需要为它分配存储空间,因为它仅仅描述了一个结构的模板或轮廓。结构体变量才包含了实实在在的数据、需要存储空间。
像下面那样,其中的 struct point pt 就表示声明了一个结构体变量:

关于结构体所占的字节大小,需要注意,千万不要认为结构体的长度等于各成员长度的和,因为不同的对象有不同的对齐要求(可以查下关于字节对齐的资料,这里不展开),因此,结构中可能会出现未命名的“空穴”(hole)。例如以下代码:
- #include
-
- 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个。
如果传递给函数的结构很大,使用指针方式的效率通常比复制整个结构的效率要高。结构体指针类似于普通变量指针:
struct point *pp
以上一句,将pp定义为一个指向struct point类型对象的指针,注意上述定义只说明了pp指针指向的对象类型是struct point类型,并未指向point这个结构,所以还访问不了point结构里的成员。那么想要正确访问point中的成员,得记得让指针指向point结构,比如下面这样:
- #include
-
- 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;
比如以下代码,重点关注下其中的 ++pp->x 的输出:
- #include
-
- 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级先执行):
