アスキーゴードで設定された
char配列があります。
char as[3] = {0x31,0x32,0}
この配列の要素をそれぞれ
0x31→0001
0x32→0010
と判 断し、
1byteのchar型データ
char hex = 0x12(00010010)
に変換する方法をご教授願います。
下記リンクのarainさん回答の逆の考え方で出来そうなきがするのですが、
逆の考え方がわからない状態です。
組み込み分野で使用する為、標準ライブラリは使用できません。
http://okwave.jp/qa/q4389139.html
ASCII → HEX 変換について
Re: ASCII → HEX 変換について
as[0] と as[1] は、udai さんが書きました:char as[3] = {0x31,0x32,0}
0x30~0x39 ('0'~'9')、0x41~0x46 ('A'~'F')、0x61~0x66 ('a'~'f')
だけだと仮定してよいのでしょうか?
#define conv2(x) (((x) >> 6 & 1) * 9 + (x) & 15)
unsigned char conv(const char *as)
{
return conv2(as[0])<<4 | conv2(as[1]);
}
// 以下、テストプログラム
#include <stdio.h>
int main(void)
{
char as[4][3] = {
{ 0x31, 0x32, 0 },
{ 0x41, 0x42, 0 },
{ 0x65, 0x66, 0 },
{ 0x43, 0x39, 0 },
};
int i;
unsigned char hex;
for (i = 0; i < 4; i++) {
hex = conv(as[i]);
printf("%s -> %02x\n", as[i], hex);
}
return 0;
}
Re: ASCII → HEX 変換について
この手のものは、速度優先なのか、サイズ優先なのか、可読性優先なのか、移植性優先なのかをはっきりさせる必要があります。
速度やサイズを優先するのであれば、プロセッサやコンパイラを明記してください。
また、すでに指摘があるのように、エラーチェックをどの程度行うのかによっては話が変わってきます。
速度やサイズを優先するのであれば、プロセッサやコンパイラを明記してください。
また、すでに指摘があるのように、エラーチェックをどの程度行うのかによっては話が変わってきます。
Re: ASCII → HEX 変換について
ごもっとも。たかぎ さんが書きました:この手のものは、速度優先なのか、サイズ優先なのか、可読性優先なのか、移植性優先なのかをはっきりさせる必要があります。
速度やサイズを優先するのであれば、プロセッサやコンパイラを明記してください。
元の質問に「組み込み分野で使用する為」とあるので、サイズが重要かなと思っていましたが、
よく考えると、マクロを展開したらコードが大きくなりますね。
かと言って、関数にすると入口と出口のコードがオーバヘッドとなります。
やっぱり、ループにするほうがよいと考え直して、次のように書き換えてみました。
int conv(const char *s)
{
int c, v = 0;
while (c = *s++)
v = (c & 0x10 ? c : c + 9) & 0x0f | (v << 4);
return v;
}
#include <stdio.h>
int main(void)
{
char as[4][3] = {
{ 0x31, 0x32, 0 },
{ 0x41, 0x42, 0 },
{ 0x65, 0x66, 0 },
{ 0x43, 0x39, 0 },
};
int i;
unsigned char hex;
for (i = 0; i < 4; i++) {
hex = conv(as[i]);
printf("%s -> %02x\n", as[i], hex);
}
return 0;
}
$ gcc -c -Os x.c
$ objdump -d x.o
x.o: file format elf32-i386
Disassembly of section .text:
00000000 <conv>:
0: 55 push %ebp
1: 31 c0 xor %eax,%eax
3: 89 e5 mov %esp,%ebp
5: 8b 4d 08 mov 0x8(%ebp),%ecx
8: eb 10 jmp 1a <conv+0x1a>
a: f6 c2 10 test $0x10,%dl
d: 75 03 jne 12 <conv+0x12>
f: 83 c2 09 add $0x9,%edx
12: 83 e2 0f and $0xf,%edx
15: c1 e0 04 shl $0x4,%eax
18: 09 d0 or %edx,%eax
1a: 0f be 11 movsbl (%ecx),%edx
1d: 41 inc %ecx
1e: 85 d2 test %edx,%edx
20: 75 e8 jne a <conv+0xa>
22: 5d pop %ebp
23: c3 ret
C:\tmp>cl -c -O1 x.c
C:\tmp>dumpbin /disasm x.obj
Microsoft (R) COFF/PE Dumper Version 9.00.30729.01
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file x.obj
File Type: COFF OBJECT
_conv:
00000000: 8B 54 24 04 mov edx,dword ptr [esp+4]
00000004: 33 C0 xor eax,eax
00000006: EB 13 jmp 0000001B
00000008: 42 inc edx
00000009: F6 C1 10 test cl,10h
0000000C: 75 03 jne 00000011
0000000E: 83 C1 09 add ecx,9
00000011: C1 E0 04 shl eax,4
00000014: 83 E1 0F and ecx,0Fh
00000017: 0B C8 or ecx,eax
00000019: 8B C1 mov eax,ecx
0000001B: 0F BE 0A movsx ecx,byte ptr [edx]
0000001E: 85 C9 test ecx,ecx
00000020: 75 E6 jne 00000008
00000022: C3 ret
Re: ASCII → HEX 変換について
比較的ローエンドのマイコンで速度優先にするのであれば、次のように表引きにしてもよいでしょう。
ただし、M16Cのように、far領域のメモリアクセスが遅い場合には逆効果になることがあります。
データキャッシュやパイプライン等があるプロセッサでは、ケースバイケースですので一概には言えません。
int ascii_to_hex(const char *s)
{
static const char table[256] =
{
['0'] = 0,
['1'] = 1,
['2'] = 2,
['3'] = 3,
['4'] = 4,
['5'] = 5,
['6'] = 6,
['7'] = 7,
['8'] = 8,
['9'] = 9,
['A'] = 10,
['B'] = 11,
['C'] = 12,
['D'] = 13,
['E'] = 14,
['F'] = 15,
['a'] = 10,
['b'] = 11,
['c'] = 12,
['d'] = 13,
['e'] = 14,
['f'] = 15,
};
int result = 0;
int c;
for (const char *ss = s; (c = (unsigned char)*ss) != '\0'; ss++)
{
result = (result << 4) + table[c];
}
return result;
}
データキャッシュやパイプライン等があるプロセッサでは、ケースバイケースですので一概には言えません。