[英]What is *(int*)&data[18] actually doing in this code?
我遇到了這種在 C++ 中讀取 BMP 文件的語法
#include <fstream>
int main() {
std::ifstream in('filename.bmp', std::ifstream::binary);
in.seekg(0, in.end);
size = in.tellg();
in.seekg(0);
unsigned char * data = new unsigned char[size];
in.read((unsigned char *)data, size);
int width = *(int*)&data[18];
// omitted remainder for minimal example
}
我不明白線路是什么
int width = *(int*)&data[18];
實際上是在做。 為什么不從unsigned char *
到int
的簡單轉換, int width = (int)data[18];
, 工作?
筆記
正如@user4581301在評論中指出的那樣,這取決於實現,並且在許多情況下會失敗。 正如@NathanOliver- Reinstate Monica和@ChrisMM指出的那樣,這是未定義的行為,無法保證結果。
根據位圖頭格式, 位圖的寬度以像素為單位存儲為一個有符號的 32 位整數,從字節偏移量 18 開始。語法
int width = *(int*)&data[18];
讀取字節 19 到 22,包括(假設為 32 位int
)並將結果解釋為整數。
&data[18]
獲取索引 18 處unsigned char
的地址(int*)
將地址從unsigned char*
為int*
以避免在 64 位架構上丟失精度*(int*)
取消引用地址以獲取引用的int
值所以基本上,它獲取data[18]
的地址並讀取該地址處的字節,就好像它們是一個整數一樣。
sizeof(data[18])
是1
,因為unsigned char
是一個字節 ( 0
- 255
) 但是sizeof(&data[18])
是4
如果系統是 32 位,如果是8
如果是 64 位,這可以是更大(對於 16 位系統甚至更小),但除 16 位系統外,它至少應為4
個字節。 顯然,在這種情況下不希望讀取超過4
個字節,並且轉換為(int*)
和隨后對int
取消引用產生4
個字節,實際上是偏移量 18 和 21 之間的 4 個字節,包括這兩個字節。 從unsigned char
到int
簡單轉換也將產生 4 個字節,但只有一個來自data
的信息字節。 以下示例說明了這一點:
#include <iostream>
#include <bitset>
int main() {
// Populate 18-21 with a recognizable pattern for demonstration
std::bitset<8> _bits(std::string("10011010"));
unsigned long bits = _bits.to_ulong();
for (int ii = 18; ii < 22; ii ++) {
data[ii] = static_cast<unsigned char>(bits);
}
std::cout << "data[18] -> 1 byte "
<< std::bitset<32>(data[18]) << std::endl;
std::cout << "*(unsigned short*)&data[18] -> 2 bytes "
<< std::bitset<32>(*(unsigned short*)&data[18]) << std::endl;
std::cout << "*(int*)&data[18] -> 4 bytes "
<< std::bitset<32>(*(int*)&data[18]) << std::endl;
}
data[18] -> 1 byte 00000000000000000000000010011010
*(unsigned short*)&data[18] -> 2 bytes 00000000000000001001101010011010
*(int*)&data[18] -> 4 bytes 10011010100110101001101010011010
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.