C语言 数组初始化的三种常用方法({0}, memset, for循环赋值)以及原理
C语言中,数组初始化的方式主要有三种:
1、声明时,使用 {0} 初始化;
2、使用memset;
3、用for循环赋值。
那么,这三种方法的原理以及效率如何呢? 请看下面的测试代码:
- #define ARRAY_SIZE_MAX (1*1024*1024)
- void function1()
- {
- char array[ARRAY_SIZE_MAX] = {0}; //声明时使用{0}初始化为全0
- }
- void function2()
- {
- char array[ARRAY_SIZE_MAX];
- memset(array, 0, ARRAY_SIZE_MAX); //使用memset方法
- }
- void function3()
- {
- int i = 0;
- char array[ARRAY_SIZE_MAX];
- for (i = 0; i < ARRAY_SIZE_MAX; i++) //for循环赋值
- {
- array[i] = 0;
- }
- }
效率:
分别执行上面三种方法,统计下平均时间可以得出: for循环浪费的时间最多,{0} 与memset 耗时差不多。
原理:
1、for循环,就是循环赋值,不解释了
2、memset,很容易找到memset内部实现代码,这里也不解释了
3、{0} 内部是怎么实现的呢?
将上述代码编译成汇编格式如下:
function1如下:
- pushl %ebp
- movl %esp, %ebp
- subl $1048600, %esp
- leal -1048584(%ebp), %eax
- movl $1048576, %edx
- movl %edx, 8(%esp)
- movl $0, 4(%esp)
- movl %eax, (%esp)
- call memset
- leave
- ret
function2如下:
- pushl %ebp
- movl %esp, %ebp
- subl $1048600, %esp
- movl $1048576, 8(%esp)
- movl $0, 4(%esp)
- leal -1048584(%ebp), %eax
- movl %eax, (%esp)
- call memset
- leave
- ret
通过汇编代码可以看出,{0}初始化方式,调用了memset函数!
对三种方法的选取:
1、for 最浪费时间,不建议(其实memset内部也是用循环实现的,只不过memset经过了严格优化,所以性能更高);
2、{0} 可能有移植性问题,虽然绝大多数编译器看到{0} 都是将数组全部初始化为0, 但是不保证所有编译器都是这样实现的;
3、综合1、2, 推荐使用memset方法。
附录:对于{0}初始化的测试
这是很基础的东西,但基础的重要性不言而喻,我敢肯定这个知识点我肯定曾经了解过,但现在,我不敢确定,由此可见纪录的重要性,这世界没有什么捷径,找对方向,然后不停重复.所以从今天开始,我会比较详细的纪录这些比较小的知识点,其实还是有不少有意思的地方的.
写这篇文章的起因在于<<COM技术内幕>>第七章新东西太多,看的我目不暇接,所以在网上找了些例子看,其中就有一个例子中出现了这样的语句:




我感兴趣的是:
1.这种赋值的结果.
2.这种形式是否符合标准编码规则?
我找到了如下资料,可能有助于对这个知识点的掌握.



我相信上面的资料是C和C++语言的标准规范,但实际编译器处理时,可能会和规范有所不同.因为编译器原则上要遵从语言规范,但对于局部数组的不确定值到底是多少,怎么处理,编译器就可以灵活处理.我测试了三种编译器,其实编译器赋予的值是固定的,都是0.
在这篇blog中 http://hi.baidu.com/widebright/blog/item/a024bc09631402256b60fbd0.html 谈论了相同的话题,现对其摘录如下:



























下面来看一个例子:































在这个例子中,全局和静态数组都按语言规范要求被初始化为0,但是局部数组并没有向前面所说的为不确定值,下面是用gcc,VC6.0,tuborC++分别编译的结果(注意gcc用g++编译c++文件,gcc不会链接库的):




GCC:
VC6.0:
TurboC++
这说明了对局部数组没有初始化的元素的值,这几种编译器都将其设置为0.但是,如果如果不对数组进行初始化,即在定义的同时没有用列表初始化,那么局部数组的值就取决于编译器而对程序员来说就是不可预料的了.有时间可以测试一下各个编译器,不过在vc中是0xcc.所以对局部数组的初始化要特别小心.但是全局的数组和静态数组还是会被正确的赋于0值的.
最后要重申下对变量初始化的重要性, http://blog.vckbase.com/smileonce/archive/2005/06/18/6777.html 这里列举了没有初始化造成的事故.
此外,这个blog地址值得收藏,在http://blog.vckbase.com/ 排行榜的blog都值得仔细看.
C语言 数组初始化的三种常用方法({0}, memset, for循环赋值)以及原理的更多相关文章
- c语言数组初始化问题
2147483648字符数组的初始化,最容易理解的方式就是逐个字符赋给数组中各元素. charstr[10]={'I','','a','m','',‘h’,'a','p','p','y'}; 即把10 ...
- C语言数组初始化方式
//一维数组初始化//初始化方法1 int arr[5] = {3,7,2,1,9}; //定义了一个长度是5的数组,并给每个元素赋值 //初始化方法2 int arr[5] = {3,7}; //给 ...
- js数组去重的三种常用方法总结
第一种是比较常规的方法 思路: 1.构建一个新的数组存放结果 2.for循环中每次从原数组中取出一个元素,用这个元素循环与结果数组对比 3.若结果数组中没有该元素,则存到结果数组中 Array.p ...
- c语言数组初始化 蛋疼
一个一般性的结论 int a[100]={N}//N是一个大于等于0的整数 以上代码只会把a[0]初始化为N,其它内存单元都会被初始化为0 int a[100]={5} 这行代码它只会把a[0]初始化 ...
- C语言数组初始化
例如: int a[15] = {0}; 第一种,编译器会把第一个初始化值赋给数组的第一个元素,然后用0赋给其余的元素.如果没有给出初始值,编译器不会去做初始化工作.这样简洁的方式让代码更加高效. 还 ...
- C语言数组初始化全部为0
] = {}; 编译器会把第一个初始化值(这里是0)赋给数组的第一个元素,然后用默认值0赋给其余的元素.如果没有给出初始值,编译器不会去做初始化工作.这样简洁的方式让代码更加高效. 另一种,就是mem ...
- javascript数组去重的三种常用方法,及其性能比较
在进行数组操作时往往会遇到去掉重复项的问题,下面简单介绍下数组去重的方法,以及其执行效率 方法一 采用两次循环 原理:拿当前的和他后面的比,如果后面的有重复的就干掉 ...
- java中二维数组初始化的几种方法
/* 第一种方式 */ int tdarr1[][] = { { 1, 3, 5 }, { 5, 9, 10 } }; /* 第二种方式 */ int tdarr2[][] = new int[][] ...
- C语言数组初始化的问题
随机推荐
- Windows-caffe配置
我在博客园的第一篇博客开始了,好紧张,好激动,好淫荡...哈哈O(∩_∩)O哈! 下面开始进入正题.配置环境为windows7+cuda7.5+vs2013+matlab2014a 之前用的happy ...
- NCPC 2016 October 8,2016 Artwork
Problem A Artwork Problem ID: artwork Time limit: 4 seconds A template for an artwork is a white gri ...
- egrep 第几列开始
第6位开始 egrep -a '^.{5}(0|5)' ${CACSDATA}/outcds.ur5.ca2.txt | sort > ${CACSDATA}/outcds.a.ur5.txt
- map赋值前要先初始化:assignment to entry in nil map
注意这种map的嵌套的形式,make只初始化了map[string]T部分(T为map[int]int),所以下面的赋值会出现错误: test := make(map[string]map[int]i ...
- python orm字段解析
null # 是否可以为空 default # 默认值 primary_key # 主键 db_column # 列名 db_index # 索引(db_index=True) unique # 唯一 ...
- [luogu4459][BJOI2018]双人猜数游戏(DP)
https://zhaotiensn.blog.luogu.org/solution-p4459 从上面的题解中可以找到样例解释,并了解两个人的思维方式. A和B能从“不知道”到“知道”的唯一情况,就 ...
- [Agc002E]Candy Piles
[Agc002E]Candy Piles 题目大意 有\(n\)个数,两人轮流操作,可以做以下操作之一: 删掉一个最大的数 将所有数-1 最后取没的人输,问先手是否必胜? 试题分析 直接决策不知道选哪 ...
- JavaEE-学习目录
JavaEE ============================================ Web工作机制 JSP Struts基础 Struts核心文件 Struts数据校验与国际化 S ...
- Linux-JDK+Tomcat的安装笔记
Linux-JDK+Tomcat的安装 一.JDK的安装 1. 使用命令uname –a查看系统的版本确定系统的位数,然后去JDK官网下载相应位数的安装程序,进行安装. 2. 使用rz命令将下载的 ...
- 让机器教人学习更有效:Becoming the Expert - Interactive Multi-Class Machine Teaching
这是CVPR2015的一篇非常有趣的文章,论文研究了如何让机器自动地教导学生进行学习目标的分类.论文研发了一种机器学习方法,通过人机交互的过程中,不断的优化机器指导的方法和技巧,从而提高人学习目标分类 ...