将数字转换为斜线分割的十六进制路径

时间:2010-07-06 11:28:58

标签: c optimization

我需要从一个数字(在C中)生成一个路径字符串

e.g:

53431453 -> 0003/2F4/C9D
到目前为止,我所拥有的是:

char *id_to_path(long long int id, char *d)
{
    char t[MAX_PATH_LEN];
    sprintf(t, "%010llX", id);

    memcpy(d,   t,   4);
    memcpy(d+5, t+4, 3);
    memcpy(d+9, t+7, 4);

    d[4] = d[8] = '/';

    return d;
}

我想知道是否有更好的方法,例如在一步中生成最终字符串而不是执行sprintf然后移动字节。

由于

编辑:

我对给定的解决方案进行了基准测试

导致每秒操作(越高越好):

(1) sprintf + memcpy  : 3383005
(2) single sprintf    : 2219253 
(3) not using sprintf : 10917996

使用-O3进行编译时,差异甚至更大:

(1) 4422101
(2) 2207157
(3) 178756551

由于这个函数会被大量调用,我会使用最快的解决方案,即使单个sprintf是最短且最易读的。

感谢您的回答!

3 个答案:

答案 0 :(得分:2)

未经测试,但您可以将int拆分为三个然后打印出来:

char *id_to_path(long long int id, char *d)
{
    sprintf(d, "%04llX/%03llX/%03llX", ( id >> 24 ) & 0xffff, ( id >> 12 ) & 0xfff, id & 0xfff);

    return d;
}

答案 1 :(得分:0)

由于字符串使用hex,因此可以使用shift和bit运算符轻松完成。

从值中获取4个最高位可以这样做:

id >> 28

将此转换为数字只是意味着将字符'0'添加到数字中,如下所示:

'0' + (id >> 28)

但是,由于A,B,C ......不会立即跟随角色9,我们必须执行额外的检查,例如:

if (c > '9') c = c - '9' - 1 'A'

如果我们想要接下来的4位,我们应该只移位24位,但是我们仍然保留最高的4位,所以我们应该将它们屏蔽掉,如下所示:

(id >> 24) & 0xf

如果我们把它倒进你的功能,我们得到这个:

char convert (int value)
{
char c = value + '0';
if (c > '9') c = c - '9' - 1 + 'A';
return c;
}

void main()
{
long id = 53431453;
char buffer[20];

buffer[0] = convert(id >> 28);
buffer[1] = convert((id >> 24) & 0xf);
buffer[2] = convert((id >> 20) & 0xf);
buffer[3] = convert((id >> 16) & 0xf);
buffer[4] = convert((id >> 12) & 0xf);
buffer[5] = convert((id >>  8) & 0xf);
buffer[6] = convert((id >>  4) & 0xf);
buffer[7] = convert((id >>  0) & 0xf);
buffer[8] = '\0';
}

现在调整它以在两者之间添加斜杠,在开头添加额外的零,...

修改 我知道这不是一步到位,但如果你以后想要改变斜杠的位置,那么它可以更好地扩展,...

答案 2 :(得分:0)

你有没有尝试过这个选项?

typedef struct {
    unsigned f7 : 4;
    unsigned f6 : 4;
    unsigned f5 : 4;
    unsigned f4 : 4;
    unsigned f3 : 4;
    unsigned f2 : 4;
    unsigned f1 : 4;
    unsigned f0 : 4;
} lubf;

#define convert(a) ( a > 9 ? a + 'A' - 10 : a + '0' )

int main()
{
    lubf bf;
    unsigned long a = 0xABCDE123;
    memcpy(&bf, &a, sizeof(a));
    char arr[9];
    arr[0] = convert(bf.f0);
    arr[1] = convert(bf.f1);
    arr[2] = convert(bf.f2);
    arr[3] = convert(bf.f3);
    arr[4] = convert(bf.f4);
    arr[5] = convert(bf.f5);
    arr[6] = convert(bf.f6);
    arr[7] = convert(bf.f7);
    arr[8] = '\0';
    printf("%lX : %s\n", a, arr);
};