Const型的常量与#define宏定义的异同点
相同的作用
在程序执行过程中Const定义的常量与#define预定义的常量会被替换为他们本身的值。而且在程序执行过程中,均不可改变。
#include <iostream>
int main()
{
const int i = 9;
int j = 10;
std::cout << j * i << std::endl;
std::cout << j * 10 << std::endl;
// 由此可见Const类型常量可认为被他本身的数值替换掉了
}
但是注意Const类型的变量不能改变:
#include <iostream>
int main()
{
const int i = 9;
int j = 10;
std::cout << j * i << std::endl;
std::cout << j * 10 << std::endl;
// 由此可见Const类型常量可认为被他本身的数值替换掉了
i = 11;
}
错误提示如下:
对于#define预处理,同样不能改变预定义常量的值:
#include <iostream>
#define i 10 // 预定义格式:#define constant value,其中代码结尾没有“;”,而且三者之间均已空格连接
int main()
{
int j = 10;
std::cout << j * i << std::endl;
std::cout << j * 10 << std::endl;
// 由此可见Const类型常量可认为被他本身的数值替换掉了
i = 10;
}
错误提示:
注:#define预定义宏操作与Const类型定义位置没有限制,但是#define一般都会在main函数之外,预定义头文件之后被定义,只要定义先于常量的使用就OK了。
作用域即起作用位置不同
下图为C++编译器对于我们所写代码的处理过程:
#define预处理命令在预处理其中被执行 |
Const类型的常量在编译运行时起作用 |
准确来说,他们所定义的类型也不同
C++为强类型语言,因此有严格的变量类型定义规则。在visual studio的C++程序中,提倡用const类型定义替代C语言中的#define宏定义。
Const类型为何比#define宏操作要好呢?这是为什么呢?
就起作用的方式而言: define只是简单的字符串替换,没有类型检查。而const有对应的数据类型,是要进行判断的,可以避免一些低级的错误。 正因为define只是简单的字符串替换会导致边界效应,具体举例可以参考下面代码:
代码1:
#include <iostream>
#define i 10.0 // 预定义格式:#define constant value,其中代码结尾没有“;”,而且三者之间均已空格连接
int main()
{
int j = 10;
std::cout << i / 3 << std::endl;
std::cout << j * 10 << std::endl;
// 由此可见Const类型常量可认为被他本身的数值替换掉了
}
代码2:
#include <iostream>
#define i 10 // 预定义格式:#define constant value,其中代码结尾没有“;”,而且三者之间均已空格连接
int main()
{
int j = 10;
std::cout << i / 3 << std::endl;
std::cout << j * 10 << std::endl;
// 由此可见Const类型常量可认为被他本身的数值替换掉了
}
你发现什么不同了吗?
代码1中为i/3,代码2中为i/3.0。这两者产生结果不相同:
代码段一:10.0/3=3.33333333333(在屏幕上输出float型结果)
代码段二:10/3=3(在屏幕上输出int型结果)
#define会根据你所定义常量的值进行自动定义类型,有时会是你摸不到头绪,很烦人。
但const类型定义不同,const类型定义符合C++类型定义的强类型定义规则,即定义常量或者变量,必须定义他们的数据类型。
#include <iostream>
int main()
{
const int i = 10;
int j = 10;
std::cout << i / 3 << std::endl;
std::cout << j * 10 << std::endl;
// 由此可见Const类型常量可认为被他本身的数值替换掉了
}
这样书写代码在C++中才算规范。
占用空间位置不同
- 就空间占用而言: 例如:
- #define PI 3.14 //预处理后,占用代码段空间,镶嵌在程序之中,一旦预处理后代码中的相应位置均会被替换,该段代码就变成了无用字段,会影响程序运行效率
- const float PI=3.14; //本质上还是一个 float,但作为一个静态常量占用数据段空间
#define宏定义可重定义同名常量而const至始至终只能定义一次同名常量
#include <iostream>
using namespace std;
int main()
{
#define MODI 10
cout << MODI << endl;
#undef MODI
cout << MODI + 1 << endl;
return 0;
}
编译器会对第九行程序报错,因为我们取消了MODI的宏定义
切记:当用完一个宏,比如MODI,不希望下面的代码再用到这个MODI,,那么就可以#undef它,那么下面如果再用到了MODI这个宏,编译器就会报错。
#XXX预处理操作可以避免重复定义
#ifdef MOD // if(MOD被定义)
#undef // MOD之前被定义过,那么就取消预定义 MOD 宏操作
//(说白了“预定义宏该操作”就是在程序执行前进行简单的符号替换)
#else // 否则
#define MOD 10 // MOD之前没被定义过,那么就预定义 MOD = 10
其他预处理操作符:
#define 定义一个预处理宏
#undef 取消宏的定义
#if 编译预处理中的条件命令,相当于C语法中的if语句
#ifdef 判断某个宏是否被定义,若已定义,执行随后的语句-if(define)
#ifndef 与#ifdef相反,判断某个宏是否未被定义-if(undefine)
#elif 若#if, #ifdef, #ifndef或前面的#elif条件不满足,则执行#elif之后的语句,相当于C语法中的else-if
#else 与#if, #ifdef, #ifndef对应, 若这些条件不满足,则执行#else之后的语句,相当于C语法中的else
#endif #if, #ifdef, #ifndef这些条件命令的结束标志.
重点:其中辨析#if与if的用法:
#if是“是否开启以下代码预处理命令的判断语句”;
If则是“常规程序中的判断语句”。
#define A 0 //把A定义为0
// 以下这段程序表明:如果A>1,则进行#if-#endif之间的预处理命令
#if (A > 1)
printf("A > 1"); //编译器没有编译该语句,该语句不生成汇编代码
#elif (A == 1)
printf("A == 1"); //编译器没有编译该语句,该语句不生成汇编代码
#else
printf("A < 1"); //编译器编译了这段代码,且生成了汇编代码,执行该语句
#endif
补充:强类型语言与弱类型语言的区别
强/弱类型是指类型检查的严格程度的。语言有无类型,弱类型和强类型三种。无类型的不检查,甚至不区分指令和数据。弱类型的检查很弱,仅能严格的区分指令和数据。强类型的则严格的在编译期进行检查。
C# 是强类型语言;因此每个变量和对象都必须具有声明类型,即必须为所有变量指定数据类型称为“强类型”。
弱类型就像javascript中的var 可以接受任何类型。
举个例子:
简单点:假设你在c#代码中,你定义了一个整型变量后,就不能赋一个字符型数据给这个变量(除非你用强制类型转换)。