C与C++中const与宏的区别区别?

1418人阅读
笔记(36)
C/C++(5)
&&& 看书的时候碰到的一个问题,先列点书上的原话:
&“C中的const的意思是‘一个不能被改变的普通变量’,在C中,它总是占用内存,而且它的名字是全局符。C编译器不能把const看成一个编译期间的常量”
&&& 做了下面一个实验,就实验来验证分析:
#pragma once
const int a = 2;
#include &stdio.h&
#include &a.h&
int main(int argc, char* argv[])
printf(&%d&, a);
&&& 这种写法在C中是没有任何问题的,因为C中,const的名字是全局符,const a的写法,C编译器把它作为一个声明,这个声明指明在别的地方有内存分配。而如果是在C++中,上述写法却是错误的,提示信息如下:
error C2734: 'a' : const object must be initialized if not extern
&&& 查了下资料,有这样一句话:“C默认const是外部连接,C++则默认const是内部连接”,如果在C++中想完成与C同样的事情,必须用extern把内部连接改成外部连接。
&&& 如上所述,在C中,const变量的名字是全局符,因此,可以查找到,但C++中,由于默认其是内部连接,仅会在当前文件中查找变量名,因此,需要加一个extern,把查找范围扩大,才能找到,如下:
#include &stdio.h&
#include &a.h&
int main(int argc, char* argv[])
printf(&%d&, a);
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:130012次
积分:1824
积分:1824
排名:第15632名
原创:41篇
转载:48篇
评论:27条
文章:11篇
阅读:11538c++中,const是什么意思,const声明的是什么
常量申明,如:const double PI = 3.14;申明双精度浮点常数.const char *str = "hello world";或char const *str ="hello world";申明char型指针,指向字符串常量char a[10];char * const str str =申明一个char型常量指针,指向a的地址class T{public:double val() const{ return val_; } //对函数的修饰,表示类的数据成员值,在该函数中不能被改变private:double val_;}
为您推荐:
其他类似问题
扫描下载二维码C语言的const与C++的const区别[整理自网络]
1、C中CONST的使用。
const是一个C语言的关键字,它限定一个变量不允许被改变。
使用const在一定程度上可以提高程序的健壮性,另外,在观看别人代码的时候,清晰理解const所起的作用,对理解对方的程序也有一些帮助。 
虽然这听起来很简单,但实际上,const的使用也是c语言中一个比较微妙的地方,微妙在何处呢?
问题1:const变量 和 常量?
为什么我象下面的例子一样用一个const变量来初始化数组,ANSI C的编译器会报告一个错误呢?      const int
n = 5;int a[n];  
1)、这个问题讨论的是“常量”与“只读变量”的区别。常量肯定是只读的,例如5,
“abc”,等,肯定是只读的,因为程序中根本没有地方存放它的值,当然也就不能够去修改它。而“只读变量”则是在内存中开辟一个地方来存放它的值,只不
过这个值由编译器限定不允许被修改。C语言关键字const就是用来限定一个变量不允许被改变的修饰符(Qualifier)。上述代码中变量n被修饰为
只读变量,可惜再怎么修饰也不是常量。而ANSI C规定数组定义时维度必须是“常量”,“只读变量”也是不可以的。   
2)、注意:在ANSI C中,这种写法是错误的,因为数组的大小应该是个常量,而const int n,n只是一个变量(常量 !=
不可变的变量,但在标准C++中,这样定义的是一个常量,这种写法是对的),实际上,根据编译过程及内存分配来看,这种用法本来就应该是合理的,只是
ANSI C对数组的规定限制了它。      
3)、那么,在ANSI C
语言中用什么来定义常量呢?答案是enum类型和#define宏,这两个都可以用来定义常量。  
问题2:const变量 和 const 限定的内容 ?
下面的代码编译器会报一个错误,请问,哪一个语句是错误的呢?       
typedef char * pS  
char string[4] = "abc";  
const char *p1 =  
const pStr p2 =  
p2++;      
答案与分析:问题出在p2++上。      
1)、const使用的基本形式: 限定m不可变。      
2)、替换1式中的m, const char * 限定*pm不可变,当然pm是可变的,因此问题中p1++是对的。   
3)、替换1式char, const newT
限定m不可变,问题中的charptr就是一种新类型,因此问题中p2不可变,p2++是错误的。 
问题3:const变量 和 字符串常量 ?    
请问下面的代码有什么问题?   
char *p = "i'm hungry!";   p[0]= 'I';       
答案与分析:上面的代码可能会造成内存的非法写操作。
分析如下, “i'm
hungry”实质上是字符串常量,而常量往往被编译器放在只读的内存区,不可写。p初始指向这个只读的内存区,而p[0] =
'I'则企图去写这个地方,编译器当然不会答应。  
问题4:const变量 和 字符串常量2 ?      
请问char a[3] = "abc" 合法吗?使用它有什么隐患?      
答案与分析:在标准C中这是合法的(转注:在C++中报错,error C2117: “a”:
数组界限溢出),但是它的生存环境非常狭小;它定义一个大小为3的数组,初始化为“abc”,,注意,它没有通常的字符串终止符'/0',因此这个数组只
是看起来像C语言中的字符串,实质上却不是,因此所有对字符串进行处理的函数,比如strcpy、printf等,都不能够被使用在这个假字符串上。 
问题5:const 和 指针      
类型声明中const用来修饰一个常量,有如下两种写法,
那么,请问,下面分别用const限定不可变的内容是什么?       
1)、const在前面   
const int nValue; //nValue是const  
const char *pC //*pContent是const, pContent可变 
const (char *) pC//pContent是const,*pContent可变 
char* const pC //pContent是const,*pContent可变 
const char* const pC //pContent和*pContent都是const    
2)、const在后面,与上面的声明对等   
int const nValue; // nValue是const  
char const * pC// *pContent是const, pContent可变 
(char *) const pC//pContent是const,*pContent可变 
char* const pC// pContent是const,*pContent可变 
char const* const pC// pContent和*pContent都是const      
答案与分析:      
const和指针一起使用是C语言中一个很常见的困惑之处,在实际开发中,特别是在看别人代码的时候,常常会因为这样而不好判断作者的意图,下面讲一下我的判断原则:   
沿着*号划一条线,如果const位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。你可以根据这个规则来看上面声明的实际意义,相信定会一目了然。
二、C中const和C++中const区别
只读变量 & 常量
在C语言中,被const修饰的就是常量吗?真的能不动如山吗?编译如下代码,你觉得如何?
&& const int a = 10;
&& int *pa =
printf("%d/n",*pa);
printf("%d/n",a);
编译器并不会像你想的那样会报错,只是给出警告(warning C4090: “初始化”:
不同的“const”限定符)&
你运行时才发现,a的值已经被改掉了。变成了 20
关键字const并不能把变量变成常量!在一个符号前面加上限定符const只是表示不能被赋值,换句话说,它的值对这个符号来说是只读的,但是并不能防止通过程序的内部(或者说外部)的方法来修改这个值。
所在C语言中被const修饰的变量只是一个只读的变量而已。如:
const int n = 100;
(C不提倡这样写,可以用宏代替)
但是在C++中不是这样的,在C++中被const的修饰毫无疑问是常量,它的值在编译时就被确定了。
&& const int a
&& int *pa =
printf("%d/n",*pa);
上面代码在C++中是错误的,肯定会出现编译错误。( error C2440: “初始化”: 无法从“const int
*”转换为“int *” )
而下面代码在C++中是很普遍的。
&&& const int n
而且这样的表达是很普遍的很值得提倡的表示法(C++中不提倡使用宏,宏可以被常量、内联函数替代)。
在C++中的const属性是可以被去掉的,通过const_cast就可以强转掉。你试过这样的代码吗?
&iostream&
int main()
const int a = 10;
const int *pa = &a;
const_cast&int*&(pa);
cout && *pa
cout && *pb
输出结果为
三、内连接和外连接的区别
&const variable
在定义时必须初始化,是文件内部可见。这是因为c++中,const变量默认是内连接的(internal
linkage)。(原因见后)
也就是说它只能在定义它的文件内部使用,连接时其它编译单元看不见它。
&&&&&&&&&&
const int i = 0
而且编译器一般不为const variable分配内存,而是将它放入
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&
//符号表(symbol table),以便编译时实现常量折叠(constant folding)。
但是,若是进行如下定义:
&&&&&&&&&&&
则将强制编译器为变量分配内存空间。因为,extern 意味着使用外部链接(external linkage)。
当你对一个const variable 去地址时,也会进行内存分配。例如:
&&&&&&&&&&&
const int i = 9;
&&&&&&&&&&&
long address =& (long ) &i;
由上面我们可以看出,编译器并不总是能够成功的避免为常量分配内存,上述两种情况就必须分配内存。所以const
如果默认是外连接,就有可能导致同一个常量在不同的cpp文件中都分配了内存(比如多个文件中都要求取得一个常量的地址)。
这就会让编译器认为同一常量出现重复定义而报错。
而如果常量默认为内连接,这就意味着该常量只在当前定义它的文件内部有效,而连接器不会试图去连接其他编译单元里的常量。
&&&&&这样,即使多个cpp文件中有相同名字的一个常量也不会发生冲突。如此,编译器就可有效的实现常量折叠(constant
&&&&&另外,有上面我们知道,在C++中,
const int i = 0;
&&&&&i的值是在符号表里,这就意味着i的值是编译期间可见的。所以,如下代码是可行的:
const& int i = 0;
const& int j = i + 1;& // ok!
因为i的值在编译时知道,j也是const
这里和C中的const有所不同,C中的const默认为外连接,所以总是会为其分配内存空间。这就意味着,在C中
const& int bufsize = 100;
在编译期间,编译器并不知道 bufsize的值。所以,下面的代码有误:
const& int bufsize& = 100;
char buf[bufsize]; // error
&&&&&&还有一点不同的是:
这句代码在C中是可以的,编译器认为这是一个声明,某处有为这个常量分配内存,但是在C++中,这句代码是不可以的。
可以有两种方式修改:
(1) const int bufsize = 100;& //定义时初始化
&&&&&&&&(2)
& // 当然,这句在C中也是可以的
&////////////////////////////////////////////////////////////////////////////////////
&在C语言中:
这个语句是正确的,因为它被C编译器看作一个声明,指明在别的地方分配存储空间.但在C++中这样写是不正确的.C++中const默认是内部连接,如果想在C++中达到以上的效果,必须要用extern关键字.
C++中,const默认使用内部连接.而C中使用外部连接.
内连接:编译器只对正被编译的文件创建存储空间,别的文件可以使用相同的表示符
或全局变量.C/C++中内连接使用static关键字指定.
外连接:所有被编译过的文件创建一片单独存储空间.一旦空间被创建,连接器必须解
决对这片存储空间的引用.全局变量和函数使用外部连接.通过extern关键
字声明,可以从其他文件访问相应的变量和函数.
************************C++代码******************************
const int test = 1;
#include "header.h"
int main()
cout && "in test1 :"
#include "header.h"
void print()
cout && "in test2:"
以上代码编译连接完全不会出问题,但如果把header.h改为:
extern const int test = 1;
在连接的时候,便会出现以下错误信息:
test2 error LNK2005: "int const test" () 已经在 test1.obj 中定义
因为extern关键字告诉C++编译器test会在其他地方引用,所以,C++编译器就会为test创建存储空间,不再是简单的存储在名字表里面.所以,当两个文件同时包含header.h的时候,会发生名字上的冲突.
此种情况和C中const含义相似:
const int test = 1;
#include "header.h"
int main()
printf("in test1:%d/n",test);
#include "header.h"
void print()
printf("in test2:%d/n",test);
test3 fatal error LNK1169: 找到一个或多个多重定义的符号
test3 error LNK2005: _test 已经在 test1.obj 中定义
C++中,是否为const分配空间要看具体情况.
如果加上关键字extern或者取const变量地址,则编译器就要为const分配存储空间
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 const和define的区别 的文章

 

随机推荐