最新电影在线观看,jrs低调看直播,avav天堂,囯产精品宾馆在线精品酒店,亚洲精品成人区在线观看

徐土豆
認證:優質創作者
所在專題目錄 查看專題
c語言運行時出現segment fault的原因
一文理解C語言中的volatile修飾符
C語言中的內存布局(memory layout)
do{}while(false)結構的妙用
const修飾符并不保證運行時的常數性質
引用與指針的區別
作者動態 更多
給定計算預算下的最佳LLM模型尺寸與預訓練數據量分配
05-19 09:33
大模型推理時的尺度擴展定律
05-18 10:32
世界多胞體與世界模型
05-13 09:42
獎勵模型中的尺度擴展定律和獎勵劫持
05-12 08:41
MeCo——給預訓練數據增加源信息,就能減少33%的訓練量并且提升效果
05-08 09:13

const修飾符并不保證運行時的常數性質

本文轉自徐飛翔的“”

版權聲明:本文為博主原創文章,遵循 版權協議,轉載請附上原文出處鏈接和本聲明。

const和volatile修飾符統稱為cv修飾符,用于指示編譯器是否允許一個程序中的某個變量的內存是否在初始化后,仍允許被修改。其中的volatile我們已經在前文[1]中討論過了,我們討論下const的一些特性。我們知道,cv修飾符都是給編譯器看的,用于指導編譯過程中的優化(如volatile)或者用戶非法變量修改行為(如const),因此這倆個修飾符只能保證編譯時的操作合乎設計時候的需求,但是如果涉及到運行時(running time)的一些操作,是無法保證的。我們本文討論const修飾后的變量,被運行時『修改』的例子。

如果我們正常使用const,理應如下所示:

const int var = 10;
int var_b = 100;

var = 100; // 非法操作,因為var是const類型,初始化后不能被修改。
var_b = 10; // 合法操作,正常的賦值

然而,我們不能確保運行時,被const修飾的變量內存,被其他程序,或者自行設計錯誤,或者黑客行為修改,舉個例:

#include <stdio.h>
int main(void) {
	int a = 10;
	const int b = 9;
	int c = 8;
	printf("%d\t%d\t%d\n\r", a, b, c);
	
	int* pa = &a;
	const int* pb = &b;
	int* pc = &c;	
	printf("%x\t%x\t%x\n\r", pa,pb,pc);
	
	*(pa+1) = 100; // modify the first time
	printf("%d\n\r", *(pa+1));
	*(pc-1) = 300;
	printf("%x\t%x\t\n\r", (pa+1), (pc-1));
	printf("%d\n\r", (pa+1) == (pc-1));
	printf("%d\n\r", (pa+1) == pb);
	printf("%d\t%d\t%d\t%d\n\r",a,*(pa+1),c,*(pb));
	return 0;
}

用g++ test_const.cpp編譯,用./a.out輸出結果,代碼輸出為:在這里插入圖片描述

我們可以發現,通過棧[2]上相鄰的變量的地址做偏移,可以實現間接地對const修飾的變量進行修改,這種行為會意料之外的修改常量,非常的危險,我們的代碼中需要檢查涉及到指針偏移的操作,檢查是否會出現越界的情況。

注意到,如果代碼中的輸出從:

printf("%d\t%d\t%d\t%d\n\r",a,*(pa+1),c,*(pb));

改成

printf("%d\t%d\t%d\t%d\n\r",a,*(pa+1),c,b);

結果是不一樣的,后者的結果仍然是輸出b = 9,那是因為C++在編譯時對常量進行折疊,因此直接輸出3這個立即數了,而不是從內存里面取出常量再輸出,這一點要注意。Reference

[1]. //blog.csdn.net/LoseInVain/article/details/103356324

[2]. //blog.csdn.net/LoseInVain/article/details/103183829

聲明:本內容為作者獨立觀點,不代表電子星球立場。未經允許不得轉載。授權事宜與稿件投訴,請聯系:editor@netbroad.com
覺得內容不錯的朋友,別忘了一鍵三連哦!
贊 2
收藏 2
關注 52
成為作者 賺取收益
全部留言
0/200
  • dy-J4n9lg5Q 2021-05-19 13:29
    思路清晰,受益匪淺
    回復