C++中的常量与变量

指针与数组

//text.cpp
int arr[5] = { 1,2,3,4,5 };
//main.cpp
extern int* arr;
int main()
{
	int ar[3] = { 1,2,3 };
	cout << arr <<endl; //打印出00000001 输出的为数组的第一个元素,为什么呢?因为在main.cpp中是按指针引用了,此事得arr是一个指针变量,变量在取值时都会进行一次解引用,所以将arr这个地址中的值取了出来,所以输出的结果为1
	cout << *arr <<endl; //执行到此处程序崩溃,为什么崩溃?arr已经进行了一次解引用,*arr是将arr解引用取出的值,也就是0000 0001这个地址中的值再一次取出,那么自然就会崩溃了
	return 0;
}

int main()
{
	int ar[3] = { 1,2,3 };
	printf("%p\n", ar);//打印出ar这个地址
	printf("%d\n", *ar);//打印出1
	return 0;
}

为什么两次的结果不相同?原因是常量与变量的区别

常量与变量

  • 常量在编译期将常量的值直接写入到常量的使用点
  • 常量的初始化必须使用常量,如果使用变量就会退化成常变量
  • ar作为数组名是一个地址,而地址是一个常量,编译时常量的值会直接编译到代码中
  • 指针是一个变量

常量与变量赋值的区别

int main()
{
	int a = 10;
	int* p = &a;
	int arr1[] = { 1,2,3,4,5 };
	cout << arr1 << endl;//输出地址
	//执行这句时的汇编
	//lea    eax,[arr1]   直接将arr1这个地址放到eax寄存器中
	//push   eax
	cout << p << endl;//输出地址
	//执行这句时的汇编
	//mov    eax,dword ptr [p]   //去p的地址中取四个字节放到eax寄存器
	//push   eax
}
int main()
{
	int a = 10;
	int b = 20;
	int* p = nullptr;
	p = &a;
	//汇编
	//mov    dword ptr [b],14h
	int c = a;
	//mov    eax,dword ptr [a]
	//mov    dword ptr [b],eax
	b = *p;
	//mov    eax,dword ptr [p]   //先去p的地址中里边存储的地址拿出来,放到eax
	//mov    ecx,dword ptr [eax] //再从拿出来的地址中取出数放到ecx
	//mov    dword ptr [b],ecx   //将ecx寄存器中的数,放到p的地址中
	return 0;
}

const修饰符

int main()
{
	const int a = 10;
	//a = 20;
	//int *p = &a;//行不通

	int* p = (int*)&a;
	*p = 20;
	
	cout << a << endl;  //打印出10
	cout << *p << endl; //打印出20   为什么结果会这样?看下一段代码
}
  • 面试:为什么常量必须初始化?
  • 因为在编译期会将所有使用到常量的点,都替换为该常量的值
  • 根据下面的代码,可以知道,常量就是常量,即使指针p看上去是指向了a,但是本质上指向的是一个临时量的,是不可能让你取改变这一常量的
int main()
{
	const int a = 10;
	//a = 20;
	//int *p = &a;//行不通,const int *类型的变量不能初始化int *类型的变量

	int* p = (int*)&a;//在这里生成一个临时的变量,取的是临时量的值,所以在上边那个代码中,不是改变了a的值,而是改变一个临时量的值,才会出现那种情况
	//lea  eax,[a]
	//mov  dword  ptr [p],eax 

	*p = 20;

	int b;
	b = a;  // 因为a是常变量,在编译期直接将常量的值写入常量的使用点
	//mov  dword ptr [b],0Ah
	b = *p; //在这里,p是指针变量
	//mov  eax,dword ptr [p]
	//mov  ecx,dword ptr [eax]
	//mov  dword ptr[b],ecx
}
  • 在c语言中,const的用法与C++中略有不同
  • const修饰的内容不能做左值
int main()
{
	int a = 10;

	int* p1 = &a;
	const int* p2 = &a;
	int const* p3 = &a;
	int* const p4 = &a;

	int* q1 = &a;
	const int* q2 = &a;
	int const* q3 = &a;
	int* const q4 = &a;

	p1 = q1; 
	p1 = q2; //error 泄露常量的地址给非常指针
	p1 = q3; //error
	p1 = q4;

	p2 = q1;
	p2 = q2;
	p2 = q3;
	p2 = q4;

	p3 = q1;
	p3 = q2;
	p3 = q3;
	p3 = q4;

	p4 = q1; //error
	p4 = q2; //error
	p4 = q3; //error
	p4 = q4; //error
	return 0;
}
  • const修饰的内容如果不包含指针,则不参与类型
int fun(int a)
{
    cout << typeid(a).name() <<endl;
    return 0;
}

int fun(const int a)
{
   cout << typeid(a).name() <<endl;
    return 0;
}
//这两个函数不可以形成重载,因为const修饰的内容如果不包含指针,则不参与类型
int fun(int *a)
{
    cout << typeid(a).name() <<endl;
    return 0;
}

int fun(const int *a)
{
   cout << typeid(a).name() <<endl;
    return 0;
}
//如果改成这样,则可形参重载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值