c++中局部变量初始化的问题
在C语言里,全局变量如果不初始化的话,默认为0,也就是说在全局空间里:
int x =0; 跟 int x; 的效果看起来是一样的。但其实这里面的差别很大,强烈建议大家所有的全局变量
都要初始化,他们的主要差别如下:
编译器在编译的时候针对这两种情况会产生两种符号放在目标文件的符号表中,对于初始化的,叫强
符号,未初始化的,叫弱符号。连接器在连接目标文件的时候,如果遇到两个重名符号,会有以下处理规
则:
1、如果有多个重名的强符号,则报错。
2、如果有一个强符号,多个弱符号,则以强符号为准。
3、如果没有强符号,但有多个重名的弱符号,则任选一个弱符号。
大部分情况下,我们不希望连接器为我们做决定,所以我不是很认同后两个规则,至少应该给个警告,
而不应该安静地通过。因为这种问题引起的bug会很难查,所以我们要尽量把全局变量初始化,对于不想给
别的文件引用的变量,也尽量用static修饰。
除了连接时的表现不一样外,未初始化的符号在目标文件的bss段中,而初始化的符号在data段中。
注: bss段(未手动初始化的数据)并不给该段的数据分配空间,只是记录数据所需空间的大小。
data段(已手动初始化的数据)则为数据分配空间,数据保存在目标文件中。
对于局部变量,不被初始化的话,其值一般分为两种情况Debug版和Release版的区别。
例:
#include "stdafx.h"
int i;
int main(int argc, char* argv[])
{
printf(" i = %d\n",i);
int j;
printf(" j= %d\n",j);
return 0;
}
在Debug版下,在这段代码中i的值打印出来是0,而j的值打印出来是-858993460,也就是0xCCCCCCCC.
至于为什么是这个值,有网友给出这个解释。(设计成0xcccccccc是有特殊用意的……这个好像叫做
Poison,未初始化的Pointer去取值的话会出错。肯定有人问为什么不弄成0x00000000,因为空指针是指
针的有效状态,可能会误导人,而0xCCCCCCCC在Windows下永远不可能是一个指针的有效状态(不是NULL,
不指向一个对象,不指向一堆对象紧接之后的区域),这就是在模拟野指针……)
值得注意的是,同样的代码在Release版下,这段代码中未被初始化的变量最后打印出来的可能都是0。
也有强大的网友给出解释。(重点在于vc的一个功能:Catch release-build errors in debug build用
/GZ编译开关打开。debug版这个开关是开的,release版是关的(为了效率)。这个开关说白了就是把所有
动态局部变量初始化成0xcccccccc,把所有动态堆变量初始化成0xcdcdcdcd。很多新手会忘记初始化这些
本来应该初始化的变量(尤其是new出来的变量),有时他们会假定这些变量应该是0,这样就可能出现在
release版正常而debug版不正常的程序,因为release版至少局部变量的初始值很可能就是0,而有时他们
又会假定或者期望这些变量不是0,这样就带了一个最难发现的bug)
From:http://www.kingofcoders.com/viewNews.php?type=newsCpp&id=189&number=4836955386
-------------------------------------------------------------------------------------------------------------------------------------
不过个人去验证局部变量,没初始化,访问会直接编译不过。
相比类里的成员对象没初始化变量的值也分对象构建的方式而不同:
struct Npc
{
int m;
int data;
};
Npc* pNpc = new Npc; // new Npc()
printf("m default value = %d\n", pNpc->m);
Npc()会调用默认构造函数,会对成员变量初始化0,new Npc则不会,data的值会是不确定的。
c++中局部变量初始化的问题的更多相关文章
- [golang 易犯错误] golang 局部变量初始化:=的陷阱
我们知道,golang中局部变量初始化方法(使用“:=”创建并赋值),让我们在使用变量时很方便.但是,这也是易犯错误的地方之一.特别是这个初始化符还支持多个变量同时初始化,更特别的是它还支持原有变量赋 ...
- static静态局部变量初始化问题
第一次写博客之类的东西,主要是为了记录自己的学习过程,以便于记忆的加深和与各位大神进行探讨,学习更多的东西. 本次上传主要是关于静态局部变量的初始化问题. 首先,静态局部变量和全局变量一样,数据都存放 ...
- C++派生类中如何初始化基类对象(五段代码)
今天收到盛大的面试,问我一个问题,关于派生类中如何初始化基类对象,我在想派生类对于构造函数不都是先构造基类对象,然后在构造子类对象,但是如果我们在成员初始化列表先初始化派生类的私有成员,在函数内去调用 ...
- php中局部变量和全局变量
php中局部变量和全局变量 代码1:函数内部使用函数外部变量错误方法 <?php $name = 'fish'; function animal() { echo $name; } animal ...
- 对js中局部变量、全局变量和闭包的理解
对js中局部变量.全局变量和闭包的理解 局部变量 对于局部变量,js给出的定义是这样的:在 JavaScript函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它.(该变量的作用域 ...
- 对JavaScript中局部变量、全局变量和闭包的理解
对js中局部变量.全局变量和闭包的理解 局部变量 对于局部变量,js给出的定义是这样的:在 JavaScript函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它.(该变量的作用域 ...
- JavaScript中局部变量与全局变量的不同
JavaScript中局部变量与全局变量 我们知道,JavaScript的变量是松散型的变量,也就是说,其变量只需用var声明,其赋值的类型是不限定的.比如: var person=18; perso ...
- u-boot中nandflash初始化流程分析(转)
u-boot中nandflash初始化流程分析(转) 原文地址http://zhuairlunjj.blog.163.com/blog/static/80050945201092011249136/ ...
- 实现Square类,让其继承自Rectangle类,并在Square类增添新属性和方法,在2的基础上,在Square类中重写Rectangle类中的初始化和打印方法
实现Square类,让其继承自Rectangle类,并在Square类增添新属性和方法,在2的基础上,在Square类中重写Rectangle类中的初始化和打印方法 #import <Found ...
随机推荐
- Java并发程序设计(五)JDK并发包之线程复用:线程池
线程复用:线程池 一.为什么需要线程池 为了避免系统频繁地创建和销毁线程,使用线程池让线程进行复用.(即创建线程变成了从线程池中获取空闲线程,销毁线程变成了把线程放回线程池中.) 二.JDK对线程池的 ...
- 小B的询问
OJ题号:BZOJ3781.洛谷2709 思路: 根据平方和公式,$(a+b)^2=a^2+2ab+b^2$,即当$c_i$增加$1$时,新的答案增加$2C_i+1$,减少时亦同.莫队求解即可. #i ...
- [BOI2004]Sequence 数字序列
Description: Hint: \(n<=10^5\) Solution: 首先考虑b不严格递增时的做法 发现当\(a[i]\)递增时\(b[i]\)直接取\(a[i]\)即可,否则此时需 ...
- Linux学习笔记13—Vi编辑器的学习
文本编辑工具vim.vi1. vim与vi的最大区别是vim编辑的时候是带颜色显示的.Vi不带颜色显示.2. yum install -y vim-enhanced 如果没有安装VIM 使用上面的命令 ...
- Linux中日期的加减运算
Linux中日期的加减运算 目录 在显示方面 在设定时间方面 时间的加减 正文 date命令本身提供了日期的加减运算. date 可以用来显示或设定系统的日期与时间. 回到顶部 在显示方面 使用者可以 ...
- 数据结构C语言版--单链表的基本功能实现
/* * 构造一个链式存储的线性表(当输入9999时,结束构造过程),然后输出该线性表 * 并统计该线性链表的长度 . *注:new和delete是C++的运算符 malloc和free是C++/C的 ...
- 如何在windows2008/2012上安装启明星系统。
启明星系统提供多种安装方式.安装包里自带了setup.exe.每个程序的 install下有在线安装(例如请假应用程序为book,则默认为 http://localhost/book/install ...
- 【Spark】Sparkstreaming-性能调优
Sparkstreaming-性能调优 Spark Master at spark://node-01:7077 sparkstreaming 线程 数量_百度搜索 streaming中partiti ...
- MDX Cookbook 06 - GENERATE 循环遍历
有时候需要从集合中取出特定的成员但是又不能执行遍历操作,这个时候就可以使用 GENERATE 函数来解决这个问题. 根据地区查询每年的销售额 - SELECT NON EMPTY { , NON EM ...
- Oracle 12c利用数据泵DataPump进行Oracle数据库备份
1.查看数据库版本 SQL> select version from v$instance; VERSION ----------------- 12.1.0.2.0 2.sysdba用户登录s ...