关键字const.docx

上传人:b****5 文档编号:11893201 上传时间:2023-04-08 格式:DOCX 页数:9 大小:19.76KB
下载 相关 举报
关键字const.docx_第1页
第1页 / 共9页
关键字const.docx_第2页
第2页 / 共9页
关键字const.docx_第3页
第3页 / 共9页
关键字const.docx_第4页
第4页 / 共9页
关键字const.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

关键字const.docx

《关键字const.docx》由会员分享,可在线阅读,更多相关《关键字const.docx(9页珍藏版)》请在冰豆网上搜索。

关键字const.docx

关键字const

关键字const

前两天在网上看到华为的一些笔试题,对基础的掌握仍然是这种大公司所重视的。

其间对指针掌握的要求比较多,有一道是关于const指针的。

看到那道题,回来整理了一些有关const指针的内容,分享一下。

  const说明指针变量,组合的情况可能会显得很复杂。

使用指针时要涉及两个目标,即指针本身和指针所指的对象。

关于const指针变量,可归结为以下三种:

  1.指向常量的指针变量;

  2.常指针变量;

  3.指向常量的常指针变量。

  下面来分别谈谈这三种情况。

一、指向常量的指针变量:

声明格式:

 consttype*var_name;

或 typeconst*var_name;

特点:

不可改值。

  将指针声明冠以const,使指向的对象为常量,而不是指针为常量。

注意:

指向常量的指针不一定指向真正的常量,它也可以指向变量,只是从该指针的角度来看,它所指向的对象是常量,通过该指针不能修改它指向的对象。

它还可以指向其它的对象,可以不初始化。

-----eg:

inta=0,b=1;

constintc=3;

constint*pi;//等同于(constint*)pi;

pi=&a;

*pi=10;//错误:

不能修改它指向的对象。

a=10;

pi=&b;

*pi=&b;

*pi=20;//错误:

不能修改它指向的对象。

b=20;

pi=&c;

*pi=&c;

*pi=30;//错误:

不能修改它指向的对象。

-----eg2:

constchar*pc="asdf";

pc[3]='a';//错误:

不能修改它指向的对象。

pc="ghik";

-----eg3:

constchar*step[3]=

{"left","right","hop"};

step[2]="skip";

step[2][1]='i';//错误:

不能修改它指向的对象。

二、常指针常量:

声明格式:

type*constvar_name;

特点:

 可改对象。

  要把指针本身,而不是它指向的对象声明为常量,采用运算符 *const,必须初始化,通过该指针可以修改它指向的对象,但它不可以指向其他的对象。

-----eg:

inta=0,b=1;

int*constpi=&a;//等于 int*(constpi)=&a;

*pi=10;

pi=&b;//错误:

pi本身为常量,不能指向其他对象。

三、指向常量的常指针变量:

声明格式:

consttype*constvar_name;

特点:

 值与对象均不能改。

  要使两个目标都是常量,两者都要声明为 const。

eg:

inta=0,b=1;

constintc=3;

constint*constpi=&a;//相当于:

(constint*)(constpi)=&a;

*pi=10;//错误:

不能修改它的对象。

a=10;

pi=&b;//错误:

不能指向其它对象。

eg2:

constchar*constpc="asdf";

pc[3]='a';//错误:

不能修改它的对象。

pc="ghik";//错误:

不能指向其它对象。

eg3:

constchar*conststep[3]=

{"left","right","hop"};

step[2]="skip";//错误:

不能指向其它对象。

step[2][1]='i';//错误:

不能修改它的对象。

  一般的,当声明中出现const描述符时,它修饰的是紧跟其后的声明元素或者在const成员函数声明中函数的this指针。

  注意:

可以将变量的地址赋给指向常量的指针变量,不会因此有什么害处,但是,常量的地址不能赋给无约束的指针。

eg:

inta=1;

constintc=2;

constint*p1=&c;

constint*p2=&a;

int*p3=&c;//非法!

int*constp4=&c;//非法!

指针常量p4能够改值。

constint*constp5=&c;

const----常量标志符,用来定义常量变量,能产生#define NUM  5一样的作用,但是更高级的作用体现在对程序的安全性的加强,以及对编译的优化上。

总结一下const的用法。

1、const int  NUM=5; 有些变量赋初值后不希望被更改,可以采用const来标志,当程序企图改变这些变量时,编译时会有错误提示。

2、void  Compute( const & T ); 引用参数传递的用法可以用来避免复制一些大类型的参数,节省内存,但是赋予了的调用函数更改权限,当参数不希望被更改时,可以才采用这种调用方式。

既节省了空间,又保障了安全性。

3、和指针组合使用产生的四种用法:

a非常量数据的非常量指针;b非常量数据的常量指针;c常量数据的非常量指针;d常量数据的常量指针。

这些其实都是对权限的限制,出于安全性方面的考虑。

用法都顾名思义,我解释一下常量指针

4、类中一些用法;可以定义const对象,即该对象不能被更改,跟第一点相同。

const成员函数void Compute(int)const;:

该函数不改变对象的属性----值。

而且const对象不能调用非const成员函数,即使该函数没有改变对象的值也不可以,会产生编译错误。

这些都是出于安全性方面的考虑。

不过当成员函数不改变对象的值的时候,推荐把函数定义为const类型,这样当程序企图改变对象时,编译会提示出错。

而且用const定义寒暑,可以优化编译,提高性能。

书上写的,原因我也不清楚:

)估计涉及到编译原理方面的知识,并且和编译器的具体设计有关。

目前所了解得就这么多^_^

Const

(2)

今天让指针常量,常量指针的说法搞糊涂了,原理明白,但是叫法上的区分糊涂呵呵!

const是C特别是C++中经常遇到的东西,能灵活的运用可以体现你的CC++的水平。

1.常量和预编译

    我们都知道在C中用到常量往往是通过预编译来实现,但是这样最大的缺点是不能够进行类型检查,使用const修饰变量就可以客服这样的缺点。

    常量在定义时必须初始化,除非它是extern

2.const与指针(重点)

    一般来讲我们可以定义5中类型的指针:

   int *pdata1;

   constint*pdata2;

   int*constpdata3;

   constint*constpdata4;

   intconst*pdata5;

   第一个和第四个比较简单:

pdata1是普通的指针;pdata4是指向常量的指针常量:

指向和指向的内容都不能改变。

   对于1,3我们看const与*的位置:

如果const在*之前。

那么就是常量指针,否则就是指针常量,

   如:

   char*consta=0,b;是指针常量,const只属于a不属于b

   charconst*a;是常量指针

   constchar*a;也是常量指针

   我自己总结了这样的记忆方法:

前固数,后固址!

就是说const在*前是固定数据,在后是固定地址。

大家还可以看出“数”正好在“址”的按照音序的前面,这样理解记忆就好了。

   通过上面的讲解,我想大家见到以后肯定不会出错了。

但是怎样区分这两种说法呢?

“常量指针”“指针常量”类比是最好的方法我经常这样用:

“函数指针”“数组指针”。

“函数指针”是指向函数的指针,“数组指针”是指向数组的指针。

那么,“常量指针”是指向常量的指针,也就是内容“数据”不能改变。

指针常量就是另外的一种意思。

   最后需要注意的是:

指针常量在定义时必须初始化,因为后面再也不能修改。

3.常量和函数

  常量和函数的联姻还是出于效率的考虑。

这也是const的最常用的用途之一。

   3.1const修饰函数的参数,参数传递时按值传递需要复制一份,当数据量很大时,是很昂贵的。

用了指针把地址传过去就可以了。

如果不想让函数改变参数的的值的话就用const修饰。

  voidfun(constint*p);

   3.2const修饰函数的返回值,还是出于效率的考虑当函数返回时,也是需要临时变量的,如果用指针(当最好是引用C++的新特性)就可以省去这样的开销。

为了保证数据的安全性,返回的数据可能不想让用户随便改动,那么使用const:

constchar*getname();

  3.3在C++中修饰成员函数,防止改变对象的状态(成员变量):

char*player:

:

Getname()const,const的成员函数不能够调用非const的函数。

那么是不是const函数什么都不能改呢?

不是。

C++中提供了mutable关键字来修饰变量,使得它可以在任何的函数中可以修改。

有三种方法来定义const 型指针:

  

(1)const <类型> *<指针变量名>;

  该语句的作用是:

定义指针变量所指数据值为常量,即:

指针变量所指数据值不能改变,但指针变量值可以改变。

例如:

  float x,y;

  const float *p=&x; //定义指针变量p所指数据值*p为常量

  *p=25; //错误,p所指变量x数据值不能用*p形式进行改变

  p=&y; //正确,可改指针变量p的值

  x=25; //正确,变量x的值可以改变

  

(2)<类型> * const <指针变量名>;

  该语句的作用是:

定义指针变量值为常量,即:

指针变量值不能改变,但指针变量所指数据值可以改变。

例如:

  float x,y;

  float * const p=&x; //定义指针变量p的值为常量

  *p=25; //正确,p所指变量x数据值可以用*p形式进行改变

  p=&y; //错误,指针变量p的值不能改变

  用这种形式定义的指针变量,必须在定义时赋初值。

  (3)const <类型> * const <指针变量名>;

  该语句的作用是:

定义指针变量值为常量,指针变量所指数据值为常量。

即:

指针变量值不能改变,指针变量所指数据值也不能改变。

例如:

  float x,y;

  const float * const p=&x; //定义指针变量p为常量

  *p=25; ` //错误,p所指变量x数据值不能用*p形式进行改变

  p=&y; //错误,不能改变指针变量p的值

  用这种形式定义指针变量,必须在定义时赋初值。

  注意:

  

(1)因为引用变量类同于指针变量,所以这三种定义形式完全适应于引用类型变量。

  

(2)定义const类型指针的目的是提高程序的安全性,用const 可限制程序随意修改指针值。

  (3)const 指针主要用作函数参数,以限制在函数体不能修改指针变量的值,或不能修改指针变量所指数据值。

Const(3)

关键字const有什么含意?

我只要一听到被面试者说:

“const意味着常数”,我就知道我正在和一个业余者打交道。

去年DanSaks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:

EmbeddedSystemsProgramming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。

尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。

(如果你想知道更详细的答案,仔细读一下Saks的文章吧。

如果应试者能正确回答这个问题,我将问他一个附加的问题:

下面的声明都是什么意思?

constinta;

intconsta;

constint*a;

int*consta;

intconst*aconst;

/******/

前两个的作用是一样,a是一个常整型数。

第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。

第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。

最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。

如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。

顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?

我也如下的几下理由:

•;关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。

如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。

(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。

•;通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。

•;合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。

简而言之,这样可以减少bug的出现。

Volatile

8.关键字volatile有什么含意?

并给出三个不同的例子。

一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。

精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。

下面是volatile变量的几个例子:

•;并行设备的硬件寄存器(如:

状态寄存器)

•;一个中断服务子程序中会访问到的非自动变量(Non-automaticvariables)

•;多线程应用中被几个任务共享的变量

回答不出这个问题的人是不会被雇佣的。

我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。

搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。

不懂得volatile的内容将会带来灾难。

假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile完全的重要性。

•;一个参数既可以是const还可以是volatile吗?

解释为什么。

•;一个指针可以是volatile吗?

解释为什么。

•;下面的函数有什么错误:

intsquare(volatileint*ptr)

{

return*ptr**ptr;

}

下面是答案:

•;是的。

一个例子是只读的状态寄存器。

它是volatile因为它可能被意想不到地改变。

const因为程序不应该试图去修改它。

•;是的。

尽管这并不很常见。

一个例子是当一个中服务子程序修该一个指向一个buffer的指针时。

•;这段代码有点变态。

这段代码的目的是用来返指针*ptr指向值的平方,但是,由于*ptr指向一个volatile型参数,编译器将产生类似下面的代码:

intsquare(volatileint*ptr)

{

inta,b;

a=*ptr;

b=*ptr;

returna*b;

}

由于*ptr的值可能被意想不到地该变,因此a和b可能是不同的。

结果,这段代码可能返不是你所期望的平方值!

正确的代码如下:

longsquare(volatileint*ptr)

{

inta;

a=*ptr;

returna*a;

}

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 人文社科 > 设计艺术

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1