[英]Swap pointers addresses in C
我需要在C中做兩個指針的超高性能交換(地址,而不是它們指向的地址)。 我知道地址是對齊的(16的倍數)並且是連續的,並且我已經檢查過此地址是否保留在每次執行中。 代碼如下:
Nodo a __attribute__((aligned(8))), b __attribute__((aligned(4)));
Nodo *nodo_superior __attribute__((aligned(4)));
nodo_superior = &a;
Nodo * nodo_actual __attribute__((aligned(4)));
nodo_actual=&b;
printf("%ld %ld\n", nodo_superior, nodo_actual);
並且控制台上的結果是(請注意,第一個地址應“對齊”對齊以便下一個方法可以工作):
140594404335200 140594404335216
現在要交換地址,我想更改每個指針的位5:
nodo_superior ^= 16;
nodo_actual ^= 16;
但是,不幸的是,C編譯器不允許這樣做,因為整數不能與指針值混合:這是錯誤,不是警告。 如果我嘗試將指針包含在這樣的聯合體中:
union {
Nodo * nodo_actual;
int local_int;
} na;
這樣的想法是這樣的:
na.local_int ^= 16;
則性能會下降,因為(我想)如果編譯器處於聯合狀態,則編譯器將無法對nodo_actual應用/推斷優化。 有什么想法可以迫使編譯器按我的意願行事嗎? 當然,我可以更改生成的匯編程序,但我認為這不是一個好選擇,
如果要切換每個指針的第5位,可以編寫:
nodo_superior = (Nodo *)((uintptr_t)nodo_superior ^ 16);
uintptr_t
是整數類型(如果存在),可以保證在不丟失信息的情況下保留指針值。
打算通過平面內存模型上明顯的同構來完成此操作,因此它應該對您有用(盡管先進行測試)。
另外,您應該使用%p
來打印指針,而不要使用%ld
來導致未定義的行為。 要打印uintptr_t
請參見此處
最好使用臨時變量在“舊方法”中執行交換。
Nodo* Swap= a; a= b; b= Swap;
這需要2次讀取和2次寫入。
“智能”解決方案
a^= 16; b^= 16;
花費2次讀取,2次xor和2次寫入。
我不確定我是否真的理解“交換兩個指針”的意思。 看來您有一對節點,並且想要從另一個節點的地址計算一個節點的地址。
一個類似的問題是當您有兩個數字(例如,玩家編號為1和2)並且想要將玩家編號從1更改為2時,反之亦然。 通常的訣竅是計算
opponent = (1+2) - player ;
您可以使用指針玩類似的技巧,因為允許進行一些算術運算:
int main(int argc, char **argv)
{
struct Node x;
struct Node y;
printf("x is at %p, y at %p\n", &x, &y);
struct Node * one = &x;
struct Node * other = &x + (&y - one); // (&x + &y) - one
printf("if one is at %p, the other is at %p\n", one, other);
one = &y;
other = &x + (&y - one);
printf("if one is at %p, the other is at %p\n", one, other);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.