日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

C和C++里的const常量、volatile修饰符的深层次说明

發布時間:2025/3/15 c/c++ 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 C和C++里的const常量、volatile修饰符的深层次说明 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

一、寫在前面

二、分析C和C++中const常量被修改后值的狀態

2.1 C中const常量被修改后值的狀態

?2.2 C++中const常量被修改后值的狀態

2.3?C和C++中const常量被修改后值的狀態分析結論

三、添加volatile修飾后,分析C和C++中const常量被修改后值的狀態

3.1?添加volatile修飾后,C中const常量被修改后值的狀態

3.2?添加volatile修飾后,C++中const常量被修改后值的狀態

3.3?添加volatile修飾后,C和C++中const常量被修改后值的狀態分析結論

四、針對const常量在C和C++里分析volatile修飾前后值被修改的狀態的結論

4.1 C中

4.2 C++中

五、原因

5.1 C中對const沒有優化,C++存在const優化

5.2 局部const常量和全局const常量

5.3 借用評論區的說法

5.4 volatile優化



一、寫在前面

1. 由于涉及到編譯器層面,所以不同編譯器結果可能不一樣。本文使用的VS編譯器。

2. 針對const修飾的整型常量:

const int local = 10;

3. 常量本質上也是一個變量,是變量就會有地址
因為直接修改const常量是不允許的(編譯就會報錯),所以只能通過指針修改其地址上的值來試驗。如下:

?這里注意下,用vs復制一個文件到另一個文件運行(比如這里程序都是一樣的,一個在c運行,一個在cpp運行,復制過去不清理解決方案,運行的其實還是上一個程序),但是編譯器選擇不同時,需要重新生成解決方案,不然運行的還是上一次的程序。

4.分析的問題及結論

不加volatile修飾的const常量修改分析const變量被修改后,常量本身值的修改情況const變量被修改后,常量對應的內存空間中的值的修改情況
C環境下會被修改會被修改
C++環境下不會被修改會被修改
加volatile修飾的const常量修改分析const變量被修改后,常量本身值的修改情況const變量被修改后,常量對應的內存空間中的值的修改情況
C環境下會被修改會被修改
C++環境下會被修改會被修改

5.整體代碼

c部分:

#include<stdio.h> #include<stdlib.h> #include<string.h>int main(void) {const int local = 10;printf("修改前:\n");printf("修改前local本身的值 : %d \n", local);printf("修改前local的地址: %x \n", &local);int *ptr = (int*)&local;*ptr = 100;printf("修改后:\n");printf("修改后local本身的值: %d \n", local);printf("修改后local對應的內存空間中的值:: %d \n", *ptr);printf("修改后local的地址: %x \n", &local);printf("\n\n");printf("測試添加volatile修飾符:\n");/****** 添加volatile避免編譯器的優化 ********/const volatile int local2 = 10;printf("修改前:\n");printf("修改前local2本身的值 : %d \n", local2);printf("修改前local的地址: %x \n", &local2);int *ptr2 = (int*)&local2;*ptr2 = 100;printf("修改后:\n");printf("修改后local2本身的值: %d \n", local2);printf("修改后local2對應的內存空間中的值:: %d \n", *ptr2);printf("修改后local2的地址: %x \n", &local2);return 0; }

輸出結果:

C++部分

#include <iostream> #include<stdio.h> using namespace std;int main(){const int local = 10;printf("修改前:\n");printf("修改前local本身的值 : %d \n", local);printf("修改前local的地址: %x \n", &local);int *ptr = (int*)&local;*ptr = 100;printf("修改后:\n");printf("修改后local本身的值: %d \n", local);printf("修改后local對應的內存空間中的值:: %d \n", *ptr);printf("修改后local的地址: %x \n", &local);printf("\n\n");printf("測試添加volatile修飾符:\n");/****** 添加volatile避免編譯器的優化 ********/const volatile int local2 = 10;printf("修改前:\n");printf("修改前local2本身的值 : %d \n", local2);printf("修改前local的地址: %x \n", &local2);int *ptr2 = (int*)&local2;*ptr2 = 100;printf("修改后:\n");printf("修改后local2本身的值: %d \n", local2);printf("修改后local2對應的內存空間中的值:: %d \n", *ptr2);printf("修改后local2的地址: %x \n", &local2);return 0; }

輸出結果:

二、分析C和C++中const常量被修改后值的狀態

這里討論的值指常量本身的值(local)常量對應的內存空間上的值(*ptr)

2.1 C中const常量被修改后值的狀態

代碼如下:

#include<stdio.h> #include<stdlib.h> #include<string.h>int main(void) {const int local = 10;printf("修改前:\n");printf("修改前local本身的值 : %d \n", local);printf("修改前local的地址: %x \n", &local);int *ptr = (int*)&local;*ptr = 100;printf("修改后:\n");printf("修改后local本身的值: %d \n", local);printf("修改后local對應的內存空間中的值:: %d \n", *ptr);printf("修改后local的地址: %x \n", &local);return 0; }

運行結果如下:

?注意輸出中選中區。

結論:通過指針的方式修改常量對應的內存空間中的值,常量本身的值(local)會被修改,常量對應的內存空間中的值(*ptr)也會被修改;

?2.2 C++中const常量被修改后值的狀態

代碼如下:

#include <iostream> #include<stdio.h> using namespace std; /***為了節省時間 輸出之間用的printf沒用cout****/int main(){const int local = 10;printf("修改前:\n");printf("修改前local本身的值 : %d \n", local);printf("修改前local的地址: %x \n", &local);int *ptr = (int*)&local;*ptr = 100;printf("修改后:\n");printf("修改后local本身的值: %d \n", local);printf("修改后local對應的內存空間中的值:: %d \n", *ptr);printf("修改后local的地址: %x \n", &local);return 0; }

運行結果如下:

??注意輸出中選中區。

結論:通過指針的方式修改常量對應的內存空間中的值,常量本身的值(local)不會被修改,常量對應的內存空間中的值(*ptr)會被修改;

2.3?C和C++中const常量被修改后值的狀態分析結論

所以,局部const常量的值在C++和C里面是否能修改的結果是不一樣的。在C里面常量本身的值和內存空間對應的值都會變,C++里常量本身發值不會變,但是對應的內存空間的值會變。原因在后面會說。

這里說的是局部,全局const是什么會在后面說。

三、添加volatile修飾后,分析C和C++中const常量被修改后值的狀態

這里討論的值指常量本身的值(local)常量對應的內存空間上的值(*ptr)

3.1?添加volatile修飾后,C中const常量被修改后值的狀態

代碼如下:

#include<stdio.h> #include<stdlib.h> #include<string.h>int main(void) {const int local = 10;printf("測試添加volatile修飾符:\n");/****** 添加volatile避免編譯器的優化 ********/const volatile int local2 = 10;printf("修改前:\n");printf("修改前local2本身的值 : %d \n", local2);printf("修改前local的地址: %x \n", &local2);int *ptr2 = (int*)&local2;*ptr2 = 100;printf("修改后:\n");printf("修改后local2本身的值: %d \n", local2);printf("修改后local2對應的內存空間中的值:: %d \n", *ptr2);printf("修改后local2的地址: %x \n", &local2);return 0; }

運行結果如下:

?注意輸出中選中區。

結論:添加volatile修飾后,通過指針的方式修改常量對應的內存空間中的值,常量本身的值(local)會被修改,常量對應的內存空間中的值(*ptr)也會被修改;也就是說volatile修飾符在這里看不出是否跳過優化。

3.2?添加volatile修飾后,C++中const常量被修改后值的狀態

代碼如下:

#include <iostream> #include<stdio.h> using namespace std; /***為了節省時間 輸出之間用的printf沒用cout****/int main(){const int local = 10;printf("測試添加volatile修飾符:\n");/****** 添加volatile避免編譯器的優化 ********/const volatile int local2 = 10;printf("修改前:\n");printf("修改前local2本身的值 : %d \n", local2);printf("修改前local的地址: %x \n", &local2);int *ptr2 = (int*)&local2;*ptr2 = 100;printf("修改后:\n");printf("修改后local2本身的值: %d \n", local2);printf("修改后local2對應的內存空間中的值:: %d \n", *ptr2);printf("修改后local2的地址: %x \n", &local2);return 0; }

運行結果如下:

??注意輸出中選中區。

結論:添加volatile修飾后,通過指針的方式修改常量對應的內存空間中的值,常量本身的值(local)會被修改,常量對應的內存空間中的值(*ptr)也會被修改也就是說volatile修飾符在這里成功避免編譯器優化。

3.3?添加volatile修飾后,C和C++中const常量被修改后值的狀態分析結論

因為在C里面,const常量的值都能被修改,所以volatile無法提現;在C++里volatile成功避免了優化。

四、針對const常量在C和C++里分析volatile修飾前后值被修改的狀態的結論

4.1 C中

無論是否進行volatile修飾,常量對應內存空間中的值(*ptr)都會被修改

無論是否進行volatile修飾,常量本身的值(local)都會被修改

4.2 C++中

無論是否進行volatile修飾,常量對應內存空間的值(*ptr)都會被修改

如果不采用volatile修飾const常量,常量本身的值(local)不會被修改,volatile修飾后常量本身的值(local)會被修改。

五、原因

5.1 C中對const沒有優化,C++存在const優化

c++中用const定義了一個常量后,不會分配一個空間給它,而是將其寫入符號表(symbol table),這使得它成為一個編譯期間的常量,沒有了存儲與讀內存的操作,使得它的效率也很高。

通過指針的方式修改常量對應的內存空間中的值時,這種修改不會影響到常量本身的值,因為用到該常量(local)的時候,編譯器根本不會去進行內存空間的讀取。這就是c++的常量折疊(constant folding),即將const常量放在符號表中,而并不給其分配內存,編譯器直接進行替換優化。除非需要用到local的存儲空間的時候,編譯器迫不得已才會分配一個空間給local,但之后local的值仍舊從符號表中讀取,不管local的存儲空間中的值如何變化,都不會對常量local產生影響(即常量放在符號表,無論是否對其進行操作,常量本身的使用都是從符號表中去取。所以就算從內存空間對其進行了修改,內存空間的值變化了,但是常量的值還是從符號表中拿,值還是沒變)。
示例:

int main(){const int local ?= 2;int* ptr = (int*)(&local);*ptr ?= 30;cout<<&local<<endl;?cout<<ptr <<endl; ?cout<<local<<endl;cout<<*ptr <<endl; }


輸出:

0x28ff08 0x28ff08 2 30

在C中卻不是這樣,C沒有constant folding的概念,用const定義一個常量的時候,編譯器會直接開辟一個內存空間存放該常量,不會進行優化,所以從內存空間對其進行了修改,內存空間的值變化了,常量本身的值也就變化了(跟變量一樣,只不過常量不能直接用常量名二次賦值或初始化)。
示例:

int main() {const int local ?= 2;int* ptr = (int*)(&local);*ptr = 30;printf("%x\n",&local);printf("%x\n",ptr);printf("%d\n",local);printf("%d\n",*ptr);return 0; }

輸出:

28ff18 28ff18 30 30

5.2 局部const常量和全局const常量

1. 針對定義在函數內部(包括main函數)的const常量,不管是c還是c++,本質上都只是將其當成一個普通的局部變量來對待,都只是在棧上分配空間。所以const根本就不能起到阻止修改其內存空間的作用,一個合法的強制類型轉換就可以輕松搞定。C++比C好的地方就在于使用了constant folding的機制,使得常量的值跟對應的內存空間無關,從而保護了該常量值。
2. 對于全局const常量(定義在main之外),在c和c++中如果我們仍然用int *ptr = (int*)(&local);這種方法來修改它內存中的值,編譯時不會報錯(這里看編譯器,gcc不報錯,vs編譯時就會報錯),但是運行時會報段錯誤,因為local是放在只讀的全局數據區中,修改該區中的數據會引發段錯誤,也就是不能進行修改。
3. 總結來說,全局const常量放在常量只讀區,C和C++里都沒法修改;局部const常量放在棧上,能夠通過操作內存的方式(int *ptr = (int*)(&local))修改其內存空間中的值。

注意這里局部const常量被修改的是常量對應內存空間的值,常量本身的值是否改變取決于是C還是C++,C++里有優化,常量本身的值不會變,而C沒有優化,所以常量本身的值會被修改。

5.3 借用評論區的說法

在C中,const修飾的變量,是指不可修改的變量(旨在提示程序員)。如何使這個變量不可修改呢?在編譯期間對這個變量進行檢查,如果有語句試圖修改這個變量,就報編譯錯誤,使編譯不通過。雖然如此,但仍然可以通過指針間接修改const變量的值(繞過編譯器檢查)來證明這是一個變量。作為函數參數,是限定函數只對該參數(這里的參數是引用類型,引用使用址傳遞效率高)進行讀,而不允許寫(避免誤操作,因為修改參數引用會直接改變原數據)。

在C++中,常量就真的是常量了。

這也就是為什么我們說c里面常量只是只讀,并不是真正的常量的原因。

5.4 volatile優化

volatile 確實能避免編譯器優化。

總結

以上是生活随笔為你收集整理的C和C++里的const常量、volatile修饰符的深层次说明的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 国产精品久久久久久久久久小说 | 精品一区91 | 国产精品亚洲一区二区三区 | 亚洲97色| 欧美国产大片 | 国产亚洲精品精品精品 | 九九精品在线观看 | av日韩精品 | 免费观看日本 | 日韩欧美aⅴ综合网站发布 国产成人一区二区三区小说 | 中文字幕日本一区 | 中文国语毛片高清视频 | 制服 丝袜 激情 欧洲 亚洲 | 麻豆性视频| 色秀视频网 | 欧美激情视频网址 | 伦理片久久 | 国产成人在线免费视频 | videos亚洲| 日本一区二区三区四区在线观看 | 国产三区av| 日韩精品一区二 | 色啪网站 | 哈利波特3在线观看免费版英文版 | 狠狠人妻久久久久久综合 | 香蕉久久夜色精品 | 麻豆影音 | 理论片中文 | 亚洲精品高清视频在线观看 | xxx国产在线观看 | 久久激情综合网 | www.com欧美| 黄色成年人 | 成人黄色免费网 | 黄色污小说 | 91午夜视频 | 麻豆视频网页 | 无码久久av一区二区三区 | 日本欧美不卡 | 337p粉嫩大胆噜噜噜亚瑟影院 | 日本高清在线一区 | 天天干天天插天天射 | 亚洲少妇精品 | 国产欧美一区二区精品久久久 | 超碰伊人久久 | av在线播放地址 | 99精品视频国产 | 日本一区免费视频 | 男女被到爽流尿 | 毛片在线免费视频 | 国产精品h | 午夜在线精品 | 日韩欧美猛交xxxxx无码 | 免费在线观看你懂的 | 亚洲人成电影在线播放 | 新呦u视频一区二区 | 揉我啊嗯~喷水了h视频 | www.久久国产 | 激情丁香 | 伊人久久天堂 | www.国产com | 91看片在线 | 成年精品 | 成人永久视频 | 欧美人妖乱大交 | 午夜久久 | 欧美精品久久96人妻无码 | 伊人青青草原 | 欧美美女在线观看 | 国产黄色一级片视频 | 激情都市一区二区 | 性生生活性生交a级 | 麻豆传媒在线观看 | 国产av一区二区三区 | 久久精品久久精品 | 婷婷色在线 | 91美女视频网站 | 吊侵犯の奶水授乳羞羞漫画 | 激情久久网站 | 日韩av网站在线播放 | av小说在线 | 欧美精品一区二区不卡 | 18男女无套免费视频 | 美女在线一区 | 波多野结衣一区二区 | 国产在线免费观看 | 少妇2做爰交换朴银狐 | 欧美激情三级 | 中文字幕+乱码+中文乱 | 亚洲最大福利 | 人妻少妇偷人精品久久久任期 | 农村搞破鞋视频大全 | 欧美日p视频 | 三级在线视频 | 少妇一级淫片日本 | 中日韩免费视频 | 国产精品爱啪在线线免费观看 | 国产亚洲福利 | 久久精品亚洲精品国产欧美 |