tag 标签: const

相关博文
  • 热度 15
    2016-3-15 21:05
    1564 次阅读|
    1 个评论
    被const修饰的变量不可被修改,因此它必须在定义时被初始化。 被const修饰的变量,能进行的操作是它的值不被修改的操作。 被const修饰的变量属于本地,两个文件中的同名const变量是两个独立的变量。 如果需要在多个文件中使用同一个const变量,则: // file_1.cc extern const int bufSize = fcn(); // file_1.h extern const int bufSize; 被const修饰的变量的引用也必须被const修饰: const int ci = 1024; const int r1 = ci; 不被const修饰的变量以及常量,也可以为被const修饰的引用赋值: int i = 42; const int r1 = i; const int r2 = 42; 但是常量不可为不被const修饰的引用赋值。 被const修饰的引用,它的对象可以是其他的数据类型,因为编译器会创建临时变量。 不被const修饰的引用,它的对象不可以是其他的数据类型,因为对临时变量的操作无意义。 指针和引用类似: const double pi = 3.14; const double *cptr = π double dval = 6.28; cptr = dval; 这里被const修饰的指针,是说它的对象不可被此指针修改。 我们不能通过const指针对修改它指向的object,但object本身可以通过其他途径更改。 如果我们希望指针本身不可被修改呢? int errNumb = 0; int *const curErr = errNumb; const double pi = 3.1415926; const double *const pip = π 指针本身不可被修改,称为top-level const; 指针指向的对象不可被修改,称为low-level const。 使用const修饰变量时,仔细考虑对象可否被修改,指针和引用可否被修改。 语法很重要,更重要的是理解客观世界的逻辑。 什么是常量表达式constant expression? 在编译时可以确定值的表达式,称为常量表达式。 const int max_files = 20; const int limit = max_files + 1; int staff_size = 24; const int sz = get_size(); 上面四个表达式,是常量表达式吗? 是,是,否,否。 怎么显式的定义常量表达式? constexpr int mf = 20; constexpr int limit = mf + 1; constexpr int sz = size(); 如果使用了constexpr修饰,编译器就会检查值是否能够在编译时确定。 const int *p = nullptr;        // p是指向const int的指针 constexpr int *q = nullptr;    // q是指向int的const指针 因此constexpr是top-level const的意思。 需要使用top-level const的时候,就使用constexpr吧,这样含义更清晰。
  • 热度 24
    2015-3-13 14:13
    1189 次阅读|
    3 个评论
    C语言中的const一直是C语言初学者心中的痛,这是因为const在不同位置有不同作用,在不同情景有不同角色。这让初学者摸不清头脑。今天,和大家一起研究一下const,让它的每个角色都“深入人心”! ============================================================================================== 情景一:最简单的const用法   #include int main ( ) { int const a ; a = 5 ; printf ( "a=%d \n " , a ) ; return 0 ; } 如果编译这个c文件,就会报错: 1071.c: In function ‘main’: 1071.c:5: error: assignment of read-only variable ‘a’ 显而易见,这是const在搞鬼,因为声明了const的变量是不能修改的! 如果将源代码修改为如下这样,就没有问题了! #include int main ( ) { int const a = 5 ; printf ( "a=%d \n " , a ) ; return 0 ; } 总结:const声明的变量必须要进行初始化赋值,如果错过这个机会,以后再想给const的变量赋值,可就没门了!切记~ PS:int const和const int是一回事,“颠倒写”都是可以的。以后遇到了别犯晕,呵呵。但是,还是要留个心眼,当const和指针搀和到一起时,这个“颠倒写”的规律可未必成立。 ============================================================================================== 情景二:发明const为了什么? 在const诞生之前,开发者一直使用#define VAR 100来定义一些有特殊用途的类常量,不过这样定义是存在一些劣势的。因此const应运而生,之后开发者可以使用const int VAR=100;来定义类常量了。 至于为什么#define有其劣势,还要读者自己去google下。:) ============================================================================================== 情景三:const和指针的配合是噩梦! 你能分辨得清这些声明么: const int * A ; int const * A ; int * const A ; const int * const A ; 如果有点犯晕的话,那就先给出它们的讲解,然后继续看后面的情景分析吧。 const int *A; //修饰指向的对象,A可变,A指向的对象不可变 int const *A;   //修饰指向的对象,A可变,A指向的对象不可变 int *const A;   //修饰指针A, A不可变,A指向的对象可变 const int *const A; //指针A和A指向的对象都不可变 ============================================================================================== 情景四:const int *A $ cat test1.c #include int main ( ) { int num = 12 ; const int * A = # printf ( "result=%d \n " ,* A ) ; return 0 ; } 编译执行结果为: $ cc test1.c $ ./a.out result=12 接下来,我们动动手脚,在代码中加入了(*A)++;这条语句: $ cat test1.c #include int main ( ) { int num = 12 ; const int * A = # ( * A ) ++; printf ( "result=%d \n " ,* A ) ; return 0 ; } 编译这个c文件: $ !cc cc test1.c test1.c: In function ‘main’: test1.c:6: error: increment of read-only location ‘*A’ 可以看到,报错了,报错的内容表示”*A”是只读的,不能修改。 我们再修改一下源代码为下面这样: $ cat test1.c #include int main ( ) { int num = 12 ; int tmp = 100 ; const int * A = # A = amp ; tmp ; printf ( "result=%d \n " ,* A ) ; return 0 ; } 编译执行结果为: $ !cc cc test1.c $ ./a.out result=100 好了,如果你仔细看了这几个小得不能再小的程序,你自己都可以给出结论了! 结论:如果声明了const int *A,那么A值是可以修改的,而*A是不可以修改的。更通俗的说,A指针可以随便指向一个整型,但只要被A盯上了的整型变量在使用*A引用时就不能修改了。 $ cat test1.c #include int main ( ) { int num = 12 ; int tmp = 100 ; const int * A = # A = amp ; tmp ; tmp = 3 ; printf ( "result=%d \n " ,* A ) ; return 0 ; } 编译执行的结果为: $ !cc cc test1.c $ ./a.out result=3 结论2:即使A指向了tmp,我虽然不能修改*A,但是我仍然是可以用tmp来修改这个值的,完全不管*A的存在。呵呵 ============================================================================================== 情景五:int *const A $ cat test1.c #include int main ( ) { int num = 12 ; int * const A = # printf ( "result=%d \n " ,* A ) ; return 0 ; } 编译执行结果为: $ !cc cc test1.c $ ./a.out result=12 我们稍微修改下源代码: $ cat test1.c #include int main ( ) { int num = 12 ; int tmp = 100 ; int * const A = # A = amp ; tmp ; printf ( "result=%d \n " ,* A ) ; return 0 ; } 编译时报错了: $ !cc cc test1.c test1.c: In function ‘main’: test1.c:7: error: assignment of read-only variable ‘A’ $ cat test1.c 可见A本身的值已经不能再变了。 继续修改源代码如下: $ cat test1.c #include int main ( ) { int num = 12 ; int * const A = # ( * A ) = 100 ; printf ( "result=%d \n " ,* A ) ; return 0 ; } 编译执行结果为: $ !cc cc test1.c $ ./a.out result=100 可以看出,(*A)是可以改变的。 结论又可以轻易推出了:int *const A;   //const修饰指针A, A不可变,A指向的对象可变 ============================================================================================== 情景六:const int *const A; //指针A和A指向的对象都不可变 $ cat test1.c #include int main ( ) { int num = 12 ; int const * const A = # ( * A ) = 100 ; printf ( "result=%d \n " ,* A ) ; return 0 ; } 编译会报错: $ !cc cc test1.c test1.c: In function ‘main’: test1.c:6: error: assignment of read-only location ‘*A’ 改下源代码: $ cat test1.c #include int main ( ) { int num = 12 ; int tmp = 100 ; int const * const A = # A = amp ; tmp ; printf ( "result=%d \n " ,* A ) ; return 0 ; } 编译仍然会报错: $ !cc cc test1.c test1.c: In function ‘main’: test1.c:7: error: assignment of read-only variable ‘A’ 呵呵,结论很明显了,const int *const A; //指针A和A指向的对象都不可变 当然const int *const A;和int const *const A=num;是等价的! 情景七:如果const用在函数形参里呢?是不是又要复杂很多? 答案是NO!一点也不复杂。 来看看这个函数头:int addnum(const int num, int a, int b); 这个函数声明中的第一个形参是const int num,这就表明如果我调用了这个函数,那么第一个实参被传到addnum函数里之后,就不能再做修改了!呵呵 就这么简单。 给个例子吧,让大家能更一目了然: $ cat test2.c #include int addto ( const int num , int a , int b ) { if ( num == 1 ) { return a + b ; } else { return 0 ; } }   int main ( ) { int num = 100 ; int a = 12 , b = 22 ; int res ; num = 1 ; res = addto ( num , a , b ) ; printf ( "res=%d \n " , res ) ; return 0 ; } 编译执行结果为: $ !cc cc test2.c $ ./a.out res=34 如果我修改一下,编译就会出错: $ cat test2.c #include int addto ( const int num , int a , int b ) { if ( num == 1 ) { num = 3 ; return a + b ; } else { return 0 ; } }   int main ( ) { int num = 100 ; int a = 12 , b = 22 ; int res ; num = 1 ; res = addto ( num , a , b ) ; printf ( "res=%d \n " , res ) ; return 0 ; } 编译报错为: $ !cc cc test2.c test2.c: In function ‘addto’: test2.c:5: error: assignment of read-only location ‘num’ 可见在函数里形参被声明为const的变量也是不能修改的哦!呵呵~ const其实不难,把本文的几个小例子看懂就OK了!
相关资源
  • 所需E币: 3
    时间: 2019-12-25 03:29
    大小: 81.51KB
    上传者: 微风DS
    c语言中const的用法关于CONST的用法const在C语言中算是一个比较新的描述符,我们称之为常量修饰符,意即其所修饰的对象为常量(immutable)。我们来分情况看语法上它该如何被使用。1.函数体内修饰局部变量。例:voidfunc(){constinta=0;}首先,我们先把const这个单词忽略不看,那么a是一个int类型的局部自动变量,我们给它赋予初始值0。然后再看const.const作为一个类型限定词,和int有相同的地位constinta;intconsta;是等价的。于是此处我们一定要清晰的明白,const修饰的对象是谁,是a,和int没有关系。const要求他所修饰的对象为常量,不可被改变,不可被赋值,不可作为左值(l-value)。这样的写法也是错误的。constinta;a=0;这是一个很常见的使用方式:constdoublepi=3.14;在程序的后面如果企图对pi再次赋值或者修改就会出错。然后看一个稍微复杂的例子。constint*p;还是先去掉const修饰符号。注意,下面两个是等价的。int*p;int*p;其实我们想要说的是,*p是int类型。那么显然,p就是指向int的指针。同理constint*p;其实等价于constint(*p);intconst(*p);即,*p是常量。也就是说,p指向的数据是常量。于是p+=8;//合法……
  • 所需E币: 3
    时间: 2020-1-15 09:50
    大小: 158.51KB
    上传者: 二不过三
    001global_time_const_2003GlobalTimingConstraintsPDFcreatedwithpdfFactoryProtrialversionwww.pdffactory.comOutlineIntroductionGlobalConstraintsTheConstraintsEditorSummaryPDFcreatedwithpdfFactoryProtrialversionwww.pdffactory.comTimingConstraintsandYourProjectWhateffectsdotimingconstraintshaveonyourproject?Theimplementationtoolsdonotattempttofindtheplace&routethatwillobtainthebestspeed……