搜档网
当前位置:搜档网 › C++中const的用法讲解

C++中const的用法讲解

C++中const的用法讲解
C++中const的用法讲解

面向对象是C++的重要特性. 但是c++在c的基础上新增加的几点优化也是很耀眼的,

就const直接可以取代c中的#define ...

讲解以下几点:

const

1. 限定符声明变量只能被读

const int i=5;

int j=0;

...

i=j; //非法,导致编译错误

j=i; //合法

2. 必须初始化

const int i=5; //合法

const int j; //非法,导致编译错误

3. 在另一连接文件中引用const常量

extern const int i; //合法

extern const int j=10; //非法,常量不可以被再次赋值

4. 便于进行类型检查

用const方法可以使编译器对处理内容有更多了解。

#define I=10

const long &i=10; /*dapingguo提醒:由于编译器的优化,使

得在const long i=10; 时i不被分配内存,而是由10直接代入

以后的引用中,以致在以后的代码中没有错误,为达到说教效

果,特别地用&i明确地给出了i的内存分配。不过一旦你关闭所

有优化措施,即使const long i=10;也会引起后面的编译错误。*/

char h=I; //没有错

char h=i; //编译警告,可能由于数的截短带来错误赋值。

5. 可以避免不必要的内存分配

#define STRING "abcdefghijklmn\n"

const char string[]="abcdefghijklm\n";

...

printf(STRING); //为STRING分配了第一次内存

printf(string); //为string一次分配了内存,以后不再分配 ...

printf(STRING); //为STRING分配了第二次内存

printf(string);

...

由于const定义常量从汇编的角度来看,只是给出了对应的内存

地址,

而不是象#define一样给出的是立即数,所以,const定义的常量在

程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝。

6. 可以通过函数对常量进行初始化

int value();

const int i=value();

dapingguo说:假定对ROM编写程序时,由于目标代码的不可改写,

本语句将会无效,不过可以变通一下:

const int &i=value();

只要令i的地址处于ROM之外,即可实现:i通过函数初始化,而其

值有不会被修改。

7. 是不是const的常量值一定不可以被修改呢?

观察以下一段代码:

const int i=0;

int *p=(int*)&i;

p=100;

通过强制类型转换,将地址赋给变量,再作修改即可以改变const 常量值。

8. 请分清数值常量和指针常量,以下声明颇为玩味:

int ii=0;

const int i=0; //i是常量,i的值不会被修改const int *p1i=&i; //指针p1i所指内容是常量,可以不初始化

int * const p2i=ⅈ //指针p2i是常量,所指内容可修改const int * const p3i=&i; //指针p3i是常量,所指内容也是常量

p1i=ⅈ //合法

*p2i=100; //合法

关于C++中的const关键字的用法非常灵活,而使用const将大大改善程序的健壮性,参考了康建东兄的const使用详解一文,对其中进行了一些补充,写下了本文。

1. const常量,如const int max = 100;

优点:const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误(边际效应)2. const 修饰类的数据成员。如:

class A

{

const int size;

}

const 数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么。如

class A

{

const int size = 100; //错误

int array[size]; //错误,未知的size

}

const数据成员的初始化只能在类的构造函数的初始化表中进行。要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现。如class A

{…

enum {size1=100, size2 = 200 };

int array1[size1];

int array2[size2];

}

枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。

3. const修饰指针的情况,见下式:

int b = 500;

const int* a = & [1]

int const *a = & [2]

int* const a = & [3]

const int* const a = & [4]

如果你能区分出上述四种情况,那么,恭喜你,你已经迈出了可喜的一步。不知道,也没关系,我们可以参考《Effective c++》Item21上的做法,如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此,[1]和[2]的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位

置无关),这种情况下不允许对内容进行更改操作,如不能*a = 3 ;

[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;[4]为指针本身和指向的内容均为常量。

4. const的初始化

先看一下const变量初始化的情况

1) 非指针const常量初始化的情况:A b;

const A a = b;

2) 指针const常量初始化的情况:

A* d = new A();

const A* c = d;

或者:const A* c = new A();

3)引用const常量初始化的情况:

A f;

const A& e = f; // 这样作e只能访问声明为const的函数,而不能访问一

般的成员函数;

[思考1]:以下的这种赋值方法正确吗?

const A* c=new A();

A* e = c;

[思考2]:以下的这种赋值方法正确吗?

A* const c = new A();

A* b = c;

5. 另外const 的一些强大的功能在于它在函数声明中的应用。在一个函数声明中,const 可以修饰函数的返回值,或某个参数;对于成员函数,还可以修饰是整个函数。有如下几种情况,以下会逐渐的说明用法:A& operator=(const A& a);

void fun0(const A* a );

void fun1( ) const; // fun1( ) 为类成员函数

const A fun2( );

1)修饰参数的const,如void fun0(const A* a ); void fun1(const A& a);

调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const A* a,则不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。

[注意]:参数const通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数本就不需要保护,所以不用const修饰。

[总结]对于非内部数据类型的输入参数,因该将“值传递”的方式改为

“const引用传递”,目的是为了提高效率。例如,将void Func(A a)改为void Func(const A &a)

对于内部数据类型的输入参数,不要将“值传递”的方式改为“const引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x)不应该改为void Func(const int &x)

2)修饰返回值的const,如const A fun2( ); const A* fun3( ); 这样声明了返回值后,const按照"修饰原则"进行修饰,起到相应的保护作用。const Rational operator*(const Rational& lhs, const Rational& rhs)

{

return Rational(lhs.numerator() * rhs.numerator(),

lhs.denominator() * rhs.denominator());

}

返回值用const修饰可以防止允许这样的操作发生:Rational a,b; Radional c;

(a*b) = c;

一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。

[总结]

1. 一般情况下,函数的返回值为某个对象时,如果将其声明为

const时,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const(const A& test = A实例),则返回值具有const 属性,则返回实例只能访问类A中的公有(保护)数据成员和const 成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。

2. 如果给采用“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。如:

const char * GetString(void);

如下语句将出现编译错误:

char *str=GetString();

正确的用法是:

const char *str=GetString();

3. 函数返回值采用“引用传递”的场合不多,这种方式一般只出现在类的赙值函数中,目的是为了实现链式表达。如:

class A

{…

A &operate = (const A &other); //负值函数

}

A a,b,c; //a,b,c为A的对象

a=b=c; //正常

(a=b)=c; //不正常,但是合法

若负值函数的返回值加const修饰,那么该返回值的内容不允许修改,上例中a=b=c依然正确。(a=b)=c就不正确了。

[思考3]:这样定义赋值操作符重载函数可以吗?

const A& operator=(const A& a);

6. 类成员函数中const的使用

一般放在函数体后,形如:void fun() const;

任何不会修改数据成员的函数都因该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其他非const成员函数,编译器将报错,这大大提高了程序的健壮性。如:class Stack

{

public:

void Push(int elem);

int Pop(void);

int GetCount(void) const; //const 成员函数private:

int m_num;

int m_data[100];

};

int Stack::GetCount(void) const

{

++m_num; //编译错误,企图修改数据成员m_num

Pop(); //编译错误,企图调用非const函数

Return m_num;

}

7. 使用const的一些建议

1 要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;

2 要避免最一般的赋值操作错误,如将const变量赋值,具体可见思考题;

3 在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;

4 const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;

5 不要轻易的将函数的返回值类型定为const;

6除了重载操作符外一般不要将返回值类型定为对某个对象的const 引用;

[思考题答案]

1 这种方法不正确,因为声明指针的目的是为了对其指向的内容进行改变,而声明的指针e指向的是一个常量,所以不正确;

2 这种方法正确,因为声明指针所指向的内容可变;

3 这种做法不正确;

在const A::operator=(const A& a)中,参数列表中的const的用法正确,而当这样连续赋值的时侯,问题就出现了:

A a,b,c:

(a=b)=c;

因为a.operator=(b)的返回值是对a的const引用,不能再将c 赋值给const常量。

1.1.1. 定义普通常量

使用#define来定义常量也是常用方法,但const也可以用来定义常量,在[Effective C++]中建议使用const代替#define来定义常量,因为const定义的常量具有类型信息,而宏没有,所以使用const定义的常量在进行赋值操作时编译器会进行更严格的类型检查,是类型安全的。

const double PI = 3.1414926;

const int POOL_SIZE = 20;

定义常量有三种方法:宏、const、enum,其中宏应该尽量避免,而const与enum也各有优缺点,最大的区别就是enum只能用于定义整数,而不能定义浮点数;而对于定义逻辑关系较近的一组整数时比较适合使用enum,也可以考虑使用类代替enum(参见[??])。常量必须在定义时进行初始化,之后便不能再赋值。说它不能被赋值并不是说常量的值是绝对不会改变的,只是说不能直接赋值,但可以通过指针及强制类型转换、const_cast是可以改变常量的值的。

#include

using namespace std;

int main( void )

{

const int ci = 5;

const int* cpci = &ci;

int *pci = (int*)&ci;

cout<<"cpci = "<

return 0;

}

输出结果:

cpci = 002DFAC8, pci = 002DFAC8

ci=5, *cpci=1, *pci=1

ci=5, *cpci=2, *pci=2

ci != *cpci

之所以使用ci直接输出变量的值时显示其值始终没有改变,但通过指针间接显示出来的值是改变了,而且输出结果的最后一行很奇怪,ci的值与*cpci的值居然不相等,只因为编译器在编译时进行了优化,将代码中的ci直接替换成了5,与宏替换是相同的效果,而指针的值则是实际内存中的值。

所以,千万不要试图使用指针强行改变const变量的值,否则程序可能表现出错误的行为,而且查找起来这种错误非常困难。在gcc 4.3.4和visual C++ 2010中均默认打开了对常量的优化选项,目前还没找到关闭该优化的命令行选项,一定不要自作聪明去改const 变量的值。

1.1.

2. 修饰指针

把const与指针放到一起,很多人便会想到一个绕口令“指针常量与常量指针。“指针常量”即一个指针变量,该变量不能被赋值,而指针指向的内存单元的内容是可以改变的;“常量指针”即一个指向常量的指针,指针变量本身可以赋值,而指针指向的内存单元的内容是不可以被重新赋值的。

char a = 'A', b = 'B';

const char* ptoc = &a; // 常量指针

*ptoc = 'C'; // 改变指针指向内存单元的内容,不可以

ptoc = &b; // 改变指针的值,可以

char* const cp = &a; // 指针常量

cp = &b; // 改变指针的值,不可以

*cp = 'D'; // 改变指针指向内存单元的内容,可以

const char* const cptoc = &a; // 指向常量的指针常量

*cptoc = 'E'; // 不可以

cptoc = &b; // 不可以

const是修饰类型还是修饰指针,要看const的位置,放在*前就是修饰数据类型,放到*后就是修饰指针,const char和char const 是一样的。

建议:在不打算修改数据内容的时候都将指针定义成常量指针,不打算指针本身被修改的场合都定义成指针常量。尽可能地多用const,用错了没关系,编译器会提示你的,只要能够编译通过,就不会因为用错const而导致程序逻辑错误,应该说const负作用极小。

1.1.3. 修饰类成员常量

当使用const修饰类成员变量时便定义了常数据成员,它的使用与使用类外定义的常量本质上并没有什么区别,在这里只想指出一点:有网友提到const数据成员只能被const修饰的函数使用这是没有根据的,是错误的。

1.1.4. 修饰类成员函数

const修饰成员函数语法:

class Socket

{

public:

typedef unsigned short socket_port_t;

socket_port_t LocalPort( void ) const

{

++readCount;

return _port;

}

private:

socket_port_t _port;

mutable int _readCount;

};

使用const修饰的成员函数不能修改类的成员变量,如成员_port,而且只能调用成员类对象const函数,但有个例外,就是mutable 修饰的成员变量可以在const修饰的成员函数中被修改,如_readCount。

另外,const只能修饰非静态函数。

建议:将所有不改变对象状态的函数都使用const修饰符标识,以提高程序的可读性。其实,头文件就是最好的类接口的说明文档,越多的提供信息就能使程序的可读性越好,越利于维护。看到成员函数的const修饰符,读者便立即明白该函数不会改变程序的状态,这也有利于当程序状态出现异常时的问题定位。

1.1.5. 修饰类对象、对象引用或对象指针(常量指针)

当const修饰自定义的类对象时,与修饰C++内置类型的变量的思想是一致的,但稍有不同,除了不能被赋值外,还不能调用没有使用const修饰的非静态成员函数。当const修饰类对象引用、指针时限制是一样的,因为引用本身与直接使用该变量实质上没有区别,而使用指针只是将.操作符改为了->本质上还是一样的

const std::string hello = “Hello from Noock Tian;

std::cout<

hello = "Hi"; // 不可以赋值

hello.push_back("!"); // 不可以

1.1.6. 修饰函数参数

const修饰函数的例子是很常见了,表示函数的参数在函数体内不会被意外修改,一般用于修饰输入参数,例如标准库中的字符串连接函数。str1是输出参数,其内容会被修改,而str2为输入参数,其内容不会修改。

char* strcat(char* str1, const char* str2);

实际上在说到const用法一开始就提到,const只是一种声明,但并不能保证,例如strcat函数虽然声明了str2为const char*型,但并不能保证内部绝对不会修改str2的内容。但const从语言本身提供了一种编写自描述性代码的方法,只要使用函数与实现函数的双方都达成一致的约定,按照契约编程,我们就可以认为const修饰

的类型在函数体内不会被修改,这与const修饰类成员函数一样,可以提高软件的可读性。

1.1.7. 修饰函数返回值

const可以用于修饰任何类型,只要返回值类型不是void,const 就可以用来修饰返回值的类型。但实际上const用于修饰非引用的返回值类型是没有意义的,因为返回值一般都会被赋值给另一个变量,此时用于传递返回值的对象已经被销毁,修饰返回值类型的const的作用也就终结了。

当返回值是引用类型时,如果该引用的值不希望被修改是可以声明为常引用的,例如:

class Socket

{

public:

const string& IP( void ) const{ return _ip; }

private:

string _ip;

};

Socket sock;

string& ip = sock.IP(); // 不可以

疑问代词用法总结及练习

疑问代词用法总结及练习 句子是英语学习的核心。从句子使用的目的来分,它可分为四类 1、陈述句(肯定句和否定句) 2、疑问句(一般疑问句、特殊疑问句和选择疑问句) 3、祈使句(肯定句和否定句) 4、感叹句。 四大句子类型的相互转换,对于学生来讲是个难点,为此,可通过说顺口溜的形式来帮助学生解决这一难题。 如:将陈述句变成一般疑问句,可以变成这样的顺口留:疑问疑问调个头,把be(系动词“is are am”)放在最前头。 如:将陈述句的肯定句变成否定句,我们就可以这样说:否定,否定加“not”,加在何处,加在系动词的后面。 在句子相互转换的题型中,最难的要算“就下列划线部分提问”或是“看答句,写问句”这种题型了,其实,我们只要熟练掌握疑问词(what,what time, what colour, where, when, who, whose, which, how, how old ,how tall, how long, how big, how heavy , how much, how many等等)具体用法。

习题 一、选择正确的单词填空 (who, where, when) is that pretty girl She is my sister. are Jack and Tom They are behind you. do you go to school I go to school from Monday to Friday. has a beautiful flower John has a beautiful flower.

are they They are my parents. is my mother She is in the living room. are you going We are going to the bakery(面包坊). Jim and Wendy play ball They play ball in the afternoon. does he jog He jogs in the park. are you from I'm from Changchun city. 11. _______ is your birthday –On May 2nd. 12、_______ are you --- I`m in the office. 13. are you ---- I`m Alice. 二.用(what time, what color, what day, what)填空。 1. A: ______ _______ is it B: It is nine o’clock. 2. A: ______ _______ does your mother get up B: My mother gets up at 6:30. 3. A: ______ _______ do you go to bed B: I go to bed at 10:00. 4. A: ______ _______ do Diana and Fiona have supper B: Diana and Fiona have supper at 18:00. 5. A: ______ _______is it B: It is purple. 6. A: ______ _______ is the sky B: The sky is blue. 7. A: ______ _______ is your coat B: My coat is black. 8. A: ______ _______ is the dog B: The dog is white. 9. A: ______ _______ is today B: Today is Monday. 10. A: ______ _______ is tomorrow B: Tomorrow is Tuesday. 11. A: ______ _______ was yesterday B: Yesterday was Sunday. 12. A: ______ _______ do you like B: I like red. 13. A: ______ is this This is a computer. 14. A: ______ are you doing B: We are playing basketball.

const int

const int* a = &b 和const* int a = &b的区别收藏 如果const关键字不涉及到指针,我们很好理解,下面是涉及到指针的情况: int b = 500; const int* a = &b; [1] int const *a = &b; [2] int* const a = &b; [3] const int* const a = &b; [4] 如果你能区分出上述四种情况,那么,恭喜你,你已经迈出了可喜的一步。不知道,也没关系,我们可以参考《Effective c++》Item21上的做法,如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此,[1]和[2]的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关),这种情况下不允许对内容进行更改操作,如不能*a = 3 ;[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;[4]为指针本身和指向的内容均为常量。另外const 的一些强大的功能在于它在函数声明中的应用。在一个函数声明中,const 可以修饰函数的返回值,或某个参数;对于成员函数,还可以修饰是整个函数。有如下几种情况,以下会逐渐的说明用法: A& operator=(const A& a); void fun0(const A* a ); void fun1( ) const; // fun1( ) 为类成员函数 const A fun2( ); --------------------------------------------------------------------------------------------------------------------------------------------- const int * pi 、int const * pi与int * const pi及其操作 (本贴已经做了重大修改) 1 从const int i 说起

关键字Const与Volatile的使用

关键字const有什么含意? 我只要一听到被面试者说:“const意味着常数”,我就知道我正在和一个业余者打交道。去年Dan Saks已经在他的文章里完全概括了const的所有用法,因此ESP(译者:Embedded Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从没有读到那篇文章,只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的答案,但我接受它作为一个正确的答案。(如果你想知道更详细的答案,仔细读一下Saks的文章吧。) 如果应试者能正确回答这个问题,我将问他一个附加的问题: 下面的声明都是什么意思? const int a; int const a; const int *a; int * const a; int const * a const; /******/ 前两个的作用是一样,a是一个常整型数。第三个意味着a是一个指向常整型数的指针(也就是,整型数是不可修改的,但指针可以)。第四个意思a是一个指向整型数的常指针(也就是说,指针指向的整型数是可以修改的,但指针是不可修改的)。最后一个意味着a是一个指向常整型数的常指针(也就是说,指针指向的整型数是不可修改的,同时指针也是不可修改的)。如果应试者能正确回答这些问题,那么他就给我留下了一个好印象。顺带提一句,也许你可能会问,即使不用关键字const,也还是能很容易写出功能正确的程序,那么我为什么还要如此看重关键字const呢?我也如下的几下理由: ?; 关键字const的作用是为给读你代码的人传达非常有用的信息,实际上,声明一个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留下的垃圾,你就会很快学会感谢这点多余的信息。(当然,懂得用const的程序员很少会留下的垃圾让别人来清理的。) ?; 通过给优化器一些附加的信息,使用关键字const也许能产生更紧凑的代码。 ?; 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数,防止其被无意的代码修改。简而言之,这样可以减少bug的出现。 Volatile 8. 关键字volatile有什么含意?并给出三个不同的例子。 一个定义为volatile的变量是说这变量可能会被意想不到地改变,这样,编译器就不会去假设这个变量的值了。精确地说就是,优化器在用到这个变量时必须每次都小心地重新读取这个变量的值,而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子: ?; 并行设备的硬件寄存器(如:状态寄存器) ?; 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables) ?; 多线程应用中被几个任务共享的变量 回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道,所有这些都要求用到volatile变量。不懂得volatile的内容将会带来灾难。 假设被面试者正确地回答了这是问题(嗯,怀疑是否会是这样),我将稍微深究一下,看一下这家伙是不是直正懂得volatile 完全的重要性。 ?; 一个参数既可以是const还可以是volatile吗?解释为什么。 ?; 一个指针可以是volatile 吗?解释为什么。

英语一般疑问句用法总结

英语一般疑问句用法总结 1. 基本用法及结构 一般疑问句用于对某一情况提出疑问,通常可用yes和no来回答,读时用升调。其基本结构是“be / have / 助动词+主语+谓语(表语)”: Is he interested in going? 他有兴趣去吗? Have you ever been to Japan? 你到过日本吗? Does she often have colds? 她常常感冒吗? Did you ask her which to buy? 你问没问她该买哪一个? 2. 陈述句变一般疑问句的方法 (1) 动词be的否定式。动词be根据不同的时态和人称可以有am, is, are, was, were等不同形式,可用作连系动词(表示“是”、“在”等)和助动词(用于构成进行时态和被动语态等),但不管何种情况,构成疑问式时,一律将动词be的适当形式置于句首: Am I right? 我是对的吗? Are you feeling better today? 你今天感到好些了吗? Was he late for school? 他上学迟到了吗? (2) 动词have的疑问式。动词have根据不同的时态和人称可以有have, has, had等形式,可以用作实意动词和助动词,分以下情况讨论:

①用作实意动词表示状态,如表示拥有、患病或用于have to 表示“必须”等,在构成构成式时可以直接将have, has, had置于句首,也可根据情况在句首使用do, does, did: Does he have [Has he] anything to say? 他有什么话要说吗? Do you have [Have you] to leave so soon? 你必须这么早走吗? Did you have [Had you] any friends then? 他当时有朋友吗? ②用作实意动词表示动作,如表示“吃(=eat)”、“喝(=drin k)”、“拿(=take)”、“收到(=receive)”、“度过(=spend)”等,构成疑问式时不能将have提前至句首,而应在句首使用do, does, did: Does he have breakfast at home? 他在家吃早餐吗? Did you have a good time at the party? 你在晚会上玩得高兴吗? ③用作助动词构成完成时态,其疑问式总是将have等置于句首: Have you finished your work? 你的工作做完了吗? Has he left when you arrived? 你到达时他已离开了吗? (3) 情态动词的疑问式。情态动词的疑问式通常是将情态动词置于句首: Can you speak English? 你会说英语吗?

const,static,extern用法总结

--------------------------CONST--------------------------------------- const应用: 一、对于基本声明 const int r=100;//标准const变量声明加初始化,编译器经过类型检查后直接用100在编译时替换。 二、对于指针 1. int x=10; const int *r=&x; //指针指向的内容是常量,r指向的内容不能够通过r改变,但如果是非const,内容可以通过自己改变,而且r指针可以改变,可以指向其它的整形. //*r=*r+1;NO //x++;YES //r=&y;YES 2. int const *r=&x; 与1完全相同 3. int * const r=&x; //指针指向是常量,不能修改去指向其它内容,但指向的内容可以修改 //r=&y;NO //*r=*r+1;YES //x++;YES 4.const int * const r=&x; //综合1、3用法,r是一个指向常量的常量型指针,指针指向不能改变,指针内容不能改变,内容可以自身改变 //r=&y;NO //*r=*r+1;NO //x++;YES 三、对于类型检查 可以把非const对象赋予const指针,这样就不能改变.但是不能把const赋给非const,除非先强制转换 const int x=100; int *p=(int*)&x; *p++; 四、对于函数 1.void Fuction1(const int r); //此处为参数传递const值,意义是变量初值不能被函数改变 2.const int Fuction1 (int); //此处返回const值,意思指返回的原函数里的变量的初值不能被修改,但是函数按值返回的这个变量被制成副本,能不能被修改就没有了意义,它可以被赋给任何的const或非const类型变量,完全不需要加上这个const关键字。 3.Class CX; //内部有构造函数,声明如CX(int r =0) CX Fuction1 () { return CX(); } const CX Fuction2 () { return CX(); } Fuction1() = CX(1); //没有问题,可以作为左值调用 Fuction2() = CX(1); //编译错误,const返回值禁止作为左值调用。 4.函数中指针的const传递和返回: int F1 (const char *pstr); //作为传递的时候使用const修饰可以保证不会通过这个指针来修改传递参数的初值 const char *F2();//意义是函数返回的指针指向的对象是一个const对象,它必须赋给一个同样是指向const对象的指针 const char * const F3(); //比上面多了一个const,这个const的意义只是在他被用作左值时有效,它表明了这个指针除了指向const对象外,它本身也不能被修改,所以就不能当作左值来处理。 五、对于类 1.首先,对于const的成员变量,只能在构造函数里使用初始化成员列表来初始化,试图在构造函数体内进行初始化const成员变量会引起编译错误。初始化成员列表形如:X:: X ( int ir ): r(ir) {} //假设r是类X的const成员变量 注意:类的构造和析构函数都不能是const函数。 2.建立了一个const成员函数,但仍然想用这个函数改变对象内部的数据。(函数不能修改类的数据成员)

C++中const用法详解

const是一个C语言的关键字,它限定一个变量不允许被改变。使用const在一定程度上可以提高程序的安全性和可靠性。类型声明中const用来修饰一个常量,有如下两种写法,那么,请问,下面分别用const限定不可变的内容是什么? 1)、const在前面 const int nValue;//nValue是const const char *pContent; //*pContent是const, pContent可变 const (char *) pContent;//pContent是const,*pContent可变 char* const pContent; //pContent是const,*pContent可变 const char* const pContent; //pContent和*pContent都是const 2)、const在后面,与上面的声明对等 int const nValue;// nValue是const char const * pContent;// *pContent是const, pContent可变 (char *) const pContent;//pContent是const,*pContent可变 char* const pContent;// pContent是const,*pContent可变 char const* const pContent;// pContent和*pContent都是const 答案与分析: const和指针一起使用是C语言中一个很常见的困惑之处,在实际开发中,特别是在看别人代码的时候,常常会因为这样而不好判断作者的意图,下面讲一下我的判断原则:当const所在代码段中不包含括号时,沿着*号划一条线,如果const 位于*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于*的右侧,const就是修饰指针本身,即指针本身是常量。你可以根据这个规则来看上面声明的实际意义,相信定会一目了然。

.net高级工程师面试题

.net软件工程师面试题 基础题: 1.简述string[]、ArrayList、List的区别。 数组: 优点: o数组在内存中是连续存储的,索引速度非常快; o赋值和修改元素也很简单; 不足: o两个数据之间插入数据比较麻烦; o声明数组的时候,必须指明数组的长度,数组长度过长会造成内存浪费,数组的长度过短,会造成数据溢出错误。 ArrayList: 优点: https://www.sodocs.net/doc/5f12862886.html, framework 提供的用于数据存储和检索的专用类 o大小依据存储的数据来动态扩展和收缩 o继承IList,可以方便的进行数据的添加、插入和删除 缺点: o允许插入不同类型的数据,都当做object类型处理 o数据处理时可能出现类型不匹配的错误

o存在装箱(值=》引用)拆箱的操作,会带来很大的性能损耗 List: 优点: o声明List集合时,需要声明集合内数据的对象类型 o避免了类型安全问题和装箱拆箱的性能问题 2.简述装箱和拆箱操作中的性能损耗是如何产生的。 3.简述对https://www.sodocs.net/doc/5f12862886.html,中的事件机制的理解。 4.在一个https://www.sodocs.net/doc/5f12862886.html,的三层结构系统中,以登录操作为例,简述在各层中如何组织代码。 5.简述相比DATASET,实体类在WEB项目中的优点与缺点。 6.简述GC是如何工作的。 Java采用VM(Virtual Machine)机制,由VM来管理程序的运行当然也包括对GC管理。90年代末期.NET出现了,.NET采用了和Java类似的方法由CLR(Common Language Runtime)来管理。 Garbage Collector(垃圾收集器,在不至于混淆的情况下也成为GC)以应用程序的root 为基础,遍历应用程序在Heap上动态分配的所有对象[2],通过识别它们是否被引用来确定哪些对象是已经死亡的、哪些仍需要被使用。已经不再被应用程序的root或者别的对象所引用的对象就是已经死亡的对象,即所谓的垃圾,需要被回收。这就是GC工作的原理。为了实现这个原理,GC有多种算法。比较常见的算法有Reference Counting,Mark Sweep,Copy Collection等等。目前主流的虚拟系统.NET CLR,Java VM和Rotor都是采用的Mark Sweep算法。

一般疑问句、选择疑问句的详细用法备课讲稿

一般疑问句、选择疑问句的详细用法

一般疑问句、 (一)一般疑问句 1、一般疑问句概述 一般疑问句(general questions),也可称为“yes/no” questions(是否型问句),因为它一般是由yes或no回答的,如: —Can you swim to the other side?你能游到对岸吗? —Yes, I can.是的,我能。 —No,I can’t.不,我不能。 —Have you locked the door?你锁门了吗? —Yes,I have.是的,锁了。 —No,I haven’t. 不,没有锁。 2一般疑问句的结构 (1)基本的结构为:be/助动词/情态动词+主语+谓语/表语+(其他),句子要读升调,如: Are they your friends?他们是你的朋友吗? Does he go to school on foot?他是步行去上学吗? Will you be free tonight?你今晚有空吗? Can you play basketball?你会打篮球吗? (2)陈述句亦可用作一般疑问句,多用在非正式文体中,句末有问号,用升调,如: Somebody is with you?有人和你一起吗? He didn’t finish the work?他没有做完活吗? You are fresh from America,I suppose?我猜,你刚从美国回来吧? 3、一般疑问句的答语 (1)一般疑问句一般由yes或no来回答,如: —Are you tired?你累了吗? —Yes,I am.是的,累了。 —No, I’m not.不,不累。 —Does she do the cleaning?她扫除了吗?

const和readonly区别

我们都知道,const和static readonly的确很像:通过类名而不是对象名进行访问,在程序中只读等等。在多数情况下可以混用。二者本质的区别在于,const的值是在编译期间确定的,因此只能在声明时通过常量表达式指定其值。而static readonly是在运行时计算出其值的,所以还可以通过静态构造函数来赋值。明白了这个本质区别,我们就不难看出下面的语句中static readonly和const能否互换了: 1. static readonly MyClass myins = new MyClass(); 2. static readonly MyClass myins = null; 3. static readonly B = 10; static readonly A = B * 20; 4. static readonly int [] constIntArray = new int[] {1, 2, 3}; 5. void SomeFunction() { const int a = 10; ... } 6.private static string astr="abcd"; private const string str = astr+"efg"; 1:不可以换成const。new操作符是需要执行构造函数的,所以无法在编译期间确定 2:可以换成const。我们也看到,Reference类型的常量(除了String)只能是Null。 3:可以换成const。我们可以在编译期间很明确的说,A等于200。 4:不可以换成const。道理和1是一样的,虽然看起来1,2,3的数组的确就是一个常量。5:不可以换成readonly,readonly只能用来修饰类的field,不能修饰局部变量,也不能修饰property等其他类成员。 6.错误:如果在astr前加上const或者const改为readonly即可; 总结:1.const、readonly和static readonly定义的常量,指定初始值后(包括在构造函数内指定的初始值) 将不可更改,可读不可写; 2.const定义时必须指定初始值,而readonly定义时可以不进行初始化(MS建议在定义时初始值),同时也可以在构造函数内指定初始值, 并以构造函数内指定的值为准; 3.const和static readonly定义的常量是静态的,只能由类直接访问;而readonly定义的常量是非静态的,只能由实例对象访问; 4.static readonly常量,如果在构造函数内指定初始值,则必须是静态无参构造函数; 5.const是编译时常量,readonly是运行时常量;cosnt较高效,readonly较灵活。在应用上以static readonly代替const,以平衡const在灵活性上的不足, 同时克服编译器优化cosnt性能,所带来的程序集引用不一致问题; 文章2:

const变量使用总结

或许还有不少人对于const修饰符理解的并不深刻,都只是停留在一个比较浅的层面上,仅仅是在读别人代码的时候看到了const修饰符的使用,自己的写代码的过中从未使用过,所以自然对于const修饰符比较陌生。那么到底什么是const 修饰符,我们在自己编写C语言代码的过程中又该如何有效的使用const修饰符呢,现在让我们来学习下const修饰符的使用。 const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,即就是说其所修饰的对象为常量。当你代码中想要设法阻止一个变量被改变,那么这个时候可以选择使用const关键字。在你给一个变量加上const修饰符的同时,通常需要对它进行初始化,在之后的程序中就不能再去改变它。 可能有的人会有一个疑问,我们不是有在C中有预处理指令#define VariableNameVariableValue可以很方便地进行值替代,干嘛还要引入const修饰符呢?!这是因为预处理语句虽然可以很方便的进行值得替代,但它有个比较致命的缺点,即预处理语句仅仅只是简单值替代,缺乏类型的检测机制。这样预处理语句就不能享受C编译器严格类型检查的好处,正是由于这样,使得它的使用存在着一系列的隐患和局限性。 在讲解const修饰符之前,我们在此首先给出const修饰符的几个典型作用: 1. const类型定义:指明变量或对象的值是不能被更新,引入目的是为了取代预编译指令 2. 可以保护被修饰的东西,防止意外的修改,增强程序的健壮性; 3. 编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。 4. 可以节省空间,避免不必要的内存分配。 接下来看看具体的使用。 一、const修饰符在函数体内修饰局部变量。 constint n=5; 和 intconst n=5;

C基础知识25个常见问题

C# 基础知识 25个常见问题(1) 2007-04-12 16:53 当初学 C# 时是找个人大概问了一下数据类型和分支语句就开始做项目了。这两天又全面的看了一下相关的基础知识(学而时习之嘛),总结了25个问题: 1.静态变量和非静态变量的区别? 2.const 和 static readonly 区别? 3.extern 是什么意思? 4.abstract 是什么意思? 5.internal 修饰符起什么作用? 6.sealed 修饰符是干什么的? 7.override 和 overload 的区别? 8.什么是索引指示器? 9.new 修饰符是起什么作用? 10.this 关键字的含义? 11.可以使用抽象函数重写基类中的虚函数吗? 12.密封类可以有虚函数吗? 13.如果基类中的虚属性只有一个属性访问器,那么继承类重写该属性后可以有几个属性访问器?如果基类中有 get 和 set 两个呢? 14.abstract 可以和 virtual 一起使用吗?可以和 override 一起使用吗? 15.接口可以包含哪些成员? 16.类和结构的区别? 17.接口的多继承会带来哪些问题? 18.抽象类和接口的区别? 19.别名指示符是什么? 20.如何释放非托管资源? 21.P/Invoke是什么? 22.StringBuilder 和 String 的区别? 23.explicit 和 implicit 的含义? 24.params 有什么用? 25.什么是反射? 以下是我做的一份参考答案(C# 语言范畴之内),如果有不准确、不全面的,欢迎各位朋友指正! 1.静态变量和非静态变量的区别? 答:静态变量: 静态变量使用 static 修饰符进行声明 在所属类被装载时创建 通过类进行访问

特殊疑问句和一般疑问句的用法

(一)由be(am,is,are)引导的一般疑问句 1、Am I a student? 我是学生吗? Yes,you are./ No,you aren’t. 2、Is this /that/it a chair?这/那/它/是一把椅子吗? Yes,it is. /No,it isn’t. 3、Is she/Amy your sister?她/艾米是你的妹妹吗?Yes,she is ./ No,she isn’t. 4、Is he/Mike your brother?他/迈克是你的哥哥吗?Yes,he is./No,he isn’t. 5、Is your brother helpful at home? 你哥哥在家有用吗?Yes, he is./ No, he isn’t. 6、Is there a forest in the park? 在公园有一个森林吗? Yes,there is./No,there isn’t. 是的,有。/不,没有。 7、Are there any panda s in the mountains?在山上有熊猫吗? Yes,there are./No,there aren’t.是的,有。/不,没有。 8、Are they dusk s? 它们是鸭子吗?(问物) Yes, they are. /No,they aren’t.是的,它们是。/不,它们不是。 9、Are they famers? 他们是农民吗?(问人) Yes, they are. /No,they aren’t. 是的,他们是。/不,他们不是。 10、Are you a teacher?你是一个老师吗?(问you 用I回答) Yes, I am./No,I’m not.是的,我是。/不,我不是。 11、Are you teacher s?你们是老师吗? Yes,we are./No,we aren’t.是的,我们是。/不,我们不是。 (二)、由do引导的一般疑问句

否定疑问句的构成和用法

否定疑问句的构成和用法 反意疑问句是在陈述句后边加上一个简短问句,对陈述句所叙述的内容提出相反的疑问,这种句子就叫作反意疑问句。反意疑问句可以表示真实的疑问,也可以表示提问人的倾向、强调或反问。如果陈述句是肯定句时,后边的反意疑问句通常要用否定式;反之,如果陈述句是否定句时,后边的反意疑问句通常要用肯定式。陈述句和后边的反意疑问句的主语以及谓语动词的人称、数、时态通常要保持一致。例如: He speaks English, doesn't he? Mary won't do it, will she? Lies cannot cover up the facts, can they? 回答反意疑问句和回答一般疑问句一样,肯定回答用"Yes, +肯定结构";否定回答用"No, +否定结构"。这与汉语习惯有所不同。例如: -He's a doctor, isn't he?他是医生,对吧? -Yes, he is.对,他是医生。(No, he isn't.不,他不是医生。) -He isn't a doctor, is he?他不是医生,对吧? -Yes, he is.不,他是医生。(No, he isn't.对,他不是医生。) 在使用反意疑问句时,特别要注意以下几点: 1.当动词have作"有"讲时,可以有两种反意疑问句形式。例如: He hasn't any sisters, has he? He doesn't have any sisters, does he? 当have表示其它含义(如:经历、遭受、得到、吃……)讲时,只有一种反意疑问句形式: You all had a good time, didn't you? He often has colds, doesn't he? They had milk and bread for breakfast, didn't they? 2.如果陈述句的谓语动词含有have to, had to时,反意疑问句通常用其适当形式。例如: We have to get there at 8 a.m. tomorrow, don't we? They had to take the early train, didn't they? 3. need和dare既可以作情态动词,又可以作实义动词,注意有两种反意疑问句形式。例如: You needn't hand in your paper today, need you? You don't need to hand in your paper today, do you? He dare ask the teacher, dare not he? He doesn't dare to ask the teacher, does he? 4.如果陈述句的谓语动词含有used to时,也可以有两种反意疑问句形式。例如: He used to live in London, usedn't/ didn't he? 5.如果陈述句中出现never, seldom, hardly, scarcely, rarely, few, little, nobody, no one, nothing等含有否定意义的词时,反意疑问句通常要用肯定式。例如: She seldom goes to the concert, does she? He has few good reasons for staying, has he? 6.如果陈述句中的主语是不定式短语、动名词短语、从句、everything或nothing时,反意疑问句通常要用it作主语。例如: To sell/ Selling newspaper was his job, wasn't it? What he said is true, isn't it? Everything is all right, isn't it? 7.如果陈述句中的主语是不定代词everybody, everyone, somebody, someone, nobody, no one, each of等时,反意疑问句通常要用they或he作主语。例如: Somebody borrowed my bike, didn't they/ he? Each of them passed the exam, didn't they?

C++ const 精髓

1.const的用法: 看到const 关键字,C++程序员首先想到的可能是const 常量。这可不是良好的条件反射。如果只知道用const 定义常量,那么相当于把火药仅用于制作鞭炮。const 更大的魅力是它可以修饰函数的参数、返回值,甚至函数的定义体。 const 是constant 的缩写,“恒定不变”的意思。被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。所以很多C++程序设计书籍建议:“Use const whenever you need”。 1.用const 修饰函数的参数 如果参数作输出用,不论它是什么数据类型,也不论它采用“指针传递”还是“引用传递”,都不能加const 修饰,否则该参数将失去输出功能。const 只能修饰输入参数: 如果输入参数采用“指针传递”,那么加const 修饰可以防止意外地改动该指针,起到保护作用。 例如StringCopy 函数: void StringCopy(char *strDestination, const char *strSource); 其中strSource 是输入参数,strDestination 是输出参数。给strSource 加上const修饰后,如果函数体内的语句试图改动strSource 的内容,编译器将指出错误。 如果输入参数采用“值传递”,由于函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护,所以不要加const 修饰。 例如不要将函数void Func1(int x) 写成void Func1(const int x)。 同理不要将函数void Func2(A a) 写成void Func2(const A a)。其中A 为用户自定义的数据类型。 对于非内部数据类型的参数而言,象void Func(A a) 这样声明的函数注定效率比较底。因为函数体内将产生A 类型的临时对象用于复制参数a,而临时对象的构造、复制、析构过程都将消耗时间。 为了提高效率,可以将函数声明改为void Func(A &a),因为“引用传递”仅借用一下参数的别名而已,不需要产生临时对象。但是函数void Func(A & a) 存在一个缺点: “引用传递”有可能改变参数a,这是我们不期望的。解决这个问题很容易,加const修饰即可,因此函数最终成为void Func(const A &a)。 以此类推,是否应将void Func(int x) 改写为void Func(const int &x),以便提高效率?完全没有必要,因为内部数据类型的参数不存在构造、析构的过程,而复制也非常快,“值传递”和“引用传递”的效率几乎相当。 问题是如此的缠绵,我只好将“const &”修饰输入参数的用法总结一下。 对于非内部数据类型的输入参数,应该将“值传递”的方式改为“const 引用传递”,目的是提高效率。例如将void Func(A a) 改为void Func(const A &a)。 对于内部数据类型的输入参数,不要将“值传递”的方式改为“const 引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x) 不应该改为void Func(const int &x)。

const的使用方法

const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,意即其所修饰的对象为常量(immutable)。 1、函数体内修饰局部变量。 例: void func(){ const int a=0; } 首先,我们先把const这个单词忽略不看,那么a是一个int类型的局部自动变量,我们给它赋予初始值0。 然后再看const. const作为一个类型限定词,和int有相同的地位。 const int a; int const a; 是等价的。于是此处我们一定要清晰的明白,const修饰的对象是谁,是a,和int没有关系。const 要求他所修饰的对象为常量,不可被改变,不可被赋值,不可作为左值(l-value)。 这样的写法也是错误的。 const int a; a=0; 这是一个很常见的使用方式: const double pi=3.14; 在程序的后面如果企图对pi再次赋值或者修改就会出错。 然后看一个稍微复杂的例子。 const int* p; 还是先去掉const 修饰符号。 注意,下面两个是等价的。 int* p; int *p; 其实我们想要说的是,*p是int类型。那么显然,p就是指向int的指针。 同理 const int* p; 其实等价于

const int (*p); int const (*p); 即,*p是常量。也就是说,p指向的数据是常量。 于是 p+=8; //合法 *p=3; //非法,p指向的数据是常量。 那么如何声明一个自身是常量指针呢?方法是让const尽可能的靠近p; int* const p; const右面只有p,显然,它修饰的是p,说明p不可被更改。然后把const去掉,可以看出p是一个指向int形式变量的指针。 于是 p+=8; //非法 *p=3; //合法 再看一个更复杂的例子,它是上面二者的综合 const int* const p; 说明p自己是常量,且p指向的变量也是常量。 于是 p+=8; //非法 *p=3; //非法 const 还有一个作用就是用于修饰常量静态字符串。 例如: const char* name="David"; 如果没有const,我们可能会在后面有意无意的写name[4]='x'这样的语句,这样会导致对只读内存区域的赋值,然后程序会立刻异常终止。有了const,这个错误就 能在程序被编译的时候就立即检查出来,这就是const的好处。让逻辑错误在编译 期被发现。 const 还可以用来修饰数组 const char s[]="David"; 与上面有类似的作用。 2、在函数声明时修饰参数 来看实际中的一个例子。 NAME

const的所有用法——Dan+Saks

In my last column, I discussed one of the reasons why the rules by which a compiler can place data into ROM are a bit more complicated in C++ than they are in C.1I have more to say about that subject, but before I do, I’d like to reply to the following query I received through e-mail from Phil Baurer at Komatsu Mining Systems: “We’re having an interesting prob-lem using const with a typedef. I hoped you could comment on this sit-uation. I am wondering if we are bumping into some unknown (by us) rule of the C language. “We are using the Hitachi C com-piler for the Hitachi SH-2 32-bit RISC microcontroller. We thought the fol-lowing code: t y p e d e f v o i d*V P; c o ns t V P v e c t o r T a b l e[] ={....};(1) should be identical to: c o ns t v o i d*v e c t o r T a b l e[] ={....};(2)“However, the linker places v e c t o r T a b l e in (1) into the C O N S T A N T section, but it places v e c t o r T a b l e in (2) into the D A T A section. “Is this the proper behavior or a bug in the compiler?” This is proper behavior; it is not a bug. You are indeed bumping into some rules of the C language that you apparently don’t know about. Don’t feel bad; you’re not alone. I believe many other C and C++ pro- grammers are confused about these rules, which is why I’m answering this in my column. I presented some of these rules in an earlier column.2However, in look- ing back at that column, I don’t think I emphasized strongly enough the points which seem to be the source of your confusion. So let me try again. Declarat ors Here’s the first insight: Every declaration in C and C++ has two principal parts: a sequence of zero or more declaration specifiers, and a sequence of one or more declarators, separated by commas. For example: A declarator is the name being declared, possibly surrounded by operators such as *, [], (), and (in the case of C++) &. As you already know, the symbol *in a declarator means “pointer to” and []means “array of.” Thus, *x[N]is a declarator indicating that x is an “array of N elements of pointer to ...” something, where that something is the type specified in the declaration specifiers. For example, s t a t i c u ns i g ne d l o ng i nt*x[N]; declares x as an object of type “array of N elements of pointer to unsigned long int.” (As explained later, the key- word s t a t i c does not contribute to the type.) How did I know that *x[N]is an “array of ... pointer to ...” rather than a “pointer to an array of ...?” It follows from this rule: The operators in a declarator group accord- ing to the same precedence as they do when they appear in an expression. For example, if you check the near- est precedence chart for either C or C++, you’ll see that []has higher precedence than *. Thus the declara- tor *x[N]means that x is an array before it’s a pointer. Parentheses serve two roles in declarators: first, as the function call operator, and second, as grouping. As the function call operator, ()have the same precedence as []. As grouping, ()have the highest precedence of all. Embedded Systems Programming FEBRUARY 1999 13 Dan Saks const T vs.T const Although C and C++ read mostly from top-to- bottom and left-to-right, pointer declarations read, in a sense, backwards.

相关主题