文字列を文字のペアに切り取り、それを HEX 形式に変換する際に助けが必要です。
例えば。char *ADDRESS = "0011AABB"; 上記のアドレスを「00」、「11」、「AA」、「BB」に分割し、その後分割して0x00、0x11、0xAA、0xBBに変換し、unsigned charに格納します。
ありがとう
文字列を文字のペアに切り取り、それを HEX 形式に変換する際に助けが必要です。
例えば。char *ADDRESS = "0011AABB"; 上記のアドレスを「00」、「11」、「AA」、「BB」に分割し、その後分割して0x00、0x11、0xAA、0xBBに変換し、unsigned charに格納します。
ありがとう
あなたはアドレス文字列が typechar *
であることを示唆していますが、それらを破棄しないことを保証する解決策、つまりそれらを type として受け取る解決策が必要だと思いますchar const *
。
また、例のように、それらが表すことができるアドレスは 32 ビットであると仮定しますchar *ADDRESS = "0011AABB"
。
その場合、あなたが求めていることを明白な方法で正確に実行するソリューションは次のとおりです。
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#define ADDRESS_BYTES 4 // Bytes in an address
/* Convert a hex numeral encoding an address to the unsigned chars that it
encodes
`addr_str` - in: a hex numeral encoding an address
`bytes` - out: The unsigned char bytes of the address, high-byte first.
return - The number of bytes output: ADDRESS_BYTES if `addr_str` is a
valid hex numeral, otherwise 0.
*/
unsigned address_bytes(char const *addr_str, unsigned char bytes[ADDRESS_BYTES])
{
char buf[3] = {0}; // 3-bytes of 0-filled working space.
char *endp;
unsigned i = 0;
unsigned j = 0;
assert(strlen(addr_str) == 2 * ADDRESS_BYTES); // Insist on 8-char string
for ( ;i < 2 * ADDRESS_BYTES; ++j) { // Take chars 2 at a time
buf[i % 2] = addr_str[i]; ++i; // Next char to buf[0]
buf[i % 2] = addr_str[i]; ++i; // Next + 1 char to buf[1]
// Convert buffer from hex numeral to unsigned char in next byte.
bytes[j] = (unsigned char)strtoul(buf,&endp,16);
if (*endp) { // Check for invalid hex.
return 0; // Failure
}
}
return j; // = 4
}
// A test program...
#include <stdio.h>
int main(void)
{
unsigned char bytes[ADDRESS_BYTES];
char const * address = "0011AABB";
unsigned done_bytes = address_bytes(address,bytes);
printf("The %d valid address bytes are (hex):",done_bytes);
unsigned i = 0;
for ( ;i < done_bytes; ++i) {
printf(" %02x",(unsigned)bytes[i]);
}
putchar('\n');
return 0;
}
ただし、正確に求めるものは効率的なソリューションではありません。32 ビット アドレスをエンコードする 8 文字の 16 進数をエンコードされた 32 ビット符号なし整数に変換し、この符号なし整数を構成する 4 つの符号なし char バイトを上位バイトから順に取得するだけで、目的を達成できます。 . 16 進数を に変換するにはuint32_t
、 を 1 回呼び出すだけ
strtoul
です。次に、この unsigned char バイトをuint32_t
上位バイトから順に取得することは、それuint32_t
がビッグ エンディアンかリトル エンディアンかを知るだけの問題です。したがって、より良い解決策は次のとおりです。
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
unsigned address_bytes(char const *address, unsigned char bytes[ADDRESS_BYTES])
{
union {
uint32_t i;
char c[ADDRESS_BYTES];
} endian_tester = {0x01020304};
int big_endian = endian_tester.c[0] == 1;
uint32_t addr = 1;
char *endp;
assert(strlen(address) == 2 * ADDRESS_BYTES);
addr = (uint32_t)strtoul(address,&endp,16);
if (*endp) {
return 0;
}
endp = (char *)&addr;
if (big_endian) {
// The least significant byte is highest in memory
bytes[0] = endp[0];
bytes[1] = endp[1];
bytes[2] = endp[2];
bytes[3] = endp[3];
} else {
// The least significant byte is lowest in memory
bytes[0] = endp[3];
bytes[1] = endp[2];
bytes[2] = endp[1];
bytes[3] = endp[0];
}
return ADDRESS_BYTES;
}
また、アドレス文字列が ASCII でエンコードされているという移植性のない仮定
を行うことができ、その意思がある場合は、strtoul
完全に呼び出すことを避け、ASCII 照合での文字の位置を使用して、入力文字から出力バイトを直接計算できます。エンコードする unsigned char 値を取得するシーケンス:
#include <assert.h>
#include <string.h>
#include <ctype.h>
unsigned address_bytes(char const *address, unsigned char bytes[ADDRESS_BYTES])
{
unsigned i = 0;
unsigned j = 0;
assert(strlen(address) == 2 * ADDRESS_BYTES);
for ( ; i < 2 * ADDRESS_BYTES; ++i,++j) {
// First character of a pair..
if (isdigit(address[i])) {
// A decimal digit encodes its ASCII value - '0'
bytes[j] = address[i] - '0';
} else if (isxdigit(address[i])) {
// A hex digit encodes 10 + its ASCII value - 'A'
bytes[j] = 10 + address[i] - 'A';
} else {
return 0; // Invalid hex
}
++i; // Second character of a pair...
bytes[j] <<= 4; // Shift the 1st character's value 1 nibble high
// OR the 2nd character's value into the low nibble of the byte...
if (isdigit(address[i])) {
bytes[j] |= address[i] - '0';
} else if (isxdigit(address[i])) {
bytes[j] |= 10 + address[i] - 'A';
} else {
return 0; // Invalid hex
}
}
return ADDRESS_BYTES;
}
それが重要な場合、最後が最速かもしれません。
GCC 4.7.2 および clang 3.2 でビルドおよびテスト済み