C语言深度剖析--读书笔记7_const关键字

1.const修饰只读变量

(1)在GCC中,const修饰的是只读变量注意,在GCC中,只读变量可以用来定义数组,但是不可以用作case 后面的判断条件。   

#include "stdio.h"

int main(void)
{
	int i;
	const int a=1;
	const int b=2;
	const int c=3;
	const int size=10;

	int iarr[size]; //没有问题,编译可以通过!

	i=2;
	switch(i)
	{
		case a:       //报错:case标号不能还原为一个整常量
			printf("a is %d\n",a);
			break;
		case b:     //报错:case标号不能还原为一个整常量
			printf("b is %d\n",b);
			break;
		case c:    //报错:case标号不能还原为一个整常量
			printf("c is %d\n",c);
			break;
		default:    
			printf("default\n");
			break;
	}

	return 0;
}
分析上面的例子,在case处报错。因为case后面必须跟:整型常量或整型类型的常量表达式(字符型也可以,因为字符在内存中,是ASCII值,也是整型)。 所以可以说明const修饰的仍是一个变量(只读的)

(2)在ANSI C中,const修饰的也是只读变量

    与GCC不同的是,在ANSI C中,只读变量不能用于定义数组。这里要注意 只读变量和常量的区别:只读变量在定义之后, 不可以再被赋值,修改。同时只读变量仍是一个变量,在编译的时候,编译器不知道其存储的内容

int main(void)
{
    const int size=10;
    int array[size];  //报错!只读变量不能用于定义数组
    return 0;
}
(3)只读变量一旦定义,不能再被赋值,修改。

const int i;
i=10; //报错:不可以向只读变量i赋值


2.const修饰变量,数组,指针

(1)修饰一般变量,数组

const作为修饰符,可以放在类型说明符前,也可以放在后。注意,const修饰数组的时候,数组中元素不可被修改

int const i1=2;
const int i2=2;//两个式子等价

int const array1[3]={1,2,3};
const int array2[3]={1,2,3}; //两个式子等价
array1[1]=0;  //报错,向只读位置array[1]赋值
(2)修饰指针

const修饰指针的时候,存在一个限定范围的问题(即指针本身不可改,还是指针指向的内容不可改)。编译器在处理的时候,先忽略类型描述符,看距离const右边紧邻的是谁,那么就认为const限定谁

#include "stdio.h"

int main(void)
{
	int i=1;
	int j=2;
	
        const int *p1=&i;  //const 离*近,修饰的是*p1,即p1所指的对象。而p1本身是可以修改的,所以p1可以指向其它位置。。
	p1=&j;  //正常通过
	*p1=j;  //报错:向只读位置‘*p1’ 赋值

	int const *p2=&i;  //此时与上一种情况相同
	p2=&j;  //ok~
	*p2=j;  //报错:向只读位置‘*p1’ 赋值

	int * const p3=&i;  //const 离p3近,修饰的是p3,p3不能指向其他内容。而p3所指向的内容可以被修改
	p3=&j;  //报错:向只读变量‘p3’赋值
	*p3=j;  //ok~
	
	const int * const p4=&i;  //前一个const修饰*p4,后一个const修饰p4,所以p4和*p4都不可以被修改
	p4=&j;  //错误:向只读变量‘p4’赋值
	*p4=j;  //错误:向只读位置‘*p4’赋值
}

3.const修饰函参,函数

(1)修饰函数参数。当不希望参数值在函数体内被意外改变的时候使用。

int func(const int *p)//建议一般的函数参数都按照此方式定义
{
	int i=10;
	p++;   //ok~p指针本身是可以被修改的
	*p=10;  //错误:向只读位置‘*p’赋值
	return 0;
}

int main(void)
{
	int array[5]={1,2,3,4,5};
	func(array);
	return 0;
}
(2)修饰函数返回值

如果返回值采用值传递的方式,那么加const是没有意义的。因为函数返回该值后,需要有一个变量来接收函数的返回值。而这个变量,其实是可以修改的。另一方面,如果返回值采用的是指针传递的方式(即返回:在函数执行过程中,保存在在堆上的变量的指针),那么才是有意义的

#include "stdlib.h"
const int *  func(void)
{
	int *p;
	p=malloc(10*sizeof(int));// 在堆上分配的10*4个字节内存,不会随func函数的结束而被销毁
	return p;                             // 而返回类型是const int * ,即说明此段内存,不允许被修改
}
int main(void)
{
	int *p1;
	const int *p2;
	p1=func(); //GCC会警告:该赋值,会导致func函数返回值的const性质被忽略(因为接收它的)
	p2=func();//正确!
}
最后补充一点: 用于接收const类型返回值的变量,也应该是cosnt类型的,如上代码。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值