[英]How to use sprintf to append array of uint_64 type to an array of 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.