const, volatile同时修饰一个变量

文章基础:

       (1) “编译器一般不为const变量分配内存,而是将它保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作。”      

       (2) volatile的作用是“告诉编译器,i是随时可能发生变化的,每次使用它的时候必须从内存中取出i的值”。

                                                                                                                                          — —《c语言深度解剖》

一,const, volatile含义

(1)const含义是“请做为常量使用”,而并非“放心吧,那肯定是个常量”。
(2)volatile的含义是“请不要做自以为是的优化,这个值可能变掉的”,而并非“你可以修改这个值”。


二,const, volatile的作用以及起作用的阶段

(1)const只在编译期有用,在运行期无用

          const在编译期保证在C的“源代码”里面,没有对其修饰的变量进行修改的地方(如有则报错,编译不通过),而运行期该变量的值是否被改变则不受const的限制。

(2) volatile在编译期和运行期都有用

         在编译期告诉编译器:请不要做自以为是的优化,这个变量的值可能会变掉;

         在运行期:每次用到该变量的值,都从内存中取该变量的值。


补充:编译期 -- C编译器将源代码转化为汇编,再转化为机器码的过程;运行期 -- 机器码在CPU中执行的过程。


三,const, volatile同时修饰一个变量

(1)合法性

          “volatile”的含义并非是“non-const”,volatile 和 const 不构成反义词,所以可以放一起修饰一个变量。

(2)同时修饰一个变量的含义

         表示一个变量在程序编译期不能被修改且不能被优化;在程序运行期,变量值可修改,但每次用到该变量的值都要从内存中读取,以防止意外错误。

展开阅读全文

const/volatile修饰标识符的进一步论证

05-12

const int *p = NULL; 相当于 int const *p = NULL;rn下面要写一对与上面一对表达式更清晰的陈述:rnrnconst int (*p) = NULL; 相当于 int const (*p) = NULL;rnrn这样其实比起第一对看起来更加清晰。const修饰(*p),即限定p指针所指地址内容的值。rnrn再看下面:rnrnint * const p = NULL;rnrn更清晰地表述为:int (* const p) = NULL;rnrn这样,很明显可以看到const修饰标识符p,即限定p指针的值。rnrn要注意的是没有int (const * p) = NULL;这样的语法。rn因为这样一来,对int的修饰会产生冲突。由于const *p对于C/C++而言本身就是一个合法的正则表达式语句。const *p = NULL; 完全OK,这时p作为int const*类型。rnrn利用括号对指针类型进行限定是比较有用的分析技巧。rnrn比如说以下情况:rnrntypedef int ARRAY[10];rnrnvoid main(void)rnrn ARRAY *p; // p是什么类型?rnrnrn那么对于类型定义情况,我们公司很多程序员都搞不清楚。尤其像以上这种情况。rn加个括号看看:ARRAY (*p);rnrn分析:由于ARRAY是int[10]类型,将它代入就成为:int[10] (*p);rn调整一下:int (*p)[10]; 所以比较自然地得出了p的类型为:int(*)[10]。rnrn指针标记*与标识符靠拢时总是与标识符进行一同规归约。rnrntypedef const int CINT;rnrnCINT *p = NULL; // p是什么类型?rnrn同样地,加括号:CINT (*p) = NULL; 就和const int (*p)一样了。rnrntypedef int* PINT;rnrnPINT const p = NULL; // p是什么类型?rnrn同样地,加括号,不过这里实际上没什么必要了,因为p作为一个单独的标识符没有指针对它进行修饰。const PINT (p) = NULL; 由于PINT为(int*)类型,因此这里的const就是对标识符p作修饰,由于p已经为(int*),因此p的类型为int* const。rnrn若为:PINT const (*p) = NULL;那么p类型为:int* const *。第一个int*是由PINT得到的。rnrn若是:PINT (* const p) = NULL; 那么p类型为int* * const 论坛

const 修饰函数参数的问题!!!!!!!!

03-17

昨天发了一个问题“很多字符串函数比如strcpy,strncpy,memcpy,等,都有rn"src和dest所指内存区域不能重叠"”rn[url=http://topic.csdn.net/u/20090316/00/6785c648-64a0-4499-85a4-c7b95c932869.html]http://topic.csdn.net/u/20090316/00/6785c648-64a0-4499-85a4-c7b95c932869.html[/url]rn好像这些函数的源代码都没有对重叠进行处理!!??rn但是现在好多人自己重写这些函数都用const 修饰函数参数就是const char* src,防止意外改动,起到保护作用!!rn但是下面这个代码src所向的内容变了,但是编译为什么没有指出错误??(gcc 版本 4.1.2 20070925 (Red Hat 4.1.2-27)rn[code=C/C++]#include rn#include rn#include rnrnrnchar * my_memmove(char * dst,const char* src,int count)rnrnrn char* ret = dst;rnrn if (dst <= src || (char *)dst >= ((char *)src + count))rnrn rnrn while (count--)rnrn rnrn *(char *)dst = *(char *)src;rnrn dst = (char *)dst + 1;rnrn src = (char *)src + 1;rnrn rnrn rnrn elsernrn rnrn dst = (char *)dst + count - 1;rnrn src = (char *)src + count - 1;rnrn while (count--)rnrn rnrn *(char *)dst = *(char *)src;rnrn dst = (char *)dst - 1;rnrn src = (char *)src - 1;rnrn rnrn rn printf("%s",src);rn return(ret);rnrnint main(int argc,char *argv[])rnrn int i;rn unsigned char a[10];rn for(i = 0;i < 10;i++)rn rn a[i] = i;rn rn my_memmove(a, &a[4],sizeof(unsigned char)*6);rn printf("\n------my_memmove--------");rn for(i = 0;i < 10;i++)rn printf("%d",a[i]);rnrn return 0;rnrn[/code] 论坛

固执的const与易变的volatile

10-31

对于const与volatile这两个关键字可能在一些简单的C语言应用中比较少见,但是在实际的项目应用中这两个关键字身影却随处可见。下面我们就这两个关键进行讨论。rn1,const 可能大家见到这个关键字会想到常量,即认为经过const声明的变量将会常量化,遗憾的是这又是一种错误的观点(注意:对于const的讨论限于C语言,在C++中const将会有新的意义,感兴趣的可以找我讨论)。rn有:const int i = 10;rn虽然有const的声明,i 依然是变量,但是是只读变量。如有:i = 50;//编译将报错,因为i不可写只可读。对其证明下一节将给出。下面将说说const的作用。rnconst 的冻结效应rn上面也提到了const int i = 10;对于i只能读不能写,也就是说i的内容被冻结了。rn那么还有:(1)const int *p; (2)int const *p; (3)int *const p; (4)int const *p const;rn又做何解呢?rnint a ; const int *p = &a; 冻结*p的值,如有*p = 10;//编译将报错。rn同(1)rnint a; int *const p = &a;//冻结p的值,即p的指向不可改。如有 p = &b//编译将报错。但是*p的值却可以改变。*p = 50;//正确rn双冻结,p与*p都被冻结。rn一旦内容被冻结就变成了只读,这样就可对数据起到保护作用了。在赋值语句中被冻结的内容不能再做左值了。rn下面看以例子:rn#include rn#includern#includern char* strcpy(char *des, const char *soure)//对源数据soure起到了保护作用rn rn assert((NULL != des) && (NULL != soure));//函数入口出对指针进行检测rn while((*des++ = *soure++) != '\0');rn return des;rn rnint main(int argc, char *argv[])rnrn char s[50];rn strcpy(s,"hello,baby!");rn printf("%s",s); rnrn对其变量性质的证明rn有const int i = 10;int a[i];//编译将报错,i是变量,编译的时候编译器无法确定数组的大小,解决方法#define i 10就可以了。但在C++中可以直接用,而还有它自己的优点。比如类型验证。rn还有一个例子可以说明在c中const int i = 10;中i是变量。rnSwitch(a)rnrnrn case 1:statement1rn break;rn ........rn case i:statement2//编译报错,因为是变量。rn break;rn ......rn default:statementnrnrn//待续。。。。 论坛

没有更多推荐了,返回首页