C++中sizeof運(yùn)算符全面詳解和代碼示例
sizeof 是 C++ 中的一個(gè)編譯時(shí)運(yùn)算符,用于獲取對(duì)象或類型所占的字節(jié)數(shù)(以 size_t 返回)。它是掌握底層內(nèi)存模型、結(jié)構(gòu)體對(duì)齊、數(shù)組大小計(jì)算等的重要工具。
1. 基本語法
sizeof(type) // 獲取類型的大小 sizeof expression // 獲取表達(dá)式結(jié)果的大小
2. 返回值類型
sizeof返回類型是std::size_t(定義在<cstddef>中),是一個(gè)無符號(hào)整型,足以容納系統(tǒng)中對(duì)象的最大可能大小。
3. 示例代碼一覽
#include <iostream>
#include <cstddef>
int main() {
int a = 5;
double b = 3.14;
int arr[10];
std::cout << "sizeof(int): " << sizeof(int) << "\n";
std::cout << "sizeof(a): " << sizeof(a) << "\n";
std::cout << "sizeof(b): " << sizeof b << "\n"; // 可省略括號(hào)
std::cout << "sizeof(arr): " << sizeof(arr) << "\n";
std::cout << "Number of elements in arr: " << sizeof(arr) / sizeof(arr[0]) << "\n";
return 0;
}
4. 結(jié)構(gòu)體對(duì)齊示例(含填充字節(jié))
#include <iostream>
struct A {
char c; // 1 byte
int i; // 4 bytes
};
int main() {
std::cout << "sizeof(char): " << sizeof(char) << "\n";
std::cout << "sizeof(int): " << sizeof(int) << "\n";
std::cout << "sizeof(A): " << sizeof(A) << "\n"; // likely 8 due to padding
}
結(jié)構(gòu)體
A實(shí)際大小常常為 8,而不是 5,這是因?yàn)榫幾g器插入了填充字節(jié)以保證成員變量對(duì)齊(稱為結(jié)構(gòu)體對(duì)齊或 padding)。
5. 指針和數(shù)組的區(qū)別
int arr[10]; int* p = arr; std::cout << "sizeof(arr): " << sizeof(arr) << "\n"; // 10 * sizeof(int) std::cout << "sizeof(p): " << sizeof(p) << "\n"; // 指針大小,通常是 8(64 位系統(tǒng))
6. 類的sizeof示例(含虛函數(shù)、繼承)
#include <iostream>
class Base {
virtual void foo() {}
};
class Derived : public Base {
int data;
};
int main() {
std::cout << "sizeof(Base): " << sizeof(Base) << "\n"; // 有 vptr,通常為 8
std::cout << "sizeof(Derived): " << sizeof(Derived) << "\n"; // vptr + int + padding
}
7. 注意事項(xiàng)
| 事項(xiàng) | 說明 |
|---|---|
| sizeof 是編譯時(shí)運(yùn)算 | 除非作用于 VLA(C99 風(fēng)格,C++ 不支持),否則計(jì)算在編譯期完成 |
| 對(duì)于類型無需括號(hào) | sizeof expression 中括號(hào)可??;sizeof(type) 中必須加括號(hào) |
| 數(shù)組退化 | sizeof(arr) 在函數(shù)參數(shù)中為指針大小,不是數(shù)組總大小 |
| 對(duì)動(dòng)態(tài)分配數(shù)組無效 | sizeof(new int[10]) 得到的是指針大小,不是數(shù)組大小 |
8.sizeof與模板配合(常用于靜態(tài)斷言)
template<typename T>
void check_size() {
static_assert(sizeof(T) <= 8, "Type is too big!");
}
9. C++11 起的alignof
#include <iostream>
#include <type_traits>
struct MyStruct {
char c;
double d;
};
int main() {
std::cout << "sizeof(MyStruct): " << sizeof(MyStruct) << "\n";
std::cout << "alignof(MyStruct): " << alignof(MyStruct) << "\n";
}
10、綜合示例
下面是一個(gè) 跨平臺(tái)結(jié)構(gòu)體對(duì)齊測(cè)試工具類 的完整示例,功能如下:
- 顯示結(jié)構(gòu)體每個(gè)成員的偏移量(
offsetof); - 顯示結(jié)構(gòu)體整體
sizeof和alignof; - 兼容 GCC / Clang / MSVC;
- 可用于診斷因字節(jié)對(duì)齊(padding)帶來的內(nèi)存浪費(fèi)。
工具類:StructInspector
功能說明:
- 使用
offsetof獲取成員偏移; - 使用
sizeof和alignof獲取結(jié)構(gòu)體大小和對(duì)齊; - 可擴(kuò)展支持任意結(jié)構(gòu)體(通過宏注冊(cè)成員)。
示例代碼
#include <iostream>
#include <iomanip>
#include <cstddef>
#include <string>
#include <type_traits>
// 通用格式輸出宏
#define PRINT_ALIGN_INFO(T) \
std::cout << "Struct: " << #T << "\n" \
<< " Size: " << sizeof(T) << "\n" \
<< " Alignof: " << alignof(T) << "\n\n";
// 檢查偏移宏(成員名必須為字符串形式)
#define PRINT_MEMBER_OFFSET(StructType, Member) \
std::cout << std::setw(20) << #Member << " @ offset: " << offsetof(StructType, Member) << "\n";
// -----------------------------
// 示例結(jié)構(gòu)體
// -----------------------------
struct MyStruct {
char c1;
double d;
int i;
char c2;
};
struct PackedStruct {
char c1;
char c2;
int i;
} __attribute__((packed)); // GCC/Clang 特性(MSVC: use #pragma pack)
#pragma pack(push, 1)
struct MsvcPackedStruct {
char c1;
char c2;
int i;
};
#pragma pack(pop)
// -----------------------------
// 工具函數(shù):打印結(jié)構(gòu)體布局
// -----------------------------
template<typename T>
void InspectStructLayout(const std::string& name) {
std::cout << "==============================\n";
std::cout << "Inspecting: " << name << "\n";
std::cout << "sizeof(" << name << ") = " << sizeof(T) << "\n";
std::cout << "alignof(" << name << ") = " << alignof(T) << "\n";
std::cout << "------------------------------\n";
}
// 示例專用模板:打印具體成員偏移
void Inspect_MyStruct() {
InspectStructLayout<MyStruct>("MyStruct");
PRINT_MEMBER_OFFSET(MyStruct, c1);
PRINT_MEMBER_OFFSET(MyStruct, d);
PRINT_MEMBER_OFFSET(MyStruct, i);
PRINT_MEMBER_OFFSET(MyStruct, c2);
std::cout << "\n";
}
void Inspect_PackedStruct() {
InspectStructLayout<PackedStruct>("PackedStruct");
PRINT_MEMBER_OFFSET(PackedStruct, c1);
PRINT_MEMBER_OFFSET(PackedStruct, c2);
PRINT_MEMBER_OFFSET(PackedStruct, i);
std::cout << "\n";
}
void Inspect_MsvcPackedStruct() {
InspectStructLayout<MsvcPackedStruct>("MsvcPackedStruct");
PRINT_MEMBER_OFFSET(MsvcPackedStruct, c1);
PRINT_MEMBER_OFFSET(MsvcPackedStruct, c2);
PRINT_MEMBER_OFFSET(MsvcPackedStruct, i);
std::cout << "\n";
}
// -----------------------------
// 主程序入口
// -----------------------------
int main() {
Inspect_MyStruct();
Inspect_PackedStruct();
Inspect_MsvcPackedStruct();
return 0;
}
示例輸出(Linux + GCC)
==============================
Inspecting: MyStruct
sizeof(MyStruct) = 24
alignof(MyStruct) = 8
------------------------------
c1 @ offset: 0
d @ offset: 8
i @ offset: 16
c2 @ offset: 20
==============================
Inspecting: PackedStruct
sizeof(PackedStruct) = 6
alignof(PackedStruct) = 1
------------------------------
c1 @ offset: 0
c2 @ offset: 1
i @ offset: 2
==============================
Inspecting: MsvcPackedStruct
sizeof(MsvcPackedStruct) = 6
alignof(MsvcPackedStruct) = 1
------------------------------
c1 @ offset: 0
c2 @ offset: 1
i @ offset: 2
可擴(kuò)展功能
可以封裝為模板工具類,如下:
template<typename T>
struct StructAnalyzer {
static void inspect(const std::vector<std::string>& member_names, const std::vector<std::size_t>& member_offsets) {
std::cout << "Sizeof: " << sizeof(T) << ", Alignof: " << alignof(T) << "\n";
for (size_t i = 0; i < member_names.size(); ++i)
std::cout << member_names[i] << " @ offset: " << member_offsets[i] << "\n";
}
};
因?yàn)?C++ 不支持反射,需要手動(dòng)提供成員名與偏移。
小結(jié)
| 功能 | 實(shí)現(xiàn) |
|---|---|
| 成員偏移計(jì)算 | offsetof(StructType, member) |
| 結(jié)構(gòu)體大小與對(duì)齊 | sizeof, alignof |
| 跨平臺(tái)結(jié)構(gòu)體分析支持 | __attribute__((packed)) / #pragma pack(1) |
| 填充字節(jié)檢查(診斷浪費(fèi)) | offsetof + sizeof 分析對(duì)比 |
總結(jié)
| 用法 | 說明 |
|---|---|
| sizeof(type) | 獲取某個(gè)類型的大小 |
| sizeof(expr) | 獲取表達(dá)式類型的大小 |
| 獲取數(shù)組元素個(gè)數(shù) | sizeof(arr) / sizeof(arr[0]) |
| 獲取結(jié)構(gòu)體大小(含對(duì)齊) | sizeof(Struct) |
| 與模板、static_assert 配合 | 編譯時(shí)類型檢查 |
| 指針大小 | 與指向?qū)ο蟠笮o關(guān) |
到此這篇關(guān)于C++中sizeof運(yùn)算符全面詳解和代碼示例的文章就介紹到這了,更多相關(guān)C++ sizeof運(yùn)算符內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C語言實(shí)現(xiàn)個(gè)人財(cái)務(wù)管理
這篇文章主要為大家詳細(xì)介紹了C語言實(shí)現(xiàn)個(gè)人財(cái)務(wù)管理,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-11-11
C語言實(shí)現(xiàn)將字符串轉(zhuǎn)換為數(shù)字的方法
這篇文章主要介紹了C語言實(shí)現(xiàn)將字符串轉(zhuǎn)換為數(shù)字的方法,涉及系統(tǒng)函數(shù)atoi()函數(shù)的使用技巧,需要的朋友可以參考下2014-12-12
C++ 中二分查找遞歸非遞歸實(shí)現(xiàn)并分析
這篇文章主要介紹了C++ 中二分查找遞歸非遞歸實(shí)現(xiàn)并分析的相關(guān)資料,需要的朋友可以參考下2017-06-06
C語言數(shù)據(jù)結(jié)構(gòu)算法之實(shí)現(xiàn)快速傅立葉變換
這篇文章主要介紹了C語言數(shù)據(jù)結(jié)構(gòu)算法之實(shí)現(xiàn)快速傅立葉變換的相關(guān)資料,需要的朋友可以參考下2017-06-06
C++?OpenCV實(shí)戰(zhàn)之零部件的自動(dòng)光學(xué)檢測(cè)
這篇文章主要為大家介紹一個(gè)C++?OpenCV的實(shí)戰(zhàn)——零部件的自動(dòng)光學(xué)檢測(cè),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2022-09-09
C語言實(shí)現(xiàn)txt數(shù)據(jù)讀入內(nèi)存/CPU緩存實(shí)例詳解
這篇文章主要介紹了C語言實(shí)現(xiàn)txt數(shù)據(jù)讀入內(nèi)存/CPU緩存實(shí)例詳解的相關(guān)資料,這里對(duì)實(shí)現(xiàn)該函數(shù)進(jìn)行了代碼實(shí)現(xiàn),需要的朋友可以參考下2017-01-01
C++實(shí)現(xiàn)LeetCode(57.插入?yún)^(qū)間)
這篇文章主要介紹了C++實(shí)現(xiàn)LeetCode(57.插入?yún)^(qū)間),本篇文章通過簡(jiǎn)要的案例,講解了該項(xiàng)技術(shù)的了解與使用,以下就是詳細(xì)內(nèi)容,需要的朋友可以參考下2021-07-07
C++基于easyx圖形庫實(shí)現(xiàn)打磚塊游戲
這篇文章主要為大家詳細(xì)介紹了C++基于easyx圖形庫實(shí)現(xiàn)打磚塊游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-05-05

