簡體   English   中英

如何在C中將uint_64的十六進制表示形式復制到十六進制的無符號char數組中?

[英]How to copy hex representation of uint_64 to unsigned char array in hex, in C?

我不確定如何用語言表達我要實現的目標,但是我僅在下面舉一個例子,希望你們能幫我一下!

基本上,我試圖將uint64_t值的十六進制表示形式復制到十六進制的無符號char數組中。

我有的:

uint64_t src;
unsigned char destination[8];
/* codes omitted, some codes that will change the value of src */
printf("src: %"PRIx64"\n", src); //this prints out src: 3132333435363738

如何以下列方式將src中的值復制到目標數組中:

destination[0] = 0x31;
destination[1] = 0x32;
destination[2] = 0x33;
//and so on...

謝謝!

編輯

抱歉,如果我的問題不清楚,那么我是編程新手,所以我很難解釋自己。 基本上,我只是想將所有從printf()打印出來的內容存儲為十六進制的無符號字符數組。

例如,printf()輸出一個字符串“ 3132333435363738”,我要取31並將其存儲在dst [0]中,其中dst [0]的值為0x31,依此類推,其中dst [1]為0x32 。

請多多包涵,謝謝!

提取以給定順序組成整數的字節的簡便方法是僅使用移位 (可能還包括掩碼)。 在您的情況下,您似乎想按大端順序提取字節( destination第一個字節=> src最高有效字節),因此將是:

uint64_t src;
unsigned char destination[8];
for(int i=0; i<8; ++i) {
    destination[i] = src>>((7-i)*8);
} 

每次迭代時, src都將向右移(7-i)* 8位,因為我們希望所需的字節位於結果的“底部”

第一次迭代:

src = 0x123456789abcdef0;
i = 0
(7-i) = 7
src >> ((7-i)*8) = 0x12

因此,我們得到0x12並將其放入destination[0] 在下一次迭代中,我們有

i = 1
(7-i) = 6
src >> ((7-i)*8) = 0x1234

現在,我們可以用0xFF 屏蔽結果以僅使用低8位(即0x34),但是在我們的情況下這並不重要,因為destination每個元素都是一個無符號字節,因此在分配大於255的值時(如在這種情況下,它確實發生了無符號的溢出,它的定義很好,只采用了“適合”目標的較低字節; 因此, destination[1]=0x34

i最多重復7次,您將獲得所需的結果。

您可以設置一個指向uint64_t本身的指針:

uint64_t src;
unsigned char *view;

view = (unsigned char *)&src;
for (size_t i = 0; i < sizeof(src); ++i) {
  printf("%x", view[i]);
}
printf("\n");

如果您需要復制值,而不僅僅是復制它,則可以應用相同的原理:

uint64_t src;
unsigned char dst[sizeof(src)];
memcpy((void *)&dst, (void *)&src, sizeof(src));
for (size_t i = 0; i < sizeof(src); ++i) {
  printf("%x", dst[i]);
}
printf("\n");

請注意,這將繼承平台的本地字節序。 如果要轉換字節序,可以在查看/復制字符串之前在src上使用庫函數uint64_t htobe64(uint64_t x) (Linux,BSD)或OSSwapHostToBigInt64(x) (OS X)。 我不知道Windows的等效項,但我認為它們具有等效項。 請參閱我使用unsigned char而不是char來避免任何符號擴展問題。

使用指針強制轉換+指針算術的解決方案或使用聯合的解決方案將不可移植。

這是一種簡便的方法,可隨心所欲地做到這一點,而無需考慮任何麻煩。 可能會有更有效的方法。

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

int main(void)
{
  uint64_t src;
  uint8_t destination[8] = {0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38};

  const uint16_t dummy = 1;
  const bool is_little_endian = *(const uint8_t*)&dummy == 1;

  src=0;
  for(size_t i=0; i<8; i++)
  {
    size_t shift = i*8;

    if(is_little_endian)
    {
      shift = 64-8-shift;
    }

    src |= (uint64_t)destination[i] << shift;
  }

  printf("%" PRIx64, src);

  return 0;
}

這基本上與@Matteo Italia提供的解決方案相同,但是使用掩碼和顯式強制轉換為固定寬度類型uint8_t而不是unsigned char 這些解決方案無論字節序如何都應起作用,因為按位運算符對左操作數的值起作用,而不對其基礎表示形式起作用。

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

int main(void)
{
    uint64_t src = 0x3132333435363738;
    uint8_t destination[8];
    uint64_t mask = 0xff << 56;
    size_t i;

    for (i = 0; i < 8; i++) {
        destination[i] = (uint8_t) ((src & mask) >> (56 - i * 8));
        mask >>= 8;
    }

    printf("src: 0x%" PRIx64 "\n", src);

    for (i = 0; i < 8; i++) {
        printf("destination[%zu] = 0x%" PRIx8 "\n", i, destination[i]);
    }

    return 0;
}

輸出為:

src: 0x3132333435363738
destination[0] = 0x31
destination[1] = 0x32
destination[2] = 0x33
destination[3] = 0x34
destination[4] = 0x35
destination[5] = 0x36
destination[6] = 0x37
destination[7] = 0x38

暫無
暫無

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

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