如果有一個應該包含 3 個整數值的緩沖區,并且您想增加中間的那個,則以下代碼將按預期作業:
#include <iostream>
#include <cstring>
int main()
{
char buffer[] = {'\0','\0','\0','\0','A','\0','\0','\0','\0','\0','\0','\0'};
int tmp;
memcpy(&tmp, buffer 4, 4); // unpack buffer[5:8] to tmp
std::cout<<buffer[4]; // prints A
tmp ;
memcpy(buffer 4, &tmp, 4); // pack tmp value back to buffer[5:8]
std::cout<<buffer[4]; // prints B
return 0;
}
對我來說,對于一個簡單的操作,僅僅修改緩沖區陣列中的一些資料,即將一個新變數推入堆疊,將特定區域從緩沖區復制到該變數,遞增它,然后復制它回到緩沖區。
我想知道是否可以將 5:8 范圍從位元組陣列轉換為 int* 變數并增加它,例如:
int *tmp = reinterpret_cast < int *>(buffer[5:8]);
(*tmp) ;
這樣效率更高,不需要 2 個 memcpy 呼叫。
uj5u.com熱心網友回復:
后一種方法在技術上是未定義的,盡管它可能適用于任何合理的實作。您的語法略有偏差,但這樣的事情可能會起作用:
int* tmp = reinterpret_cast<int*>(buffer 4);
(*tmp) ;
問題在于它違反了 C 嚴格的別名規則。本質上,您可以將任何物件視為 的陣列char
,但不允許將陣列char
視為其他任何物件。因此,要完全符合要求,您需要采用您在第一個片段中所做的方法:將 anint
視為一個陣列char
(這是允許的)并將陣列中的位元組復制到其中,根據需要對其進行操作,然后再復制回來。
我會注意到,如果您關心運行時效率,您可能不應該這樣做。編譯器非常擅長優化這類事情,最終很可能只是在原地操作位元組。例如,clang with-O2
將您的第一個片段(用std::cout
替換為printf
以避免流 I/O 開銷)編譯為:
mov edi, 65
call putchar
mov edi, 66
call putchar
演示
請記住,在撰寫 C 時,您是在描述希望編譯器撰寫的程式的行為,而不是撰寫機器將執行的指令。
uj5u.com熱心網友回復:
只需更改buffer[5:8]
為buffer 4
,就像在您的memcpy()
通話中一樣,然后它可能會按照您想要的方式作業:
int *tmp = reinterpret_cast<int*>(buffer 4 /* or: &buffer[4] */);
(*tmp) ;
或者,您可以使用參考而不是指標:
int &tmp = reinterpret_cast<int&>(buffer[4] /* or: *(buffer 4) */);
tmp ;
但是,請注意,這兩種方法在技術上都是未定義的行為,因為像這樣訪問陣列違反了嚴格別名規則。該memcpy()
方法是安全和標準的方法,編譯器非常擅長優化memcpy()
呼叫。
但是,該reinterpret_cast
方法可能仍然有效,具體取決于您的編譯器。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/506472.html
上一篇:后增量的邏輯是什么?
下一篇:為什么我得到賽格。過錯?