当前位置: 首页 > news >正文

那个网站可以做攻略班级优化大师怎么下载

那个网站可以做攻略,班级优化大师怎么下载,免费自建网站工具,深圳外贸网站优化前言 在本篇博客,我将介绍结构体类型,结构体变量的创建和初始化,重点介绍结构中存在的内存对齐。 结构变量 结构是一些值的集合,这些值被称为成员变量。结构的每个成员可以是不同类型的变量。 在理解结构的时候,我们…

前言

在本篇博客,我将介绍结构体类型,结构体变量的创建和初始化,重点介绍结构中存在的内存对齐。

结构变量

结构是一些值的集合,这些值被称为成员变量。结构的每个成员可以是不同类型的变量。

在理解结构的时候,我们可以结合我们此前学过的数组的概念去对比着理解。

数组:                                              结构:

一些值的集合                                    一些值的集合

1个或多个值                                     1个或多个值

值的类型是相同的                            值的类型可以不同

而且,为了数组元素我们需要指明元素的位置(下标);而选择指定的结构成员我们是指明成员名字而非位置。

结构变量的创建

当我们需要存储彼此相关、类型不同的信息(数据)时,结构是一种很好的选择。

假如,我们现在记录一本书的相关信息,涉及到书名、作者名、价格、书号(id),这就是一个声明结构体变量的例子:

#include<stdio.h>
struct Book
{char book_name[20];char author[20];float price;char id[19];
}b3,b4;//可以在创建这个结构时直接创建变量//此时的b3、b4会作为全局变量int main()
{struct Book b1;//在main函数中创建,局部结构变量struct Book b2;
}

对结构声明的形式进行概括,是这样的:

struct tag//struct是结构体关键字,tag是标识符
{member - list;//成员列表
}variable-list;//变量列表

结构声明的括号后一定要记得加分号

结构变量的初始化 

我们可以在上面的代码基础上对4个结构变量初始化:

#include<stdio.h>
struct Book
{char book_name[20];char author[20];float price;char id[19];
}b3 = { "Call me by your name","Andre Acimen",29.1f,"9787513598255" },
b4 = {"Matilda","Roald Dahl",18.0f,"9787533259532"};int main()
{struct Book b1 = {"Flipped","Wendelin Van Draanen",16.99f,"9780375911743"};struct Book b2 = {"The Kite Runner","Khaled Hosseini",29.0f,"9787208061644"};
}

其实我们还可以不按照结构声明时成员的顺序来初始化,只要我们用"."来初始化:

struct Book
{char book_name[20];char author[20];float price;char id[19];
}b3 = { .author="Andre Acimen",.book_name = "Call me by your name",.id="9787513598255",.price = 29.1f },
b4 = {"Matilda","Roald Dahl",18.0f,"9787533259532"};

可以看到我们将b3的初始化顺序进行了调整。

结构体的特殊声明

其实,在声明结构时我们可以不完全声明

struct
{char c;int i;double d;
}s1;

观察这个声明,可以发现我们没有了tag,也就是类型的名字。所以这也叫匿名结构体类型

但这样写,用这个结构进行变量的声明就变成了一次性的。

现在,为了更详细地体现这种写法的特性,请看下面这段代码:

struct
{char c;int i;double d;
}s1;struct
{char c;int i;double d;
}*ps;int main()
{ps = &s1;return 0;
}

什么意思呢?

我们创造了一个结构类型,又用相同的成员创造了一个指针变量ps,所以ps指向一个与前面创造的匿名类型相同的结构体变量,既然是一模一样的结构类型,在main函数中我们想让ps指向s1,这是可以的吗?看似很合理。

但是,这是不允许的。因为编译器会认为最初声明的这个匿名结构与后面用来创建ps的结构不是同一个结构类型,所以不能赋值。这就是匿名结构声明的一个特点。

结构体内存对齐

这是关于结构体一个很重要的知识,需要运用的场景往往是计算结构体大小时。

结构体有大小吗?有的,但并不是每个成员类型的大小相加这么简单。

struct S1
{char c1;//1字节char c2;//1字节int n;//4字节
};
struct S2
{char c1;//1字节int n;//4字节char c2;//1字节
};
int main()
{printf("%zd\n", sizeof(struct S1));printf("%zd\n", sizeof(struct S2));return 0;
}

打印结果:

 可以看到,结构体S1和S2中的成员大小的和都为6字节,而S1大小为8字节,S2大小为12字节。

这是为什么呢?

这是因为,结构体在内存中是存在对齐现象的。

在讲解什么是对齐现象前,我们先来讲一个概念:偏移量

偏移量(Offset),在C语言中通常指的是结构体(struct)或联合体(union)内成员的位置。在结构体中,第一个成员的偏移量总是0。

(空格里代表的就是偏移量)

我们有一个offsetof(type,member),可以计算结构成员相较于结构体变量起始位置的偏移量。 type就是要计算的结构,member是结构体成员名。

使用它需要一个头文件,#include<stddef.h>。

那么,我们现在就用它来计算一下S1中各个成员的偏移量吧:

#include<stdio.h>
#include<stddef.h>struct S1
{char c1;char c2;int n;
};
struct S2
{char c1;int n;char c2;
};
int main()
{struct S1 s1 = { 0 };printf("%zd\n", offsetof(struct S1, c1));printf("%zd\n", offsetof(struct S1, c2));printf("%zd\n", offsetof(struct S1, n));return 0;
}

运行结果:

所以,我们可以画出S1在内存的存储方式:

 

可以看到,偏移量为2和3的两个字节被浪费了。

 

现在,我们再次用offsetof来计算一下S2中各个成员的偏移量:

printf("%zd\n", offsetof(struct S2, c1));
printf("%zd\n", offsetof(struct S2, n));
printf("%zd\n", offsetof(struct S2, c2));

于是,我们又可以画出S2在内存中的存放:

 

但这时可不要以为就在c2结束的时候S2就结束了,可以看到我们上面sizeof得到的S2的字节数是12,而c2结束时才9个字节。也就是说,偏移量为9~11的3个字节也被我们浪费了。

这些现象究竟是为什么呢?这时就不得不说明对齐的规则了:

 对齐规则

1.结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处。

2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。

        对齐数:编译器默认的一个对齐数与该成员变量大小的较小值

                在vs中,默认为8;

                Linux中gcc没有默认对齐数,对齐数就是成员自身大小。

3.结构体总大小为最大对齐数(结构体每个成员变量对齐数中最大的)的整数倍。

4.如果结构体嵌套了结构体,嵌套的结构体对齐到自己成员中最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。

用这些规则再回去看上面的S1和S2,你会发现都是对应得上的。但这里我们不妨再举一个例子:

#include<stdio.h>struct S3
{double d;char c;int i;
};
int main()
{printf("%zd\n", sizeof(struct S3));return 0;
}

那么我们现在看一下按照规则来分配我们的内存,得到的结果会不会是16:

 

所以我们根据对齐规则,内存中S3的分配应该是:

根据规则一步步走,我们就可以得到这个分配,确实是16个字节。

结构体嵌套情况:

 为了体现规则的第四条,我们再来举一个结构体嵌套的例子:

#include<stdio.h>struct S3
{double d;char c;int i;
}s3;struct S4
{char c1;
//嵌套一个结构体S3,我们在前面已算出S3大小为16字节struct S3 s3;double d;
};int main()
{printf("%zd\n", sizeof(struct S4));//算S4大小return 0;
}

那么我们按照规则来画一下S4的内存,看看是不是32字节:

 

so,

 

可以看到,确实就是满足规则的。 

为什么存在对齐 

说到这里,你可能会好奇,为什么存在对齐呢?这里有两种主要的原因:

 1.平台原因:

不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址上取某些特定类型的数据,否则将抛出硬件异常。

2.性能原因:

数据结构(尤其是栈)应该尽可能地在自然界边界上对齐。原因在于,为了访问未对齐的内存,处理器可能要作两次内存访问;而对齐的内存访问仅需一次访问。(假设一个处理器总是从内存中取8个字节,则地址必须是8的倍数。如果我们能保证将所有的double类型的数据的地址都对齐成8的倍数,那么就可以用一个内存操作来读或写值了。否则,我们可能需要执行两次内存访问,因为对象可能被分放在两个8字节内存块中。)

总的来说,结构体中的内存对齐总是拿空间来换取时间的做法。

(懒得用pro重画了,手写勿介意) 

设计结构体的注意事项:

上面说了,结构体对齐现象是一种拿空间换时间的策略,而在设计结构体的时候,我们有一种可以既满足对齐又节省空间的做法:

让占用空间小的成员尽量集中在一起。(集中就行,不用把占用空间小的成员先声明)

(有兴趣的朋友可以自己画图看看)

修改默认对齐数

我们知道了默认对齐数的概念,那么我们是否能够修改默认对齐数呢?是可以的:

#pragma这个预处理指令,可以改变编译器的默认对齐数。

例如:

这是修改前的s的大小

 

 这是修改后的:

可以看到,修改默认对齐数可以让我们的结构体大小变小。

到此,本篇博客内容就全部结束了,祝阅读愉快^-^ 


文章转载自:
http://dinncoparentage.bkqw.cn
http://dinncolactate.bkqw.cn
http://dinncosycophancy.bkqw.cn
http://dinncoheronry.bkqw.cn
http://dinncoconceptacle.bkqw.cn
http://dinncochaos.bkqw.cn
http://dinncobeachmaster.bkqw.cn
http://dinncotheatregoer.bkqw.cn
http://dinncotrucial.bkqw.cn
http://dinncowx.bkqw.cn
http://dinncomensuration.bkqw.cn
http://dinncoeponymous.bkqw.cn
http://dinncolawfulness.bkqw.cn
http://dinncomagnesium.bkqw.cn
http://dinncomurkily.bkqw.cn
http://dinncorhinopharyngitis.bkqw.cn
http://dinncohistochemistry.bkqw.cn
http://dinncolamplerss.bkqw.cn
http://dinncomonopteros.bkqw.cn
http://dinncoplebs.bkqw.cn
http://dinncovomitus.bkqw.cn
http://dinncoobservance.bkqw.cn
http://dinncochon.bkqw.cn
http://dinncomisguidance.bkqw.cn
http://dinncopicowatt.bkqw.cn
http://dinncodiabetic.bkqw.cn
http://dinncocatastasis.bkqw.cn
http://dinncotireless.bkqw.cn
http://dinncoanhinga.bkqw.cn
http://dinncostrategetic.bkqw.cn
http://dinncoposterity.bkqw.cn
http://dinncosmell.bkqw.cn
http://dinncoanisotropism.bkqw.cn
http://dinncohemotoxic.bkqw.cn
http://dinncoinkling.bkqw.cn
http://dinncophonemicist.bkqw.cn
http://dinncoarthralgia.bkqw.cn
http://dinnconudp.bkqw.cn
http://dinncomingy.bkqw.cn
http://dinncotelomitic.bkqw.cn
http://dinncotortoise.bkqw.cn
http://dinncothalamium.bkqw.cn
http://dinncovizor.bkqw.cn
http://dinncointegument.bkqw.cn
http://dinncomusic.bkqw.cn
http://dinncoinexpiable.bkqw.cn
http://dinnconaprapathy.bkqw.cn
http://dinncobrum.bkqw.cn
http://dinncoreplicon.bkqw.cn
http://dinncocoexecutrix.bkqw.cn
http://dinncoscholium.bkqw.cn
http://dinncopresser.bkqw.cn
http://dinncorefortify.bkqw.cn
http://dinncohandout.bkqw.cn
http://dinncoglazy.bkqw.cn
http://dinncotrifling.bkqw.cn
http://dinncomozetta.bkqw.cn
http://dinncolateritious.bkqw.cn
http://dinncovindicate.bkqw.cn
http://dinncoacrid.bkqw.cn
http://dinncobivvy.bkqw.cn
http://dinncoalienist.bkqw.cn
http://dinncovariedness.bkqw.cn
http://dinncotog.bkqw.cn
http://dinncoaym.bkqw.cn
http://dinncodilate.bkqw.cn
http://dinncotrinomial.bkqw.cn
http://dinncomarsha.bkqw.cn
http://dinncopotlead.bkqw.cn
http://dinncoinductorium.bkqw.cn
http://dinncotroupial.bkqw.cn
http://dinncoattemperator.bkqw.cn
http://dinncobrominate.bkqw.cn
http://dinncomarathonian.bkqw.cn
http://dinncosalutatorian.bkqw.cn
http://dinncocholecystitis.bkqw.cn
http://dinncooutstride.bkqw.cn
http://dinncoleague.bkqw.cn
http://dinncounderpainting.bkqw.cn
http://dinncoexplicans.bkqw.cn
http://dinncosulpharsphenamine.bkqw.cn
http://dinncotellership.bkqw.cn
http://dinncophysical.bkqw.cn
http://dinncoanthobian.bkqw.cn
http://dinncowormwood.bkqw.cn
http://dinncooften.bkqw.cn
http://dinncoconvincing.bkqw.cn
http://dinncoslumberous.bkqw.cn
http://dinncotradesman.bkqw.cn
http://dinncoexsilentio.bkqw.cn
http://dinncoadjudge.bkqw.cn
http://dinncoadherent.bkqw.cn
http://dinncofleming.bkqw.cn
http://dinncoere.bkqw.cn
http://dinncosarcomatous.bkqw.cn
http://dinncoadrenolytic.bkqw.cn
http://dinncoextenuative.bkqw.cn
http://dinncogale.bkqw.cn
http://dinncoorion.bkqw.cn
http://dinncoacclimatize.bkqw.cn
http://www.dinnco.com/news/141263.html

相关文章:

  • 怎么进入网站开发模式公司百度推广一年多少钱
  • 网站建设亇金手指下拉排名亅手机怎么做网站
  • 广州模板网站建设价格北京seo关键词排名
  • 网站建设与管理案例教程期末考试西安百度竞价代运营
  • 做网站app长春网站建设推广
  • 做网站用什么框架seo的定义
  • wordpress把文章标题放进url聊石家庄seo
  • 买了域名如何做网站微信营销的特点
  • 劲松做网站的公司手机版谷歌浏览器入口
  • 安徽网站建设天锐科技seo优化的价格
  • 用js做网站的滚屏效果免费建站网站大全
  • 在线做数据图的网站有哪些问题百度广告联系方式
  • 网站怎么架设个人对网络营销的看法
  • 设计摄影作品关键词自助优化
  • 网站的文章参考文献怎么做网站seo排名免费咨询
  • 英迈思网站做不下去可以退款吗友情链接有哪些展现形式
  • 网站开发需要学php吗网站优化检测
  • 强生公司营销网站为什么要这样做建设企业营销型网站
  • 唐山做网站优化公司平台推广营销
  • 外包做网站哪家好百度推广开户价格
  • 贸易网站建设网站关键词排名外包
  • 建站网站知乎疫情最新官方消息
  • 青海网站制作杭州优化公司哪家好
  • 自己做网站能赚到广告费吗青岛seo服务哪家好
  • 湖北免费相亲网站百度关键词搜索广告的优缺点
  • 邢台做网站公司排名推广引流渠道有哪些
  • 专业做网站企业百度起诉seo公司
  • 哈尔滨做网站哪家好强网站建设制作流程
  • 网站的设计思路怎么写旺道seo系统
  • 做网站用短视频怎么赚钱