嵌入式C语言变量、数组、指针初始化的多种操作

简介: 嵌入式C语言变量、数组、指针初始化的多种操作

在敲代码的时候,我们会给变量一个初始值,以防止因为编译器的原因造成变量初始值的不确定性。

对于数值类型的变量往往初始化为0,但对于其他类型的变量,如字符型、指针型等变量等该如何初始化呢?

数值类变量初始化

整型、浮点型的变量可以在定义的同时进行初始化,一般都初始化为0

1int    inum  = 0;
2float  fnum = 0.00f;
3double dnum = 0.00;

字符型变量初始化

字符型变量也可在定义的同时进行初始化,一般初始化为'\0'

1char ch = '\0';

字符串初始化

字符串初始化的方法比较多,我这里简单介绍三种,因为字符串本质上是由一个个字符组成的字符数组,所以其初始化的最终目的,就是将字符数组里面的一个个字符都初始化为'\0'

方法一:使用空的字符串""

char str[10] = "";

方法二:使用memset

char str[10];

memset(str, 0, sizeof(str));

方法三:写一个循环。

char str[10];

for(int i = 0; i < 10; i++)

{

str[i] = '\0';

}

这里比较推荐的是第二种初始化方法。也即使用memset进行初始化。

很多人对memset这个函数一知半解,只知道它可以初始化很多数据类型的变量,却不知道其原理是什么样的,这里做一下简要的说明:memset是按照字节进行填充的。

先看下面的一段代码:

int num;

memset(&num, 0, sizeof(int));

printf("step1=%d\n", num);

memset(&num, 1, sizeof(int));

printf("step2=%d\n", num);

在讨论之前,我们先看一下运行结果

chenyc@DESKTOP-IU8FEL6:~/src$ gcc -o memset memset.c -g

chenyc@DESKTOP-IU8FEL6:~/src$ ./memset

step1 = 0

step2 = 16843009

chenyc@DESKTOP-IU8FEL6:~/src$

看到这个运行结果,是不是和你想象中的不一样呢?

step1 = 0 相信大家都好理解,可 step2 = 16843009 很多人就不能理解了。按照一般的惯性思维,不是应该 = 1 才对么?

这就是我要说的,memset是按照字节进行填充的。

我们知道,int 型是4个字节(每个字节有8位),按二进制表示出来就应该是:

00000000 00000000 00000000 00000000

按照按字节填充的原则,step1 的结果就是将4个字节全部填充0,所以得到的结果仍然是0:

00000000 00000000 00000000 00000000

而 step2 则是将每个字节都填充为1 (注意是每个字节,而不是每个byte位) ,所以相对应的结果就应该是:

00000001 00000001 00000001 00000001

大家可以自己将上面那个二进制数转换成十进制看看,看看是不是16843009

所以严格来说,memset函数本身并不具有初始化的功能,而是一个单纯的按字节填充函数,只是人们在使用的过程中,扩展出了初始化的作用。

字符串初始化有一个小窍门,我们知道字符串本质上是字符数组,因此它具有两个特性,

  • 字符串在内存里是连续的,
  • 字符串遇'\0'结束。
    所以我们在初始化的时候,总是愿意给字符串本身长度加1的长度的内存进行初始化。

char year[4+1];

memset(year, 0, sizeof(year));

strcpy(year,"2018");

指针初始化

一般来说,指针都是初始化为NULL

int *pnum = NULL;

int num = 0;

pnum = &num;

指针是个让人又爱又恨的东西,一般的整形、字符串等,初始化之后就可以直接拿来用了,可指针如果初始化为NULL后,没有给该指针重新分配内存,则会出现难以预料的错误(最最常见的就是操作空指针引起的段错误)。

在动态内存管理中,由于变量的内存是分配在堆中的,所以一般用malloccalloc等函数申请过动态内存,在使用完后需要及时释放,一般释放掉动态内存后要及时将指针置空,这也是很多人容易忽略的。

char *p = NULL;

p=(char *)malloc(100);

if(NULL == p)

{

printf("Memory Allocated at: %x\n",p);

}

else

{

printf("Not Enough Memory!\n");

}

free(p);

p = NULL; //这一行给指针置空必不可少,否则很可能后面操作了这个野指针而不自知,从而导致出现严重的问题

很多人经常会犯的一个错误,我们知道,在指针作为实参进行参数传递时,该指针就已经退化成了数组,所以很多人就想到用memset来对该指针进行初始化:

void fun(char *pstr)

{

memset(pstr, 0, sizeof(pstr));

...

}

这种写法是不正确的。我们姑且不管指针能不能用memset来进行初始化,指针首先保存的是一个4字节的地址,所以sizeof(pstr)永远只能 = 4,这样的初始化就毫无意义。

结构体初始化

结构体的初始化就比较简单了,基本也都是采用memset的方式。

typedef struct student

{

int id;

char name[20];

char sex;

}STU;

STU stu1;

memset((char *)&stu1, 0, sizeof(stu1));

关于初始化结构体的长度问题,也即memset的第三个参数,一般来说,传入数据类型和变量名效果是一样的,上例中,下面写法是等价的效果:

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元素并未初始化

memset((char *)&stus, 0, sizeof(STU)*10); //正确,效果与第一个是一样的

有些人习惯将memset的第二个参数写成以下形式:

memset((char *)&stu1, 0x00, sizeof(stu1));

只要理解了memset是按字节进行填充的,就知道这样写也是正确的,完全没有问题。

目录
相关文章
|
24天前
|
存储 NoSQL 编译器
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
指针是一个变量,它存储另一个变量的内存地址。换句话说,指针“指向”存储在内存中的某个数据。
77 3
【C语言】指针的神秘探险:从入门到精通的奇幻之旅 !
|
15天前
|
存储 编译器 C语言
【C语言】C语言的变量和声明系统性讲解
在C语言中,声明和定义是两个关键概念,分别用于告知编译器变量或函数的存在(声明)和实际创建及分配内存(定义)。声明可以多次出现,而定义只能有一次。声明通常位于头文件中,定义则在源文件中。通过合理组织头文件和源文件,可以提高代码的模块化和可维护性。示例包括全局变量、局部变量、函数、结构体、联合体、数组、字符串、枚举和指针的声明与定义。
44 12
|
24天前
|
存储 编译器 C语言
【C语言】指针大小知多少 ?一场探寻C语言深处的冒险 !
在C语言中,指针的大小(即指针变量占用的内存大小)是由计算机的体系结构(例如32位还是64位)和编译器决定的。
48 9
|
24天前
|
安全 程序员 C语言
【C语言】指针的爱恨纠葛:常量指针vs指向常量的指针
在C语言中,“常量指针”和“指向常量的指针”是两个重要的指针概念。它们在控制指针的行为和数据的可修改性方面发挥着关键作用。理解这两个概念有助于编写更安全、有效的代码。本文将深入探讨这两个概念,包括定义、语法、实际应用、复杂示例、最佳实践以及常见问题。
42 7
|
24天前
|
传感器 算法 安全
【C语言】两个数组比较详解
比较两个数组在C语言中有多种实现方法,选择合适的方法取决于具体的应用场景和性能要求。从逐元素比较到使用`memcmp`函数,再到指针优化,每种方法都有其优点和适用范围。在嵌入式系统中,考虑性能和资源限制尤为重要。通过合理选择和优化,可以有效提高程序的运行效率和可靠性。
75 6
|
24天前
|
C语言
【C语言】全局搜索变量却找不到定义?原来是因为宏!
使用条件编译和 `extern` 来管理全局变量的定义和声明是一种有效的技术,但应谨慎使用。在可能的情况下,应该优先考虑使用局部变量、函数参数和返回值、静态变量或者更高级的封装技术(如结构体和类)来减少全局变量的使用。
31 5
|
27天前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
1月前
|
存储 C语言
C语言如何使用结构体和指针来操作动态分配的内存
在C语言中,通过定义结构体并使用指向该结构体的指针,可以对动态分配的内存进行操作。首先利用 `malloc` 或 `calloc` 分配内存,然后通过指针访问和修改结构体成员,最后用 `free` 释放内存,实现资源的有效管理。
121 13
|
2月前
|
C语言
无头链表二级指针方式实现(C语言描述)
本文介绍了如何在C语言中使用二级指针实现无头链表,并提供了创建节点、插入、删除、查找、销毁链表等操作的函数实现,以及一个示例程序来演示这些操作。
38 0
|
3月前
|
存储 人工智能 C语言
C语言程序设计核心详解 第八章 指针超详细讲解_指针变量_二维数组指针_指向字符串指针
本文详细讲解了C语言中的指针,包括指针变量的定义与引用、指向数组及字符串的指针变量等。首先介绍了指针变量的基本概念和定义格式,随后通过多个示例展示了如何使用指针变量来操作普通变量、数组和字符串。文章还深入探讨了指向函数的指针变量以及指针数组的概念,并解释了空指针的意义和使用场景。通过丰富的代码示例和图形化展示,帮助读者更好地理解和掌握C语言中的指针知识。
143 4