C语言各种变量的初始化方式

 更新时间:2025年04月10日 10:36:59   作者:DeepClick  
这篇文章主要介绍了C语言各种变量的初始化方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教

数值类变量初始化

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

    int  inum  = 0;
    float fnum = 0.00f;
    double  dnum = 0.00;

字符型变量初始化

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

char 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是按字节进行填充的,就知道这样写也是正确的,完全没有问题。

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • C++ 解引用与函数基础详解之内存地址、调用方法及声明

    C++ 解引用与函数基础详解之内存地址、调用方法及声明

    函数是C++ 中重要的编程概念,它们可以提高代码的可重用性、可读性和可维护性,本文介绍C++ 解引用与函数基础详解之内存地址、调用方法及声明,感兴趣的朋友跟随小编一起看看吧
    2024-04-04
  • 数据结构之链式二叉树详解

    数据结构之链式二叉树详解

    所谓二叉树遍历 (Traversal) 是按照某种特定的规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次。本文通过代码示例详细介绍了C语言中的链式二叉树,需要的朋友可以参考一下
    2023-04-04
  • 基于C语言实现UDP服务器

    基于C语言实现UDP服务器

    这篇文章主要为大家详细介绍了如何使用C语言编写一个简单的UDP服务器程序,以及如何接收和处理客户端发送的数据,有需要的小伙伴可以了解下
    2024-10-10
  • vs2019永久配置opencv开发环境的方法步骤

    vs2019永久配置opencv开发环境的方法步骤

    这篇文章主要介绍了vs2019永久配置opencv开发环境的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-03-03
  • C++中类的三种访问权限解析:private、public与protect

    C++中类的三种访问权限解析:private、public与protect

    这篇文章主要介绍了C++中类的三种访问权限解析:private、public与protect,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-11-11
  • C/C++语言中的头文件汇总

    C/C++语言中的头文件汇总

    这篇文章主要汇总了C/C++语言中的头文件,方便各位朋友更好的工作和学习,有需要的朋友可以参考下
    2020-06-06
  • C/C++ 中 void*从概念到实战深度解析

    C/C++ 中 void*从概念到实战深度解析

    本文主要介绍了C/C++中的void*类型,从概念、特性、用途到实战规范进行了全面拆解,void*是一种通用指针,可以指向任意类型的数据,但需要显式转换以使用,本文给大家介绍的非常详细,感兴趣的朋友跟随小编一起看看吧
    2025-11-11
  • C++虚函数表的原理与使用解析

    C++虚函数表的原理与使用解析

    对C++ 了解的人都应该知道虚函数(Virtual Function)是通过一张虚函数表(Virtual Table)来实现的。简称为V-Table。本文就将详细讲讲虚函数表的原理与使用,需要的可以参考一下
    2022-04-04
  • C/C++ 中堆和栈及静态数据区详解

    C/C++ 中堆和栈及静态数据区详解

    这篇文章主要介绍了C/C++ 中堆和栈及静态数据区详解的相关资料,需要的朋友可以参考下
    2017-04-04
  • C++ 超详细讲解stack与queue的使用

    C++ 超详细讲解stack与queue的使用

    C++ Stack(堆栈) 是一个容器类的改编,为程序员提供了堆栈的全部功能,也就是说实现了一个先进后出(FILO)的数据结构,许多程序都使用了 queue 容器。queue 容器可以用来表示超市的结账队列或服务器上等待执行的数据库事务队列
    2022-03-03

最新评论