簡體   English   中英

反轉 64 位值的字節

[英]Reverse bytes for 64-bit value

我正在嘗試反轉分配的 64 位地址指針的字節並使用以下代碼:

char swapPtr(char x){
x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
x = (x & 0x00FF00FF00FF00FF) << 8  | (x & 0xFF00FF00FF00FF00) >> 8;
return x;
}

但是,它只是把一切都搞砸了。 但是,類似的功能對於 64 位長度來說非常有效。 是否需要為指針做一些不同的事情?

我進行函數調用的方式可能有問題嗎?

對於指針:

*(char*)loc = swapPtr(*(char*)loc);

長久以來:

*loc = swapLong(*loc);

不能使用char x作為指針!!!! 一個char只有一個字節長。

你至少需要

unsigned long int swapPtr(unsigned long int x) {

或者更好,使用指針的類型

void* swapPtr(void* x) {

當您開始位移指針時,您的編譯器很可能會抱怨; 在這種情況下,最好將參數顯式轉換為無符號 64 位整數:

#include <stdint.h>
uint64_t x;

另請注意,您必須使用變量的地址進行調用,因此您可以使用

result = swapLong(&loc);

不是*loc (它查看loc指向的位置 - 值,而不是地址)。

完整程序:

#include <stdio.h>
#include <stdint.h>

uint64_t swapLong(void *X) {
  uint64_t x = (uint64_t) X;
x = (x & 0x00000000FFFFFFFF) << 32 | (x & 0xFFFFFFFF00000000) >> 32;
x = (x & 0x0000FFFF0000FFFF) << 16 | (x & 0xFFFF0000FFFF0000) >> 16;
x = (x & 0x00FF00FF00FF00FF) << 8  | (x & 0xFF00FF00FF00FF00) >> 8;
return x;
}

int main(void) {
  char a;
  printf("the address of a is 0x%016llx\n", (uint64_t)(&a));
  printf("swapping all the bytes gives 0x%016llx\n",(uint64_t)swapLong(&a));
}

輸出:

the address of a is 0x00007fff6b133b1b
swapping all the bytes gives 0x1b3b136bff7f0000

編輯你可以使用類似的東西

#include <inttypes.h>

printf("the address of a is 0x%016" PRIx64 "\n", (uint64_t)(&a));

其中宏PRIx64擴展為“您需要以十六進制打印 64 位數字的格式字符串”。 比上面的干凈一點。

這是將 64 位值從 LE 轉換為 BE 或反之的另一種方法。

您基本上可以通過定義var_type將這種方法應用於任何類型:

typedef long long var_type;

指針反轉:

void swapPtr(var_type* x)
{
    char* px = (char*)x;
    for (int i=0; i<sizeof(var_type)/2; i++)
    {
        char temp = px[i];
        px[i] = px[sizeof(var_type)-1-i];
        px[sizeof(var_type)-1-i] = temp;
    }
}

按值反轉:

var_type swapVal(var_type x)
{
    var_type y;
    char* px = (char*)&x;
    char* py = (char*)&y;
    for (int i=0; i<sizeof(var_type); i++)
        py[i] = px[sizeof(var_type)-1-i];
    return y;
}

您還可以使用_bswap64內在函數(在 Skylake 架構上具有 2 的延遲和 0.5 的吞吐量)。 它是匯編指令bswap r64的包裝器,因此可能是最有效的:

將 64 位整數 a 的字節順序顛倒,並將結果存入 dst。 此內在函數用於在小端值和大端值之間進行轉換。

#include <immintrin.h>

uint64_t swapLongIntrinsic(void *X) {
    return __bswap_64((uint64_t) X);
}

注意:不要忘記標題

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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