c语⾔memset字符串赋值,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[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经过了严格优化,所以性能更⾼);
c语言如何创建字符串数组2、{0} 可能有移植性问题,虽然绝⼤多数编译器看到{0} 都是将数组全部初始化为0, 但是不保证所有编译器都是这样实现的;
3、综合1、2, 推荐使⽤memset⽅法。
附录:对于{0}初始化的测试
这是很基础的东西,但基础的重要性不⾔⽽喻,我敢肯定这个知识点我肯定曾经了解过,但现在,我不敢确定,由此可见纪录的重要性,这世界没有什么捷径,对⽅向,然后不停重复.所以从今天开始,我会⽐较详细的纪录这些⽐较⼩的知识点,其实还是有不少有意思的地⽅的.
写这篇⽂章的起因在于<>第七章新东西太多,看的我⽬不暇接,所以在⽹上了些例⼦看,其中就有⼀个例⼦中出现了这样的语句:
...
wchar_t wname[128]={0};
char cname[256]={0};
...
我感兴趣的是:
1.这种赋值的结果.
2.这种形式是否符合标准编码规则?
我到了如下资料,可能有助于对这个知识点的掌握.
/*
初始化值的个数可少于数组元素个数.当初始化值的个数少于数组元素个数时,前⾯的按序初始化相应值, 后⾯的初始化为0(全局或静态数组)
或为不确定值(局部数组).
*/
我相信上⾯的资料是C和C++语⾔的标准规范,但实际编译器处理时,可能会和规范有所不同.因为编译器原则上要遵从语⾔规范,但对于局部数组的不确定值到底是多少,怎么处理,编译器就可以灵活处理.我测试了三种编译器,其实编译器赋予的值是固定的,都是0.
/*
⼀直以为 int a[256]={0};是把a的所有元素初始化为0,int a[256]={1};是把a所有的元素初始化为1.
调试的时查看内存发现不是那么⼀回事,翻了⼀下《The C++ Programming Language》总算有定论。PDF的竟然不然复制,就把它这
章翻译了,如下
5.2.1 数组初始化
数组可以⽤⼀个列值来初始化,例如
int v1[] ={1,2,3,4};
char v2[]={'a','b','c',0};
当数组定义时没有指定⼤⼩,当初始化采⽤列表初始化了,那么数组的⼤⼩由初始化时列表元素个数决定。所以v1和v2分别为 int[4] 和char[4]类型。如果明确指定了数组⼤⼩,当在初始化时指定的元素个数超过这个⼤⼩就会产⽣错误。例如:
char v3[2] ={'a','b',0}; //错误:太多的初始化值了
char v3[3] ={'a','b',0}; //正确
如果初始化时指定的的元素个数⽐数组⼤⼩少,剩下的元素都回被初始化为 0。例如
int v5[8]={1,2,3,4};
等价于
int v5[8]={1,2,3,4,0,0,0,0};
注意没有如下形式的数组赋值:
void f()
{
v4={'c','d',0}; //错误:不是数组赋值
}
如果你想这样的复制的话,请使⽤ vector(16章第三节) 或者 valarray(22章第四节)。
字符数组可以⽅便地采⽤字符串直接初始化(参考第五章 2.2⼩节)
译注: 就是 这样啦 char alpha []="abcdefghijklmn";
*/
下⾯来看⼀个例⼦:
#include
int array1[5]={1,2,3};
static int array2[5]={1};
void main()
{
int arr1[5]={2};
static int arr2[5]={1,2};
int n;
cout <
for(n=0; n<5; n++)
cout <
cout <
for(n=0; n<5; n++)
cout <
cout <
for(n=0; n<5; n++)
cout <
cout <
for(n=0; n<5; n++)
cout <
cout <
}
在这个例⼦中,全局和静态数组都按语⾔规范要求被初始化为0,但是局部数组并没有向前⾯所说的为不确定值,下⾯是⽤
gcc,VC6.0,tuborC++分别编译的结果(注意gcc⽤g++编译c++⽂件,gcc不会链接库的):
/*
GCC 可同时⽤来编译 C 程序和 C++ 程序。⼀般来说,C 编译器通过源⽂件的后缀名来判断是 C 程序还是 C++ 程序。
在 Linux 中,C 源⽂件的后缀名为 .c,⽽ C++ 源⽂件的后缀名为 .C 或 .cpp。
但是,gcc 命令只能编译 C++ 源⽂件,⽽不能⾃动和 C++ 程序使⽤的库连接。因此,通常使⽤ g++ 命令来完成 C++ 程序的编译和
连接,该程序会⾃动调⽤ gcc 实现编译。
*/
GCC:
VC6.0:
TurboC++
这说明了对局部数组没有初始化的元素的值,这⼏种编译器都将其设置为0.但是,如果如果不对数组进⾏初始化,即在定义的同时没有⽤列表初始化,那么局部数组的值就取决于编译器⽽对程序员来说就是不可预料的了.有时间可以测试⼀下各个编译器,不过在vc中是0xcc.所以对局部数组的初始化要特别⼩⼼.但是全局的数组和静态数组还是会被正确的赋于0值的.
c语⾔数组初始化问题
2147483648字符数组的初始化,最容易理解的⽅式就是逐个字符赋给数组中各元素. charstr[10]={'I','','a','m','',‘h’,'a','p','p','y'}; 即把10 ...
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数组去重的三种常⽤⽅法,及其性能⽐较
在进⾏数组操作时往往会遇到去掉重复项的问题,下⾯简单介绍下数组去重的⽅法,以及其执⾏效率 ⽅法⼀ 采⽤两次循环 原理:拿当前的和他后⾯的⽐,如果后⾯的有重复的就⼲掉 ...
09-C语⾔数组
⽬录: ⼀.使⽤xcode编辑⼯具 ⼆.数组 三.数组遍历 四.多维数组 回到顶部 ⼀.使⽤xcode编辑⼯具 1 打开xcode程序 2 创建⼀个项⽬ OSX -> Application - ...
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论