结构体

作者: Scott丶Wang | 来源:发表于2018-09-29 16:14 被阅读14次

一、了解结构体

在C语言中,除了最常见用的数据类型,字符类型(char)、整数类型(short、int、long )、实型(float、double)......最常见也是最经典的还有一种数据类型,那就是结构体。

二、结构体经典面试题:

(1)什么是结构体?
(2)一般在什么情况下用到结构体?
(3)什么是结构体内存对齐?为什么要对齐?怎样对齐?
(4)对齐参数如何设置?可以设置为按照任意字节数对齐吗?
(5)如何知道结构体某个成员相对于结构体起始位置的偏移量?

三、 下面,我们围绕以上提出的6个问题来解释结构体。

(1)什么是结构体?
定义:结构体是一系列数据的集合这些数据可能描述了一个物体,也可能是对一个问题的抽象。举个栗子,简单的说,对于人,人有名字,性别,年龄,身高,体重等个人信息,那么,我们在定义这种个体的时候,就不能说它能用一个字符或整型变量来定义。 这时候,就需要结构体闪亮登场了。
eg:

struct People {
    char name[20];
    int age;
    char gender[3];
    float height;
};

(2)一般在什么情况下用到结构体?

  • a、一般当内置内存无法满足用户需要,没有合适类型对应对象时,需要封装特定的类型
  • b、当函数有多个参数时,返回值过多,需要封装特定类型,将参数打包返回。

(3)什么是结构体内存对齐?为什么要对齐?怎样对齐?
eg:

struct A {
    int a;
    char b;
    double c;
    char d;
};

解析:
在windows系统32位平台上:
int占4个字节
char占1个字节
float占4个字节
double占8个字节
int a从0偏移开始,占四个字节,即占用0,1,2,3,现在可用偏移为4偏移,接下来存char b; 由于4是1的倍数,故而,b占用4偏移,接下来可用偏移为5偏移,接下来该存double c; 由于5不是8的倍数,所以向后偏移5,6,7,都不是8的倍数,偏移到8时,8是8的倍数,故而c从8处开始存储,占用8,9,10,11,12,13,14,15偏移,现在可用偏移为16偏移,最后该存char d ;因为16是1的倍数,故d占用16偏移,接下来在整体向后偏移一位,现处于17偏移,min(默认对齐参数,类型最大字节数)=8;因为17不是8的倍数,所以继续向后偏移18…23都不是8的倍数,到24偏移处时,24为8的整数倍,故而,该结构体大小为24个字节。


20171021163101071.png

方法总结:

  • a、从零偏移处开始,按字节大小计算,判断此偏移地址是否为该成员变量和对齐参数两者之间的最小值,即min(对齐参数,sizeof()成员);
  • b、若是,则从此处开始占用内存,大小为该类型所占字节数值,若不是,则内存向后偏移到最小值整数倍处,再开始占用空间。
  • c、按a、b、两步骤算出结构体实际所占内存时,为了方便后面类型的存储,再向后偏移一位,然后判断该地址是否是默认对齐数与该结构体中最大类型所占字节数的最小值 ,即:min(默认对齐参数,类型最大字节数)的整数倍,若是,则当前偏移地址的字节数便是结构体大小,若不是,继续向后偏移,直至为最小值整数倍为止。

(4)对齐参数如何设置?可以设置为按照任意字节数对齐吗?
解析:在windows中,VS编译器下,默认对齐数为8;
在Linux中,默认对齐数为4
设置对齐参数可在结构体struct之前加上#pragma pack(对齐数),在struct之后加上#pragma pack;便可以设置对齐参数。
eg:

#pragma pack(4)
struct A {
    int a;
    char b;
    double c;
    char d;
};
#pragma pack;

对齐参数不能任意设置,只能是内置类型已有的字节数,如:char(1)、short(2),int(4),double(8)…不能是3,5…任意数。

(5)如何知道结构体某个成员相对于结构体起始位置的偏移量?
使用offsetof宏来判断结构体中成员的偏移地址。使用offsetof宏需要包含stddef.h头文件,该宏定义如下:

#define offsetof(type,menber) (size_t)&(((type*)0)->member)

巧妙之处在于将地址0强制转换为type类型的指针,从而定位到member在结构体中偏移位置,编译器认为0是一个有效的地址,从而认为0是type指针的起始地址。

相关文章

  • 结构体

    [toc] 结构体的定义方式 先定义结构体类型,再定义结构体变量 定义结构体类型的同时定义结构体变量 定义结构体类...

  • 【C语言笔记】<十九>结构体

    结构体的基本概念 结构体初始化 结构体的内存存储细节 结构体定义的方式 结构体类型的作用域 指向结构体的指针 结构...

  • C结构体和链表

    一,结构体变量定义及初始化 二,无名结构体 备注:无名结构体很少使用 三,宏定义结构体 四,结构体嵌套 五,结构体...

  • 结构体

    结构体定义* 结构体中的格式:* struch 结构体名* {* 结构体成员变量* }* 结构体中的特点* 1.结...

  • 结构体数组的定义

    结构体数组的定义 1、先定义结构体类型,再定义结构体数组 2、定义结构体类型的同时定义结构体数组 3、省略结构体类...

  • C#结构体,析构方法,跨程序访问

    结构体 结构体定义 结构体的语法格式: struct + 结构体名 { 结构体成员变量(相当于类中的字段) } 结...

  • 结构体

    结构体有名定义 无名定义 结构体嵌套定义 结构体内存对齐 结构体成员初始化 结构体变量引用 结构体的有名定义:直白...

  • 菜鸡学Swift3.0 13.结构体

    结构体 struct 是值类型 1.定义结构体 struct 结构体类型 { var 结构体属性:类型 ...} ...

  • 结构体

    结构体初识 结构体指针 结构体的匿名字段 结构体嵌套 Go语言中的OOP

  • C语言 第九章 结构体

    [TOC] 第九章结构体 结构体的定义 结构体定义2 指针表示结构体

网友评论

      本文标题:结构体

      本文链接:https://www.haomeiwen.com/subject/vncboftx.html