无法正确地将十六进制字节打包到unsigned char数组或指针中

时间:2014-03-22 22:48:56

标签: c struct hex

我试图模仿带有unsigned char数组或指针的结构,但是我无法获得相同的十六进制值。

.input与print()是正确的。 我试图从stringBytes_Data或data_hexStrFormatted与print()获得相同的效果。

有人可以提供建议吗?

鉴于

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); 

1 个答案:

答案 0 :(得分:1)

你似乎在问:

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

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

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 

示例输出:

#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;
}

工作代码 - #1

Redone - 以前的版本有各种“关闭两倍”错误,这些错误被系统归零缓冲区部分隐藏。

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终端上的原始输出(它不是有效的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):

{{1}}

这些数据似乎没有任何特别的意义,但美丽是旁观者的眼睛。