volatile
在C++中,volatile
是一個(gè)關(guān)鍵字,用于修飾變量,告訴編譯器該變量的值可能在程序流程之外被意外修改,因此編譯器不應(yīng)該對(duì)該變量進(jìn)行優(yōu)化(如緩存變量值或重排指令順序)。
volatile
主要用于以下場(chǎng)景:
1、多線(xiàn)程訪(fǎng)問(wèn)共享變量:在多線(xiàn)程編程中,如果一個(gè)變量被多個(gè)線(xiàn)程訪(fǎng)問(wèn),并且其中一個(gè)線(xiàn)程可能會(huì)修改該變量的值,就應(yīng)該使用volatile
修飾該變量,以確保線(xiàn)程能夠正確讀取變量的最新值,而不是從緩存中讀取舊值。
2、中斷處理:在嵌入式系統(tǒng)或硬件相關(guān)的編程中,中斷處理程序中通常會(huì)訪(fǎng)問(wèn)硬件寄存器或其他與硬件相關(guān)的狀態(tài)變量。由于中斷處理程序可能在程序的正常流程之外執(zhí)行,為了確保正確處理這些變量,應(yīng)使用volatile
修飾。
以下是一個(gè)簡(jiǎn)單的示例,演示了volatile
的用法:
#include < iostream >
#include < thread >
volatile int sharedVariable = 0;
void modifySharedVariable() {
for (int i = 0; i < 5; ++i) {
sharedVariable = i;
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
}
void readSharedVariable() {
for (int i = 0; i < 5; ++i) {
std::cout < < "Read sharedVariable: " < < sharedVariable < < std::endl;
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
}
int main() {
std::thread writerThread(modifySharedVariable);
std::thread readerThread(readSharedVariable);
writerThread.join();
readerThread.join();
return 0;
}
在上述示例中,我們使用了volatile
修飾sharedVariable
變量。modifySharedVariable()
函數(shù)在循環(huán)中不斷修改sharedVariable
的值,而readSharedVariable()
函數(shù)在另一個(gè)線(xiàn)程中循環(huán)讀取sharedVariable
的值。由于sharedVariable
是一個(gè)共享變量,在多線(xiàn)程環(huán)境下,為了避免讀取舊值,我們使用volatile
修飾,確保readSharedVariable()
函數(shù)能夠正確讀取到最新的值。
需要注意的是,volatile修飾符只用于修飾變量,而不是函數(shù)。它不會(huì)解決所有多線(xiàn)程問(wèn)題,更復(fù)雜的線(xiàn)程同步問(wèn)題可能需要使用互斥鎖(std::mutex)或其他同步機(jī)制來(lái)保證正確性。
assert()
在C++中,assert()
是一個(gè)宏定義,用于在代碼中進(jìn)行斷言檢查。它是一個(gè)調(diào)試工具,用于在程序運(yùn)行時(shí)檢查某個(gè)條件是否為真。如果斷言條件為假(即false
),則會(huì)觸發(fā)斷言失敗,并導(dǎo)致程序中止執(zhí)行。在發(fā)布版本中,默認(rèn)情況下,斷言會(huì)被禁用,因此不會(huì)對(duì)性能產(chǎn)生影響。
assert()
宏的定義位于
頭文件中,通常在開(kāi)發(fā)階段使用,以幫助開(kāi)發(fā)者檢測(cè)程序中的錯(cuò)誤和問(wèn)題。在調(diào)試階段,當(dāng)斷言條件為假時(shí),它會(huì)輸出錯(cuò)誤信息,并在終端顯示斷言失敗的位置和原因。
斷言的一般語(yǔ)法如下:
#include < cassert >
int main() {
int x = 10;
assert(x == 5); // 斷言條件為假,程序會(huì)終止,并顯示錯(cuò)誤信息
return 0;
}
在上述代碼中,assert(x == 5)
會(huì)檢查變量x是否等于5。由于x的值為10,斷言條件為假,程序會(huì)終止執(zhí)行,并顯示斷言失敗的信息,如文件名、行號(hào)、條件表達(dá)式等。
需要注意的是,由于在發(fā)布版本中默認(rèn)會(huì)禁用斷言,因此不應(yīng)該將assert()
用于對(duì)用戶(hù)輸入進(jìn)行驗(yàn)證或執(zhí)行關(guān)鍵業(yè)務(wù)邏輯。對(duì)于這些情況,應(yīng)該使用更穩(wěn)健的錯(cuò)誤處理機(jī)制。
在開(kāi)發(fā)過(guò)程中,合理使用assert()
可以幫助發(fā)現(xiàn)代碼中的問(wèn)題,提高程序的健壯性和可維護(hù)性。但在最終發(fā)布版本中,需要確保去除所有不必要的斷言,以確保代碼的性能和正確性。
sizeof()
在C++中,sizeof
是一個(gè)運(yùn)算符,用于計(jì)算類(lèi)型或變量的大?。ㄗ止?jié)數(shù))。它的語(yǔ)法形式為sizeof (type)
或sizeof expression
。
運(yùn)算符有以下幾個(gè)特點(diǎn)和使用場(chǎng)景:
- 返回值:
sizeof
運(yùn)算符返回一個(gè)size_t
類(lèi)型的值,表示類(lèi)型或變量所占用的字節(jié)數(shù)。 - 對(duì)類(lèi)型的大小計(jì)算:對(duì)于給定的數(shù)據(jù)類(lèi)型,
sizeof(type)
可以計(jì)算出該類(lèi)型的大小。例如:
#include < iostream >
int main() {
std::cout < < "Size of int: " < < sizeof(int) < < " bytes" < < std::endl;
std::cout < < "Size of double: " < < sizeof(double) < < " bytes" < < std::endl;
return 0;
}
輸出可能為:
Size of int: 4 bytes
Size of double: 8 bytes
- 對(duì)變量的大小計(jì)算:sizeof運(yùn)算符也可以計(jì)算變量所占用的字節(jié)數(shù)。例如:
#include < iostream >
int main() {
int x = 10;
double y = 3.14;
std::cout < < "Size of x: " < < sizeof(x) < < " bytes" < < std::endl;
std::cout < < "Size of y: " < < sizeof(y) < < " bytes" < < std::endl;
return 0;
}
輸出可能為:
Size of x: 4 bytes
Size of y: 8 bytes
- 對(duì)數(shù)組的大小計(jì)算:對(duì)于數(shù)組,sizeof運(yùn)算符可以計(jì)算整個(gè)數(shù)組所占用的總字節(jié)數(shù)。例如:
#include < iostream >
int main() {
int arr[] = {1, 2, 3, 4, 5};
std::cout < < "Size of arr: " < < sizeof(arr) < < " bytes" < < std::endl;
return 0;
}
輸出可能為:
Size of arr: 20 bytes
- 對(duì)指針的大小計(jì)算:
sizeof
運(yùn)算符計(jì)算指針變量本身的大小,而不是指針?biāo)赶虻膶?duì)象的大小。無(wú)論指針指向的對(duì)象類(lèi)型大小是多少,指針本身的大小都是固定的。
#include < iostream >
int main() {
int x = 10;
int* ptr = &x;
std::cout < < "Size of ptr: " < < sizeof(ptr) < < " bytes" < < std::endl;
return 0;
}
輸出可能為:
Size of ptr: 8 bytes (在 64 位系統(tǒng)上)
請(qǐng)注意,sizeof
運(yùn)算符在編譯時(shí)計(jì)算,不會(huì)真正運(yùn)行代碼。因此,它在編譯時(shí)就能知道類(lèi)型或變量的大小,并返回一個(gè)常量值。
總之,sizeof
運(yùn)算符是一個(gè)非常有用的工具,用于在編程中確定數(shù)據(jù)類(lèi)型和變量的大小,特別是在處理內(nèi)存分配、結(jié)構(gòu)體、數(shù)組等場(chǎng)景中。
#pragma pack(n)
在C++中,#pragma pack(n)
是一個(gè)預(yù)處理指令(preprocessor directive),用于告訴編譯器按照指定的字節(jié)對(duì)齊方式對(duì)結(jié)構(gòu)體或類(lèi)進(jìn)行內(nèi)存對(duì)齊。通常情況下,編譯器會(huì)對(duì)結(jié)構(gòu)體或類(lèi)進(jìn)行自動(dòng)的內(nèi)存對(duì)齊,以提高訪(fǎng)問(wèn)效率和性能。
#pragma pack(n)
的語(yǔ)法中,n是指定的對(duì)齊字節(jié)數(shù),可以是1、2、4、8等,表示結(jié)構(gòu)體或類(lèi)的成員變量將按照n字節(jié)對(duì)齊。在結(jié)構(gòu)體或類(lèi)定義之前使用該預(yù)處理指令,其作用會(huì)影響接下來(lái)的結(jié)構(gòu)體或類(lèi)的成員排列。
以下是一個(gè)簡(jiǎn)單的示例,演示了#pragma pack(n)
的用法:
#include < iostream >
// 默認(rèn)情況下,編譯器會(huì)進(jìn)行自動(dòng)對(duì)齊,對(duì)于int類(lèi)型通常是4字節(jié)對(duì)齊
struct MyStructAuto {
char c;
int i;
};
// 使用 #pragma pack(1) 指定1字節(jié)對(duì)齊,取消自動(dòng)對(duì)齊
#pragma pack(1)
struct MyStructPacked {
char c;
int i;
};
#pragma pack()
int main() {
std::cout < < "sizeof(MyStructAuto): " < < sizeof(MyStructAuto) < < std::endl;
std::cout < < "sizeof(MyStructPacked): " < < sizeof(MyStructPacked) < < std::endl;
return 0;
}
輸出可能為:
sizeof(MyStructAuto): 8
sizeof(MyStructPacked): 5
在上述示例中,我們定義了兩個(gè)結(jié)構(gòu)體:MyStructAuto
和MyStructPacked
。在MyStructAuto
中,編譯器會(huì)自動(dòng)進(jìn)行對(duì)齊,默認(rèn)情況下,int
類(lèi)型通常是4字節(jié)對(duì)齊,因此MyStructAuto
的大小是8字節(jié)(1字節(jié)的char加上4字節(jié)的int,再加上3字節(jié)的填充)。
而在MyStructPacked
中,我們使用了#pragma pack(1)
指定了1字節(jié)對(duì)齊,這將取消自動(dòng)對(duì)齊,導(dǎo)致MyStructPacked
的大小只有5字節(jié)(1字節(jié)的char加上4字節(jié)的int,沒(méi)有填充字節(jié))。
需要注意的是,使用#pragma pack(n)
可能會(huì)影響內(nèi)存對(duì)齊,導(dǎo)致結(jié)構(gòu)體或類(lèi)的訪(fǎng)問(wèn)效率降低,尤其是對(duì)于大型結(jié)構(gòu)體。在使用#pragma pack(n)
時(shí),應(yīng)謹(jǐn)慎考慮,確保了解其影響,并只在必要時(shí)使用。通常情況下,讓編譯器自動(dòng)進(jìn)行內(nèi)存對(duì)齊是較為推薦的做法。
評(píng)論
查看更多