将8Byte char hex string转换为4Byte值;最好在uint32_t中获取正确的二进制值

时间:2016-08-15 02:26:57

标签: c binary hex

我有以下功能:

uint32_t PrintValue(uint32_t *addr_to_dump, uint32 value);

基本上是内存转储的值的内容。现在我有一个包含9个char元素的数组。

uint8_t array_8b[9];

此处收到的值来自二进制文件,其十六进制值为“ACDB5823”,即4字节。我通过UDP消息发送它作为字符串ACDB5823,它是8字节。每个字符1个字节。

在我使用的嵌入式设备中,UART将此值作为uint8_t值接收。我用这些值填充数组。

如何从8字节字符串字符串中取回原始的4字节(以便它适合uint32_t值)? 我确实试过了

strtol(update_word_array, NULL, 16)

将char数组中的第9个值设为'\ 0',但我最终使用PrintValue函数得到ffff ff7f?

现在我使用PrintValue函数在内存转储中获取ACDB5823。

我对这里的转换感到有点困惑。有什么好资源吗?

1 个答案:

答案 0 :(得分:-1)

蛮力的例子,您需要在主机上执行此类操作,使其正常工作,然后将其嵌入系统中的正确位置。您可以使用C库来完成大部分工作,但由于您完全了解编码(与通用厨房接收器库相比),因此它只是代码/工作而不是蛮力。

#include <stdio.h>
unsigned char start[16];
unsigned char send[16];
unsigned char recv[16];
unsigned char end[16];
void send_somewhere ( void )
{
    unsigned int ra;
    for(ra=0;ra<16;ra++) recv[ra]=send[ra];
}
static unsigned char to_hex ( unsigned char x )
{
    if(x>9) return(x+0x37);
    return(x+0x30);
}
static unsigned char from_hex ( unsigned char x )
{
    if(x>0x39) return((x-0x37)&0xF);
    return((x-0x30)&0xF);
}
int main ( void )
{
    unsigned int ra;
    unsigned int rb;
    unsigned int rc;
    unsigned int rd;
    start[0]=0xAC;
    start[1]=0xDB;
    start[2]=0x58;
    start[3]=0x23;
    for(ra=0;ra<4;ra++) printf("[%02X]",start[ra]); printf("\n");
    rb=0;
    for(ra=0;ra<4;ra++)
    {
        send[rb++]=to_hex((start[ra]>>4)&0xF);
        send[rb++]=to_hex((start[ra]>>0)&0xF);
    }
    for(ra=0;ra<8;ra++) printf("[%02X]",send[ra]); printf("\n");
    send[9]=0; printf("%s\n",send);
    send_somewhere();
    for(ra=0;ra<8;ra++) printf("[%02X]",recv[ra]); printf("\n");
    rb=0;
    for(ra=0;ra<8;ra+=2)
    {
        rc=0;
        rc=from_hex(recv[ra+0]);
        rc<<=4;
        rc|=from_hex(recv[ra+1]);
        end[rb++]=rc;
    }
    for(ra=0;ra<4;ra++) printf("[%02X]",end[ra]); printf("\n");
    //if you just need any arbitrary ASCII for some reason even though
    //UDP doesnt require it in any way.
    rb=0;
    for(ra=0;ra<4;ra++)
    {
        send[rb++]=0x40+((start[ra]>>4)&0xF);
        send[rb++]=0x40+((start[ra]>>0)&0xF);
    }
    for(ra=0;ra<8;ra++) printf("[%02X]",send[ra]); printf("\n");
    send[9]=0; printf("%s\n",send);
    send_somewhere();
    for(ra=0;ra<8;ra++) printf("[%02X]",recv[ra]); printf("\n");
    rb=0;
    for(ra=0;ra<8;ra+=2)
    {
        rc=recv[ra+0]&0xF;
        rc<<=4;
        rc|=recv[ra+1]&0xF;
        end[rb++]=rc;
    }
    for(ra=0;ra<4;ra++) printf("[%02X]",end[ra]); printf("\n");
    return(0);
}
制造

[AC][DB][58][23]
ACDB5823
[ACDB5823]
[ACDB5823]
ACDB5823
[AC][DB][58][23]

或其他方式

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
unsigned char start[16];
char send[16];
char recv[16];
unsigned char end[16];
unsigned char temp[16];
void send_somewhere ( void )
{
    unsigned int ra;
    for(ra=0;ra<8;ra++) recv[ra]=send[ra];
}
int main ( void )
{
    unsigned int ra;
    unsigned int rb;
    unsigned int rc;
    unsigned int rd;
    start[0]=0xAC;
    start[1]=0xDB;
    start[2]=0x58;
    start[3]=0x23;
    for(ra=0;ra<4;ra++) printf("[%02X]",start[ra]); printf("\n");
    //endianless and no alignment problems
    rc=0;
    ra=0;
    rc|=start[ra++]; rc<<=8;
    rc|=start[ra++]; rc<<=8;
    rc|=start[ra++]; rc<<=8;
    rc|=start[ra++]; //rc<<=8;
    printf("%08X\n",rc);
    sprintf(send,"%08X",rc);
    printf("[%s]\n",send);

    send_somewhere();

    recv[9]=0;
    printf("[%s]\n",recv);
    rc=strtoul(recv,NULL,16);
    printf("%08X\n",rc);
    //endianless and no alighment problems
    ra=4;
    end[--ra]=rc&0xFF; rc>>=8;
    end[--ra]=rc&0xFF; rc>>=8;
    end[--ra]=rc&0xFF; rc>>=8;
    end[--ra]=rc&0xFF; //rc>>=8;
    for(ra=0;ra<4;ra++) printf("[%02X]",end[ra]); printf("\n");

    //or another way that might use less code, maybe more, but doesnt
    //use 32 bit variables.
    sprintf(send,"%02X%02X%02X%02X",start[0],start[1],start[2],start[3]);
    printf("[%s]\n",send);

    send_somewhere();

    recv[9]=0;
    printf("[%s]\n",recv);
    //then choose whatever solution, C library solutions are just so bloated
    for(ra=0;ra<8;ra++)
    {
        temp[ra]=strtoul(&recv[7-ra],NULL,16);
        recv[7-ra]=0;
    }
    for(ra=0;ra<8;ra++) printf("[%02X]",temp[ra]); printf("\n");
    for(ra=0;ra<8;ra+=2)
    {
        rc=temp[7-ra];
        rc<<=4;
        rc|=temp[6-ra];
        end[ra>>1]=rc;
    }
    for(ra=0;ra<4;ra++) printf("[%02X]",end[ra]); printf("\n");
    return(0);
}
制造

[AC][DB][58][23]
ACDB5823
[ACDB5823]
[ACDB5823]
ACDB5823
[AC][DB][58][23]
[ACDB5823]
[ACDB5823]
[03][02][08][05][0B][0D][0C][0A]
[AC][DB][58][23]

指出,在您尝试实现某些内容并通过UDP发送之前很久,找出如何构建和解析UDP数据包的两端。可以在任何带有编译器的机器上执行此操作,不必是目标嵌入式系统。

调用库函数可能看起来更简单,但是根据资源紧张你的嵌入式系统,你可以通过强制它来节省大量的代码空间和/或执行时间,即使它看起来像是更多的代码行。

像这样做指针游戏

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

unsigned int *x;
unsigned char start[16];
int main ( void )
{
    unsigned int ra;
    start[0]=0xAC;
    start[1]=0xDB;
    start[2]=0x58;
    start[3]=0x23;
    for(ra=0;ra<4;ra++) printf("[%02X]",start[ra]); printf("\n");
    x=(unsigned int *)&start[0];
    printf("%08X\n",x[0]);
    return(0);
}

导致endian问题,对齐问题和可移植性问题。基本上它可能最初工作,但随着时间的推移,代码是一个滴答作响的定时炸弹。像这样的习惯最终会咬你,咬一口(主要的代码重写取决于习惯使用的范围和范围)(跨编译域的指向结构更糟)。我建议不要这样做。

如果您尝试理解上面的代码而不是尝试使用它,那就更好了。只不过是基本位操作和ASCII表知识。谷歌ASCII表并查看其中一个图像结果。

转换为ASCII,您可以使用16深度查找表并简化更多内容。可能是最干净的解决方案。在recv端,如图所示,很容易将ASCII转换回半字节,然后组合半字节。八进制在两端都会容易得多,但需要更长的时间。