簡體   English   中英

交換C中的指針地址

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM