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语言数组初始化的问题
随机推荐
- hdoj2602 Bone Collector(DP,01背包)
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2602 题意 有n块骨头,每块骨头体积为volume,价值为value,还有一个容量为v的背包,现在将骨 ...
- OneDrive 开机启动设置失效如何处理?
问题现象: 『设置里勾选了开机启动onedrive,但是重启电脑勾选就没了,重新勾选没用,一重启就没了』 win10的onedrive无法开机启动 - Microsoft Community 处理方式 ...
- GPS数据包格式及数据包解析
GPS数据包解析 GPS数据包解析 目的 GPS数据类型及格式 数据格式 数据解释 解析代码 结构体定义 GPRMC解析函数 GPGGA解析函数 测试样例输出 gps数据包格式 gps数据解析 车联网 ...
- poj-1251-最小生成树
title: poj-1251-最小生成树 date: 2018-11-20 16:38:14 tags: acm 刷题 categories: ACM-最小生成树 概述 前段时间数据结构的课上提到了 ...
- 优客365 v2.9版本 后台存在SQL注入
安装 打开后台登陆界面 http://localhost:9096/yk365/system/login.php 输入单引号报错 得到表名 经过跟踪后在\module\login.php文件出现错误 ...
- C++11中的raw string literals
作为一名C++书看得少得可怜的新手,我一直没有勇气去系统地学习一下C++ 11添加的新特性.不过,平日里逛论坛,阅读大犇们的博客,倒是了解了一些.比如,这个帖子: 如何绕过g++ 4.8.1那个不能在 ...
- [BalticOI2002]Bicriterial routing
OJ题号: BZOJ1375.ECNU1468 题目大意: 给定一个无向连通图,每条边有两个权值w1和w2.定义一条路径是优秀的当且仅当没有别的路径满足两个权值的和都比该路径小,求s到t的优秀路径条数 ...
- python开发_tkinter_复选菜单
在之前的blog中有提到python的tkinter中的菜单操作 python开发_tkinter_窗口控件_自己制作的Python IDEL_博主推荐 python开发_tkinter_窗口控件_自 ...
- 读书笔记_Effective_C++_条款四十:明智而审慎地使用多重继承
多重继承是一种比较复杂的继承关系,它意味着如果用户想要使用这个类,那么就要对它的父类也了如指掌,所以在项目中会带来可读性的问题,一般我们都会尽量选择用单继承去替代它. 使用多重继承过程容易碰到的问题就 ...
- SMACH专题(二)----Concurrent状态机
Concurrent状态机是一种同时执行多个状态的状态机.如下图所示.状态FOO和BAR同时执行,当两个状态输出的结果同时满足一个组合条件时(FOO输出outcome2,BAR输出outcome1)才 ...