c - 无法正确地将十六进制字节打包到无符号字符数组或指针中

标签 c struct hex

我尝试用无符号字符数组或指针模仿结构,但无法获得相同的十六进制值。

.print() 的输入正确。 我试图通过 print() 从 stringBytes_Data 或 data_hexStrFormatted 获得相同的效果。

谁能给点建议吗?

给定

struct _vector {
char *input;
unsigned char len;
};


static struct _vector tv2 = {
   .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
            "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
            "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
            "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
            "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
            "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
            "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
            "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
   .len = 64,
};

以及查看数据的函数:

static void print(char *intro_message, unsigned char *text_addr,
                    unsigned int size) {
unsigned int   i;

for (i = 0;  i < size;  i++) {
    printf("%2x ", text_addr[i]);
    if ((i & 0xf) == 0xf)
        printf("\n");
}
printf("\n");
}

如何才能获得相同的效果:

char* stringBytes_Data = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";                

我尝试过,但结果是错误的:

unsigned char* data_hexStrFormatted;

int lengthOfStr = strlen(stringBytes_Data);
int charCounterForNewStr = 0;       
int formattedLength = (2*lengthOfStr)+1;

data_hexStrFormatted = (unsigned char*) malloc((formattedLength)*sizeof(unsigned char)); // x2 as we add \x to XX, and 1 for NULL end char


for(i=0; i<lengthOfStr; i=i+2) { 
      // prepend \x
         data_hexStrFormatted[charCounterForNewStr++] = '\\';
         data_hexStrFormatted[charCounterForNewStr++] = 'x';

      data_hexStrFormatted[charCounterForNewStr++] = stringBytes_Data[i]; 
      data_hexStrFormatted[charCounterForNewStr++] = stringBytes_Data[i+1];
} 
data_hexStrFormatted[formattedLength-1] = '\0';

printf("%s\n", data_hexStrFormatted);
printf("%d byte length \n", strlen(data_hexStrFormatted)/4);

 print("data_hexStrFormatted",
                    (unsigned char *)
                    data_hexStrFormatted,
                    (formattedLength)/4); 

最佳答案

你似乎在问:

  • 给定一个包含十六进制数字对的字符串,将十六进制数字转换为字节值?

如果是这样,则可以使用类似于以下的代码:

static inline int hexit(const unsigned char c)
{
    static const char hex_digits[] = "0123456789ABCDEF";
    return strchr(hex_digits, toupper(c)) - hex_digits;
}

此函数对于有效的十六进制数字可以正常工作;它会对无效输入产生无意义的结果。如果您决定需要检测错误的输入,则需要对其进行改进。还有其他方法可以编写此函数(实际上有很多)。一种有效的方法是使用正确值静态初始化的 256 字节数组,因此您只需编写 return hex_array[c];

char* stringBytes_Data = "6bc1bee22e409f96e93d7e117393172aae2d8a571e03ac9c9eb76fac45af8e5130c81c46a35ce411e5fbc1191a0a52eff69f2445df4f9b17ad2b417be66c3710";

size_t len = strlen(stringBytes_Data);
char buffer[len / 2];

assert(len % 2 == 0);

for (size_t i = 0; i < len; i += 2)
    buffer[i / 2] = hexit(stringBytes_Data[i]) << 4 | hexit(stringBytes_Data[i+1]);

printf("%.*s\n", (int)len/2, buffer);

此代码设置数组 buffer 以包含转换后的代码。如果数组中有奇数个字符(这就是断言的状态),它将无法正常工作。


工作代码 - #2

使用问题中的 print() 函数,并删除 info_message 参数,因为它未使用:

#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

struct Vector
{
    char *input;
    unsigned char len;
};

static struct Vector tv2 =
{
    .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
             "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
             "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
             "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
             "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
             "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
             "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
             "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
    .len = 64,
};

static inline int hexit(const unsigned char c)
{
    static const char hex_digits[] = "0123456789ABCDEF";
    return strchr(hex_digits, toupper(c)) - hex_digits;
}

static void print(unsigned char *text_addr, unsigned int size)
{
    unsigned int i;

    for (i = 0; i < size; i++)
    {
        printf("%2x ", text_addr[i]);
        if ((i & 0xf) == 0xf)
            printf("\n");
    }
    printf("\n");
}

static void print2(const char *tag, const unsigned char *data, size_t size)
{
    printf("%s:\n", tag);
    for (size_t i = 0; i < size; i++)
    {
        printf("%2x ", data[i]);
        if ((i & 0x0F) == 0x0F)
            printf("\n");
    }
    printf("\n");
}

static void print_text(const char *tag, const char *data, size_t datalen)
{
    char buffer[datalen / 2];

    assert(datalen % 2 == 0);

    for (size_t i = 0; i < datalen; i += 2)
        buffer[i / 2] = hexit(data[i]) << 4 | hexit(data[i + 1]);

    //printf("%s: [[%.*s]]\n", tag, (int)datalen / 2, buffer);
    assert(memcmp(buffer, tv2.input, tv2.len) == 0);
    print((unsigned char *)buffer, datalen / 2);
    print2(tag, (unsigned char *)buffer, datalen / 2);
}

int main(void)
{
    char *stringBytes_Data =
        "6bc1bee22e409f96e93d7e117393172a"
        "ae2d8a571e03ac9c9eb76fac45af8e51"
        "30c81c46a35ce411e5fbc1191a0a52ef"
        "f69f2445df4f9b17ad2b417be66c3710"
    ;

    print_text("buffer", stringBytes_Data, strlen(stringBytes_Data));
    return 0;
}

示例输出:

6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a 
ae 2d 8a 57 1e  3 ac 9c 9e b7 6f ac 45 af 8e 51 
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a  a 52 ef 
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10 

buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a 
ae 2d 8a 57 1e  3 ac 9c 9e b7 6f ac 45 af 8e 51 
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a  a 52 ef 
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10 

工作代码 - #1

重做 - 以前的版本有各种“两倍”错误,这些错误被系统将缓冲区清零部分掩盖了。

#include <assert.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>

struct Vector
{
    char *input;
    unsigned char len;
};

static struct Vector tv2 =
{
    .input = "\x6b\xc1\xbe\xe2\x2e\x40\x9f\x96"
             "\xe9\x3d\x7e\x11\x73\x93\x17\x2a"
             "\xae\x2d\x8a\x57\x1e\x03\xac\x9c"
             "\x9e\xb7\x6f\xac\x45\xaf\x8e\x51"
             "\x30\xc8\x1c\x46\xa3\x5c\xe4\x11"
             "\xe5\xfb\xc1\x19\x1a\x0a\x52\xef"
             "\xf6\x9f\x24\x45\xdf\x4f\x9b\x17"
             "\xad\x2b\x41\x7b\xe6\x6c\x37\x10",
    .len = 64,
};

static inline int hexit(const unsigned char c)
{
    static const char hex_digits[] = "0123456789ABCDEF";
    return strchr(hex_digits, toupper(c)) - hex_digits;
}

static void print(const char *tag, const unsigned char *data, size_t size)
{
    printf("%s:\n", tag);
    for (size_t i = 0; i < size; i++)
    {
        printf("%2x ", data[i]);
        if ((i & 0x0F) == 0x0F)
            printf("\n");
    }
    printf("\n");
}

static void print_text(const char *tag, const char *data, size_t datalen)
{
    char buffer[datalen / 2];

    assert(datalen % 2 == 0);

    for (size_t i = 0; i < datalen; i += 2)
        buffer[i / 2] = hexit(data[i]) << 4 | hexit(data[i + 1]);

    printf("%s: [[%.*s]]\n", tag, (int)datalen / 2, buffer);
    assert(memcmp(buffer, tv2.input, tv2.len) == 0);
    print(tag, (unsigned char *)buffer, datalen / 2);
}

int main(void)
{
    char *stringBytes_Data =
        "6bc1bee22e409f96e93d7e117393172a"
        "ae2d8a571e03ac9c9eb76fac45af8e51"
        "30c81c46a35ce411e5fbc1191a0a52ef"
        "f69f2445df4f9b17ad2b417be66c3710"
    ;

    print_text("buffer", stringBytes_Data, strlen(stringBytes_Data));
    return 0;
}

UTF-8 终端上的原始输出(它不是有效的 UTF-8 数据,因此有问号):

buffer: [[k???.@???=~s?*?-?W????o?E??Q0?F?\????
R???$E?O??+A{?l7]]
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a 
ae 2d 8a 57 1e  3 ac 9c 9e b7 6f ac 45 af 8e 51 
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a  a 52 ef 
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10 

原始输出转换为 UTF-8,就好像它是 ISO 8859-15(或 8859-1):

buffer: [[kÁŸâ.@é=~s*®-W¬·o¬E¯Q0ÈF£\äåûÁ
Rïö$EßO­+A{æl7]]
buffer:
6b c1 be e2 2e 40 9f 96 e9 3d 7e 11 73 93 17 2a 
ae 2d 8a 57 1e  3 ac 9c 9e b7 6f ac 45 af 8e 51 
30 c8 1c 46 a3 5c e4 11 e5 fb c1 19 1a  a 52 ef 
f6 9f 24 45 df 4f 9b 17 ad 2b 41 7b e6 6c 37 10 

这些数据似乎没有什么特殊含义,但情人眼里出西施。

关于c - 无法正确地将十六进制字节打包到无符号字符数组或指针中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22584680/

相关文章:

c - 线程程序问题

C - 我应该如何将文件中的标记解析为结构?

使用结构的 C 程序发生了什么事?/工作不正常

android - 颜色的十六进制透明度

java - 如何在 Java 中将十六进制字符串转换为 float ?

c - 谁使用 POSIX 实时信号,为什么?

c - Unix/C - 2 种方法有不同的行为

c - 从内存中释放一个结构体数组

c++ - VS2008 传递变量 - 结构与结构组件 - 优点/缺点?

C语言编程之打印最高位为1的十六进制字符