1.结构体变量中的元素如何访问?

(1)数组中元素的访问方式:表面上有2种方式(数组下标方式和指针方式);实质上都是指针方式访问。
(2)结构体变量中的元素访问方式:只有一种,用.或者->的方式来访问。(.和->访问结构体元素其实质是一样的,只是C语言规定用结构体变量来访问元素用. 用结构体变量的指针来访问元素用->。实际上在高级语言中已经不区分了,都用.)
(3)结构体的访问方式有点类似于数组下标的方式

2.利用指针访问结构体元素

  结构体元素地址=结构体首地址+元素偏移量

  

struct mystruct
{
int a;
int b; } s1; //s1.b的地址
int* p=(int*)((int)&s1+);
*p=;// s1.b=5;

3.结构体对齐

  一般情况下,为了配合硬件,如果对齐排布和访问会提高效率,否则会大大降低效率。

  (0)、一般编辑器默认4字节对齐。

  (1)、结构体对齐要考虑:结构体整体本身必须安置在4字节对齐处,结构体对齐后的大小必须4的倍数(编译器设置为4字节对齐时,如果编译器设置为8字节对齐,则这里的4是8)
  (2)、结构体中每个元素本身都必须对其存放,而每个元素本身都有自己的对齐规则。
  (3)、编译器考虑结构体存放时,以满足以上2点要求的最少内存需要的排布来算。

struct mystruct1
{    // 1字节对齐 4字节对齐
int a;         // 4 4
char b; // 1 2(1+1)
short c;   // 2 2
}; struct mystruct11
{ // 1字节对齐 4字节对齐
int a; // 4 4
char b; // 1 2(1+1)
short c;   // 2 2
}; typedef struct mystruct111
{ // 1字节对齐 4字节对齐 2字节对齐
int a; // 4 4 4
char b; // 1 2(1+1) 2
short c; // 2 2 2
short d; // 2 4(2+2) 2
} My111; typedef struct mystruct2
{ // 1字节对齐 4字节对齐
char a; // 1 4(1+3)
int b; // 4 4
short c;  // 2 4(2+2)
}MyS2; struct mystruct21
{ // 1字节对齐 4字节对齐
char a; // 1 4(1+3)
int b; // 4 4
short c; // 2 4(2+2)
} ;
typedef struct myStruct5
{ // 1字节对齐 4字节对齐
int a; // 4 4
struct mystruct1 s1; // 7 8
double b; // 8 8
int c; // 4 4
}MyS5; struct stu
{ // 1字节对齐 4字节对齐
char sex; // 1 4(1+3)
int length; // 4 4
char name[]; // 10 12(10+2)
};

4.结构体对齐指令

  以#prgama pack(n)开头,以#pragma pack()结尾,定义一个区间,这个区间内的对齐参数就是n。

#pragma pack(2)

struct s
{
char c; //2 (1+1)
int b; //4 (4) } ;
#pragma pack()

  取消对齐访问
  __attribute__((packed));
  设置结构体整体对齐访问(不包含元素)
  __attribute__((aligned(n)));

  

struct mystruct11
{ // 1字节对齐 4字节对齐
int a; // 4 4
char b; // 1 2(1+1)
short c; // 2 2
}__attribute__((packed)); typedef struct mystruct111
{ // 1字节对齐 4字节对齐 2字节对齐
int a; // 4 4 4
char b; // 1 2(1+1) 2
short c; // 2 2 2
short d; // 2 4(2+2) 2
}__attribute__((aligned())) My111;

5.offsetof宏与container_of宏

offsetof            在0地址处虚拟出一个结构体,通过元素的地址则为偏移量

container_of     通过元素地址减去偏移量得到结构体地址

typeof()传入变量,返回相应的数据类型。
#include<stdio.h>

struct mystruct
{
char a;
int b;
short c; };
// TYPE是结构体类型,MEMBER是结构体中一个元素的元素名
// 这个宏返回的是member元素相对于整个结构体变量的首地址的偏移量,类型是int
#define offsetof(TYPE, MEMBER) ((int) &(((TYPE *)0)->MEMBER))//TYPE *为传入值 // ptr是指向结构体元素member的指针,type是结构体类型,member是结构体中一个元素的元素名
// 这个宏返回的就是指向整个结构体变量的指针,类型是(type *)
//typeof() 是通过变量名 返回数据类型的
#define container_of(ptr, type, member) ({ \
const typeof(((type *))->member) * __mptr = (ptr); \ //定义一个typeof(((type *)0)->member)类型的指针指向 结构体元素地址
(type *)((char *)__mptr - offsetof(type, member)); }) //元素地址-偏移量=结构体首地址
//通过元素地址减去偏移量得到结构体地址
int main()
{
struct mystruct s1;
struct mystruct *Ps;
s1.b=;
int * pb=&s1.b;
Ps=container_of(pb,struct mystruct,b);
printf("container_of宏实例\n");
printf("&s1=%p\n",&s1);
printf("Ps=%p\n",Ps); //int *p=(int *)((char*)&s1+4);
int *p=(int *)((int)&s1+);
printf("*p=%d.\n",*p);
printf("offsetof宏实例\n");
int offsetof_a=offsetof(struct mystruct,a);
int offsetof_b=offsetof(struct mystruct,b);
int offsetof_c=offsetof(struct mystruct,c);
printf("offsetof_a=%d\n",offsetof_a);
printf("offsetof_b=%d\n",offsetof_b);
printf("offsetof_c=%d\n",offsetof_c); return ; }

C语言结构体对齐的更多相关文章

  1. 解析C语言结构体对齐(内存对齐问题)

    C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...

  2. 结构体对齐及#pragma详细解释

    在linux下c语言结构体对齐: 1.自然对齐 struct 是一种复合数据类型,其构成元素既可以是基本数据类型(如int.long.float 等)的变量,也可以是一些复合数据类型(如array.s ...

  3. C语言基础--结构体对齐,位域,联合体

    结构体对齐 1--结构体对齐的原因与意义 许多计算机系统对基本数据类型的可允许地址做出了一些限制,要求某种类型的对象的地址必须是某个值K(通常是2,4,8)的倍数,而这个k则被称为该数据类型的对齐模数 ...

  4. C语言中结构体对齐问题

    C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...

  5. 4-17疑难点 c语言之【结构体对齐】

    今天学习了结构体这一章节,了解到了结构体在分配内存的时候采取的是对齐的方式 例如: #include<stdio.h> struct test1 { int a; char b; shor ...

  6. [置顶] 什么是C语言结构体字节对齐,为什么要对齐?

    一.概念 对齐跟数据在内存中的位置有关.如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐.比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的.   ...

  7. C语言结构体的字节对齐原则

    为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址访问,这就需要各种类型数据 ...

  8. 漫谈C语言结构体struct、公用体union空间占用

    先用代码说话: #include<stdio.h> union union_data0{ int a ;//本身占用4个字节 char b ;//本身占用1个字节 int c ; }; u ...

  9. 浅谈c语言结构体

    对于很多非计算机专业来说,c语言课程基本上指针都不怎么讲,更别说后面的结构体了.这造成很多学生对结构体的不熟悉.这里我就浅谈一下我对结构体的认识. 结构体,就是我们自己定义出一种新的类型,定义好之后, ...

随机推荐

  1. Base-64 字符数组或字符串的长度无效等问题解决方案

    项目特殊需要,调用ActiveX三维控件进行控件某一特殊部位的截图操作,这个截图保存由ActiveX控件控制保存到本地是没问题的,现在需要将这个截图上传到服务器,多人共享,就牵扯到需要读取本地文件…… ...

  2. WIN7下查看CPU核心数

    方法一 WIN+R输入cmd,输入wmic,输入cpu get *(注意空格),找到numberofcores和numberoflogicalprocessors,如下图为双核4线程,真核心数是2,使 ...

  3. ASP.NET MVC 利用IRouteHandler, IHttpHandler实现图片防盗链

    你曾经注意过在你服务器请求日志中多了很多对图片资源的请求吗?这可能是有人在他们的网站中盗链了你的图片所致,这会占用你的服务器带宽.下面这种方法可以告诉你如何在ASP.NET MVC中实现一个自定义Ro ...

  4. 在DevExpress中使用CameraControl控件进行摄像头图像采集

    在我们以前的项目了,做摄像头的图片采集,我们一般还是需要做一个封装处理的,在较新版本的DevExpress控件里面,增加了一个CameraControl控件,可以直接调用摄像头显示的,因此也可以做头像 ...

  5. ASP.NET MVC——Razor视图引擎

    Razor是MVC框架视图引擎,我们今天就来说一说Razor视图引擎. 首先还是来创建一个基础项目叫Razor来演示. 先来定义一个Model叫Product public class Product ...

  6. 阅读微信支付demo收获

       1,公司现有系统有很多,存放重要接口的日志分布在不同的库,每个系统都有单独的日志采集表,日志采集模块:        ????         这些日志可以统一放到一个地方,通过一个组件提供出去 ...

  7. javaweb

    关于java,作为一个初学者,作为一个即将跨入其中的钻研者,我觉得我很必要好好地升入其中认真学习每一个环节

  8. jQuery的$.ajax

    在介绍JSONP之前,先简单的介绍一些JSON.JSON是JavaScript Object Notation的缩写,是一种轻量的.可读的基于文本的数据交换开放标准.源于JavsScript编程语言中 ...

  9. elasticsearch高级配置二----线程池设置

    一个Elasticsearch节点会有多个线程池,但重要的是下面四个: 索引(index):主要是索引数据和删除数据操作(默认是cached类型) 搜索(search):主要是获取,统计和搜索操作(默 ...

  10. 安装cocoapods遇到两大坑-Ruby版本升级和Podfile的配置

    今天安装cocoapods #移除原有ruby源 $ gem sources --remove https://rubygems.org/ #使用可用的淘宝网 $ gem sources -a htt ...