|
在敲代码的时候,我们会给变量一个初始值,以防止因为编译器的原因造成变量初始值的不确定性。对于数值类型的变量往往初始化为0,但对于其他类型的变量,如字符型、指针型等变量等该如何初始化呢?; Y/ R! ^ g7 f6 Y2 x. t: O5 A- L " Y3 h2 c+ w8 x4 [. o# F! c$ h( G$ j 数值类变量初始化 - l5 d- v9 T i0 p3 I 整型、浮点型的变量可以在定义的同时进行初始化,一般都初始化为0。 1int inum = 0;7 I1 C- y7 s2 ]- l- s9 t 2float fnum = 0.00f; 3double dnum = 0.00; 8 f: c' ^$ ]$ d/ ^; w f& w 7 U3 e8 w5 K1 E$ E 字符型变量初始化5 { b; h2 n0 Z" _2 K$ X" W 字符型变量也可在定义的同时进行初始化,一般初始化为'\0'。 1char ch = '\0'; ( V7 R* g: m- v. I1 y % Q8 L F) f S: g+ p# f8 Y+ @9 P 字符串初始化 字符串初始化的方法比较多,我这里简单介绍三种,因为字符串本质上是由一个个字符组成的字符数组,所以其初始化的最终目的,就是将字符数组里面的一个个字符都初始化为'\0'。 方法一:使用空的字符串""。char str[10] = ""; 方法二:使用memset。char str[10]; memset(str, 0, sizeof(str)); 方法三:写一个循环。char str[10]; ^" b g3 t* W4 [0 n7 {9 @ S' y for(int i = 0; i < 10; i++)2 n0 D; ~+ M7 e { str = '\0'; } 这里比较推荐的是第二种初始化方法。也即使用memset进行初始化。 很多人对memset这个函数一知半解,只知道它可以初始化很多数据类型的变量,却不知道其原理是什么样的,这里做一下简要的说明:memset是按照字节进行填充的。: E6 }% y, p7 Y# N: p0 V, Dint num;: T% ~' \, e' C- B memset(&num, 0, sizeof(int));! W! g3 h# S) R G2 W3 y printf("step1=%d\n", num); memset(&num, 1, sizeof(int)); printf("step2=%d\n", num);) T) `6 X D8 U; m 在讨论之前,我们先看一下运行结果chenyc@DESKTOP-IU8FEL6:~/src$ gcc -o memset memset.c -g chenyc@DESKTOP-IU8FEL6:~/src$ ./memset step1 = 0; F: l1 D1 v9 p @% R step2 = 16843009 chenyc@DESKTOP-IU8FEL6:~/src$ 看到这个运行结果,是不是和你想象中的不一样呢?00000000 00000000 00000000 00000000 按照按字节填充的原则,step1 的结果就是将4个字节全部填充0,所以得到的结果仍然是0:00000000 00000000 00000000 000000000 [) ` p8 q: p 而 step2 则是将每个字节都填充为1 (注意是每个字节,而不是每个byte位) ,所以相对应的结果就应该是:00000001 00000001 00000001 00000001 大家可以自己将上面那个二进制数转换成十进制看看,看看是不是16843009。字符串初始化有一个小窍门,我们知道字符串本质上是字符数组,因此它具有两个特性,
memset(year, 0, sizeof(year)); strcpy(year,"2018"); 指针初始化 一般来说,指针都是初始化为NULL。# F' a/ E3 m) @. J4 k3 f int *pnum = NULL;* _$ N' I4 m0 Q, \ int num = 0; pnum = #3 s1 u( U- c4 b& H% Q4 I0 d1 k' u 指针是个让人又爱又恨的东西,一般的整形、字符串等,初始化之后就可以直接拿来用了,可指针如果初始化为NULL后,没有给该指针重新分配内存,则会出现难以预料的错误(最最常见的就是操作空指针引起的段错误)。在动态内存管理中,由于变量的内存是分配在堆中的,所以一般用malloc、calloc等函数申请过动态内存,在使用完后需要及时释放,一般释放掉动态内存后要及时将指针置空,这也是很多人容易忽略的。 char *p = NULL; , X# o/ V7 c% W; T6 k p=(char *)malloc(100); if(NULL == p) { $ e3 z3 R, E& i3 A/ G7 r1 i7 K! p/ Q printf("Memory Allocated at: %x\n",p); 7 z r5 Z9 e) v5 D% o }- k0 C: S5 S+ [) { c else { printf("Not Enough Memory!\n"); } free(p); p = NULL; //这一行给指针置空必不可少,否则很可能后面操作了这个野指针而不自知,从而导致出现严重的问题 很多人经常会犯的一个错误,我们知道,在指针作为实参进行参数传递时,该指针就已经退化成了数组,所以很多人就想到用memset来对该指针进行初始化:0 B6 d5 d/ v( V, ^' { void fun(char *pstr), d+ q4 Z# A- c) f% _ { memset(pstr, 0, sizeof(pstr)); ...3 x0 C$ Z, p9 f4 Z. u& K }2 W1 }/ C& @1 n! f) x 这种写法是不正确的。我们姑且不管指针能不能用memset来进行初始化,指针首先保存的是一个4字节的地址,所以sizeof(pstr)永远只能 = 4,这样的初始化就毫无意义。 1 p; B3 C5 u9 X1 i/ c2 r+ L" G6 J 结构体初始化 结构体的初始化就比较简单了,基本也都是采用memset的方式。# s3 d/ {$ M2 a ]; D& A) j typedef struct student { int id; char name[20]; char sex;( S7 S4 i- K& m# x `% N' y }STU; STU stu1; memset((char *)&stu1, 0, sizeof(stu1)); 关于初始化结构体的长度问题,也即memset的第三个参数,一般来说,传入数据类型和变量名效果是一样的,上例中,下面写法是等价的效果:7 a+ n9 {$ Q) x0 ~, c memset((char *)&stu1, 0, sizeof(STU)); 但是对于结构体数组的初始化,长度就需要注意一下了,还是以上例来做说明: STU stus[10]; memset((char *)&stus, 0, sizeof(stus)); //正确,数组本身在内存里就是连续的,sizeof取出的就是数组的字节长度 memset((char *)&stus, 0, sizeof(STU)); //错误,只会初始化第一个STU结构体,后面还有9个STU元素并未初始化/ Z* f8 R2 c- x4 d" g4 L9 }4 c memset((char *)&stus, 0, sizeof(STU)*10); //正确,效果与第一个是一样的6 s# ]4 x* n4 T* j% ^; f0 O 有些人习惯将memset的第二个参数写成以下形式:memset((char *)&stu1, 0x00, sizeof(stu1));5 ~4 G r T1 N# | 只要理解了memset是按字节进行填充的,就知道这样写也是正确的,完全没有问题。 * n2 @( r3 x. f* c3 E0 U5 H |
微信公众号
手机版