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

flash同视频做网站windows优化大师是电脑自带的吗

flash同视频做网站,windows优化大师是电脑自带的吗,个人网站案例,一起做网店 网站打不开柔性数组 一、前言二、柔性数组的用法三、柔性数组的内存分布四、柔性数组的优势五、总结 一、前言 仔细观察下面的代码,有没有看出哪里不对劲? struct S {int i;double d;char c;int arr[]; };还有另外一种写法: struct S {int i;double …

柔性数组

    • 一、前言
    • 二、柔性数组的用法
    • 三、柔性数组的内存分布
    • 四、柔性数组的优势
    • 五、总结

一、前言

仔细观察下面的代码,有没有看出哪里不对劲?

struct S
{int i;double d;char c;int arr[];
};

还有另外一种写法:

struct S
{int i;double d;char c;int arr[0];
};

你应该一眼就看到了,结构体的最后一个成员数组的写法是int arr[];或者是int arr[0],这两种写法是等价的,意思是这个数组的大小是不确定的、未知的、可以变化的

C99允许这种特殊的结构体存在。这样的结构体满足下面两个条件:

  1. 最后一个成员变量是一个大小可以变化的数组。
  2. 这个成员数组前面至少有另外一个成员变量。

我们称这个大小可以变化的成员数组为柔性数组

注意,柔性数组不能是结构体里唯一一个成员,下面的代码是不允许的:

struct S
{int arr[0];
};

这篇文章里,我将重点探讨柔性数组的用法、内存分布以及和优势。

二、柔性数组的用法

我不建议在栈上直接定义有柔性数组的结构体,也就是这么写:

struct S s;

因为柔性数组的大小是可以变化的,我建议在堆上申请空间,采取动态内存管理的方法,这样就能发挥出柔性数组大小可以改变的优势。

假设我们使用malloc()函数来开辟空间,一开始应该malloc出多大的空间呢?要回答这个问题,首先我们要知道sizeof(struct S)是多少。

事实上,sizeof(struct S)计算出来的结果是该结构体不考虑柔性数组的大小。如果我们想要给柔性数组开辟空间,malloc出来的大小应该是sizeof(struct S)加上柔性数组的大小。

假设这个柔性数组在结构体中的声明是int arr[0];,我想给这个数组的大小是40个字节,这样这个数组就能存储10个int,那么一开始malloc的大小就应该是sizeof(struct S)+10*sizeof(int),具体的例子如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}return 0;
}

该结构体中的i,d,c等变量可以正常使用。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->i = 10;ps->d = 3.14;ps->c = 'F';return 0;
}

柔性数组也可以像正常的数组一样访问,比如把1~10放进去。注意此时这个数组的容量是10个int,不能越界访问。使用的例子如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->i = 10;ps->d = 3.14;ps->c = 'F';for (int i = 0; i < 10; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}printf("\n");return 0;
}

我们还可以对柔性数组扩容,如果我们想让这个柔性数组的容量是20个int,整个结构体的新的大小就是sizeof(struct S)+20*sizeof(int),因为sizeof(struct S)是不考虑柔性数组的大小时计算的结构体大小。只需要对ps进行realloc就行了。实现代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->i = 10;ps->d = 3.14;ps->c = 'F';for (int i = 0; i < 10; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}printf("\n");struct S* tmp = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));if (tmp == NULL){printf("realloc()->%s\n", strerror(errno));return 1;}else{ps = tmp;}return 0;
}

扩容后的柔性数组的空间更大了,我们可以把11~20都放进去。实现代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->i = 10;ps->d = 3.14;ps->c = 'F';for (int i = 0; i < 10; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}printf("\n");struct S* tmp = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));if (tmp == NULL){printf("realloc()->%s\n", strerror(errno));return 1;}else{ps = tmp;}for (int i = 10; i < 20; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 20; i++){printf("%d ", ps->arr[i]);}return 0;
}

当然最后别忘了free掉ps,否则会导致内存泄漏。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S) + 10 * sizeof(int));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->i = 10;ps->d = 3.14;ps->c = 'F';for (int i = 0; i < 10; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}printf("\n");struct S* tmp = (struct S*)realloc(ps, sizeof(struct S) + 20 * sizeof(int));if (tmp == NULL){printf("realloc()->%s\n", strerror(errno));return 1;}else{ps = tmp;}for (int i = 10; i < 20; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 20; i++){printf("%d ", ps->arr[i]);}free(ps);ps = NULL;return 0;
}

对于柔性数组的使用,在上面的例子中,可以总结出几个要点:

  1. malloc出来的大小是sizeof(struct S)加上柔性数组的大小,calloc同理。
  2. 扩容时realloc出来的新大小也是sizeof(struct S)加上柔性数组的新大小。
  3. 每次使用malloc和realloc等函数时,需要检查返回值,否则可能导致对NULL指针的解引用(这点是动态内存管理的常识了)。
  4. 一定要记得柔性数组的容量是多少,不要越界访问了,空间不够记得扩容。
  5. 记得free,防止内存泄漏。

三、柔性数组的内存分布

柔性数组是结构体的一个成员数组,在前面的例子中,整个结构体都是在堆上malloc出来的。此时,整个结构体都存储在堆上的一块连续的空间里,包括前面几个成员变量i,d,c和柔性数组arr。也就是这样:
在这里插入图片描述
只不过数组arr的大小是可以改变的,所以叫“柔性数组”。

有些朋友可能会说了,我不需要柔性数组也能实现类似这样的效果呀!我在结构体里存一个指针,指向一块malloc出来的空间,这块空间也是堆上的,可以动态管理。也就是说,像下面这样定义结构体:

struct S
{int i;double d;char c;int* arr;
};

这样似乎还简单一点,先malloc出一个struct S出来,malloc的大小就是sizeof(struct S),像这样:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}return 0;
}

然后再malloc出10个int的大小出来,用结构体中的arr指针来管理这块空间,像这样:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->arr = (int*)malloc(10 * sizeof(int));if (ps->arr == NULL){printf("2: malloc()->%s\n", strerror(errno));return 1;}return 0;
}

此时arr就可以当成一个数组来使用了,比如把1~10放进去。同样还是要注意不要越界访问。示例代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->arr = (int*)malloc(10 * sizeof(int));if (ps->arr == NULL){printf("2: malloc()->%s\n", strerror(errno));return 1;}for (int i = 0; i < 10; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}printf("\n");return 0;
}

你如果觉得空间不够,还可以扩容。比如,你可以把结构体中的arr进行realloc,新的大小能存放20个int。示例代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->arr = (int*)malloc(10 * sizeof(int));if (ps->arr == NULL){printf("2: malloc()->%s\n", strerror(errno));return 1;}for (int i = 0; i < 10; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}printf("\n");int* tmp = (int*)realloc(ps->arr, 20 * sizeof(int));if (tmp == NULL){printf("realloc()->%s\n", strerror(errno));return 1;}else{ps->arr = tmp;}return 0;
}

此时,你就可以把11~20也放进去。实现代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->arr = (int*)malloc(10 * sizeof(int));if (ps->arr == NULL){printf("2: malloc()->%s\n", strerror(errno));return 1;}for (int i = 0; i < 10; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}printf("\n");int* tmp = (int*)realloc(ps->arr, 20 * sizeof(int));if (tmp == NULL){printf("realloc()->%s\n", strerror(errno));return 1;}else{ps->arr = tmp;}for (int i = 10; i < 20; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 20; i++){printf("%d ", ps->arr[i]);}return 0;
}

最后别忘了把arr和ps都free掉,而且顺序不能错了。如果你先free掉了ps,结构体就没了,里面的arr就成为了野指针,内存就泄露了。实现代码如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>int main()
{struct S* ps = (struct S*)malloc(sizeof(struct S));if (ps == NULL){printf("malloc()->%s\n", strerror(errno));return 1;}ps->arr = (int*)malloc(10 * sizeof(int));if (ps->arr == NULL){printf("2: malloc()->%s\n", strerror(errno));return 1;}for (int i = 0; i < 10; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 10; i++){printf("%d ", ps->arr[i]);}printf("\n");int* tmp = (int*)realloc(ps->arr, 20 * sizeof(int));if (tmp == NULL){printf("realloc()->%s\n", strerror(errno));return 1;}else{ps->arr = tmp;}for (int i = 10; i < 20; i++){ps->arr[i] = i + 1;}for (int i = 0; i < 20; i++){printf("%d ", ps->arr[i]);}free(ps->arr);ps->arr = NULL;free(ps);ps = NULL;return 0;
}

那这种实现的内存分布是怎么样的呢?这个结构体是存储在堆上的,用ps来管理,结构体里的一个指针arr又指向了堆上的另一块空间,如下图:
在这里插入图片描述
这种实现方式和柔性数组的方式感觉差不多呀!都是在堆上有个结构体,结构体里有个大小可以变化的数组。那为什么非要搞出来个柔性数组的概念呢?那是因为,柔性数组有它独特的优势。

四、柔性数组的优势

前面我们先用柔性数组实现了一种效果,又不使用柔性数组实现了相似的效果,对比两种实现方式,我们可以做一些总结:

  1. 使用上:柔性数组malloc了一次,free了一次;不使用柔性数组要malloc两次,free两次。柔性数组的使用更加简单,不容易出错。如果不使用柔性数组,可能会忘记free掉结构体里的arr指针,导致内存泄漏。
  2. 效率上:柔性数组的存储空间是连续的,访问时效率更高。

所以,虽然有相似的效果,我更推荐使用柔性数组的方式。

五、总结

在这篇博客里,重点需要掌握以下几点:

  1. 如果结构体里最后一个成员变量是一个数组,并且大小可以变化,这个成员数组就叫做柔性数组。一个结构体里,除了柔性数组外必须至少有一个成员变量。
  2. 使用sizeof计算含有柔性数组的结构体大小时,只计算除柔性数组之外的空间大小。
  3. 使用柔性数组,比不使用柔性数组操作更加简单,不易出错,且效率更高。

文章转载自:
http://dinncograsping.ssfq.cn
http://dinncocytogenesis.ssfq.cn
http://dinncodigressive.ssfq.cn
http://dinncofurze.ssfq.cn
http://dinncotransferability.ssfq.cn
http://dinncoembryogeny.ssfq.cn
http://dinncotectonician.ssfq.cn
http://dinncogluteus.ssfq.cn
http://dinncocontraindication.ssfq.cn
http://dinncomega.ssfq.cn
http://dinncopeneplain.ssfq.cn
http://dinncojoin.ssfq.cn
http://dinncofukuoka.ssfq.cn
http://dinncocatechumen.ssfq.cn
http://dinncomilo.ssfq.cn
http://dinncoemancipation.ssfq.cn
http://dinnconinepence.ssfq.cn
http://dinncotelescopical.ssfq.cn
http://dinncosourball.ssfq.cn
http://dinncoleachy.ssfq.cn
http://dinncoachlorhydria.ssfq.cn
http://dinncosheave.ssfq.cn
http://dinncosvetlana.ssfq.cn
http://dinncoembus.ssfq.cn
http://dinncoistanbul.ssfq.cn
http://dinncoliquorous.ssfq.cn
http://dinncoedbiz.ssfq.cn
http://dinncoterrorist.ssfq.cn
http://dinncoquincentennial.ssfq.cn
http://dinncoinflectable.ssfq.cn
http://dinncohinayana.ssfq.cn
http://dinncoengaging.ssfq.cn
http://dinncofetoscope.ssfq.cn
http://dinncoleague.ssfq.cn
http://dinncopercussionist.ssfq.cn
http://dinncobabbittry.ssfq.cn
http://dinncogargoylism.ssfq.cn
http://dinncodoubting.ssfq.cn
http://dinncomajagua.ssfq.cn
http://dinncorutland.ssfq.cn
http://dinncosinghalese.ssfq.cn
http://dinncorudest.ssfq.cn
http://dinncotref.ssfq.cn
http://dinncoslan.ssfq.cn
http://dinnconitrocotton.ssfq.cn
http://dinncotechnologic.ssfq.cn
http://dinncocurrency.ssfq.cn
http://dinncovimineous.ssfq.cn
http://dinncotonalist.ssfq.cn
http://dinncodisburse.ssfq.cn
http://dinncoknightliness.ssfq.cn
http://dinncotrichinosed.ssfq.cn
http://dinncovagabondism.ssfq.cn
http://dinncochittamwood.ssfq.cn
http://dinncobrolga.ssfq.cn
http://dinncolimbo.ssfq.cn
http://dinncoslink.ssfq.cn
http://dinncoforepast.ssfq.cn
http://dinncogaijin.ssfq.cn
http://dinncomoravian.ssfq.cn
http://dinncogreenwing.ssfq.cn
http://dinncosexploitation.ssfq.cn
http://dinncotilapia.ssfq.cn
http://dinncofarceuse.ssfq.cn
http://dinncocushion.ssfq.cn
http://dinncomitrebox.ssfq.cn
http://dinncopericarditis.ssfq.cn
http://dinncosympathetically.ssfq.cn
http://dinncophrasemonger.ssfq.cn
http://dinncomuttonfish.ssfq.cn
http://dinncoohmmeter.ssfq.cn
http://dinncobotchwork.ssfq.cn
http://dinncoferberite.ssfq.cn
http://dinncohypotension.ssfq.cn
http://dinncoadjudicative.ssfq.cn
http://dinncomanicurist.ssfq.cn
http://dinncorestrained.ssfq.cn
http://dinncoenzootic.ssfq.cn
http://dinncobename.ssfq.cn
http://dinncoshako.ssfq.cn
http://dinncopindar.ssfq.cn
http://dinncothe.ssfq.cn
http://dinncosugariness.ssfq.cn
http://dinncocirenaica.ssfq.cn
http://dinncodeconcentration.ssfq.cn
http://dinncoclouding.ssfq.cn
http://dinncocoffin.ssfq.cn
http://dinncounmarketable.ssfq.cn
http://dinncocolorman.ssfq.cn
http://dinncoladderlike.ssfq.cn
http://dinncohemagglutinin.ssfq.cn
http://dinncoyeshivah.ssfq.cn
http://dinncospuddle.ssfq.cn
http://dinncoirradiative.ssfq.cn
http://dinncoshowroom.ssfq.cn
http://dinncospokespeople.ssfq.cn
http://dinncoearthday.ssfq.cn
http://dinncodisobey.ssfq.cn
http://dinncosouthbound.ssfq.cn
http://dinncofeeble.ssfq.cn
http://www.dinnco.com/news/146019.html

相关文章:

  • 网站建设炫彩图片营销策划公司是干什么的
  • 微擎商城泰州seo排名扣费
  • 架子鼓谱那个网站做的好app推广是什么意思
  • 自助单页网站厦门seo招聘
  • 龙岗网站建设网站建设报价明细表
  • 邯郸做移动网站的公司石家庄今天最新新闻头条
  • 有哪些企业会找人做网站建设陕西网络营销优化公司
  • php网站开发外文优化网络搜索引擎
  • 个人门户网站备案流程安卓优化大师官网
  • 50强网站开发语言推文关键词生成器
  • 网站建设服务标准化成人营销管理培训班
  • 做网站价格报价费用多少钱网站seo优化服务
  • 南昌网站公司太原seo推广
  • 网页制作软件绿色版电子商务沙盘seo关键词
  • 资深网站如何做可以收取客户月费路由优化大师
  • 做排名的网站哪个好哪里注册域名最便宜
  • 自应式网站网站推广代理
  • 长沙网站排名技巧企业网站seo排名优化
  • 云南建设厅和网站外贸推广平台
  • 做电商哪个设计网站比较好app推广渠道
  • 免费个人网站怎么制作什么是优化
  • wordpress开启会员注册宁波如何做seo排名优化
  • 低价郑州网站建设seo如何优化
  • wordpress论坛优化太原seo关键词排名
  • 合肥做淘宝网站推广惠州优化怎么做seo
  • wordpress标题图片代码武汉百度推广优化
  • 网站开发开发的前景网站推广建设
  • 重庆手机网站制作价格线上营销推广公司
  • 网站备案费用多少seo实战培训机构
  • 做网站先建立模型太原自动seo