首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >访问builtin_bswap函数的正确方式是什么?

访问builtin_bswap函数的正确方式是什么?
EN

Stack Overflow用户
提问于 2021-04-04 05:12:09
回答 2查看 274关注 0票数 0

我有一个应用程序,它使用一个数据库,其中的数据以大端顺序存储。为了跨硬件平台可移植地访问此数据,我使用了config.h模块中定义的4个宏:

代码语言:javascript
运行
复制
word(p) - gets a big-endian 16 bit value at pointer p as a native 16-bit value.
putword(p, w) - stores a native 16-bit variable (w) to pointer p as 16-bit big-endian.
dword(p) and putdword(p, d) do the same for 32-bit values

这一切都运行得很好,但是小端机器上的宏使用暴力的“移位和掩码”方法。

无论如何,看起来在linux上有builtin_bswap16和builtin_bswap32函数可以更有效地完成这项工作(作为内联汇编代码?)。那么,怎样才是编写word/putword宏的正确方法,以便它们在X86_64 linux机器上使用这些内置函数呢?将我的宏编码为htons/l函数调用是否可以有效地完成相同的事情--是否需要启用编译器优化才能使这些解决方案中的任何一个工作?如果它使gdb变得无用,我宁愿不要优化。

EN

回答 2

Stack Overflow用户

发布于 2021-04-05 06:15:47

嗯。我写了一个简单的测试程序,不使用特殊的包含文件,只需调用__builtin_swap...直接执行函数(请参阅“快速...”下面的宏)。一切都很好用。当我在gdb中反汇编代码时,我发现快速...宏在4-5条汇编指令中执行,对于最坏情况下的'dword‘宏,需要多达27条指令。相当整洁的改进,几乎不需要付出任何努力。

代码语言:javascript
运行
复制
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned int uint;

#define word(a)       (ushort) ( (*((uchar *)(a)) << 8) |          \
                                 (*((uchar *)(a) + 1)) )
#define putword(a,w)  *((char *)(a))   =  (char) (((ushort)((w) >>  8)) & 0x00ff), \
                      *((char *)(a)+1) =  (char) (((ushort)((w) >>  0)) & 0x00ff)
#define dword(a) (uint)  ( ((uint)(word(a)) << 16) |      \
                             ((uint)(word(((uchar *)(a) + 2)))) )
#define putdword(a,d) *((char *)(a))   =  (char) (((uint)((d) >> 24)) & 0x00ff), \
                      *((char *)(a)+1) =  (char) (((uint)((d) >> 16)) & 0x00ff), \
                      *((char *)(a)+2) =  (char) (((uint)((d) >>  8)) & 0x00ff), \
                      *((char *)(a)+3) =  (char) (((uint)((d) >>  0)) & 0x00ff)

#define fastword(a)   (ushort) __builtin_bswap16(* ((ushort *) a));
#define fastputword(a, w)  *((ushort *) a) =  __builtin_bswap16((ushort)w);
#define fastdword(a)   (uint) __builtin_bswap32(* ((uint *) a));
#define fastputdword(a, d)  *((uint *) a) =  __builtin_bswap32((uint)d);

int main()
{
unsigned short s1, s2, s3;
unsigned int i1, i2, i3;

        s1 = 0x1234;
        putword(&s2, s1);
        s3 = word(&s2);
        i1 = 0x12345678;
        putdword(&i2, i1);
        i3 = dword(&i2);
        printf("s1=%x, s2=%x, s3=%x, i1=%x, i2=%x, i3=%x\n", s1, s2, s3, i1, i2, i3);

        s1 = 0x1234;
        fastputword(&s2, s1);
        s3 = fastword(&s2);
        i1 = 0x12345678;
        fastputdword(&i2, i1);
        i3 = fastdword(&i2);
        printf("s1=%x, s2=%x, s3=%x, i1=%x, i2=%x, i3=%x\n", s1, s2, s3, i1, i2, i3);
}
票数 0
EN

Stack Overflow用户

发布于 2021-04-05 07:56:00

我只会使用htons, htonl和朋友。它们的可移植性要好得多,任何给定libc的作者很可能已经将它们实现为调用__builtin内部函数或内联asm或其他任何东西的内联函数或宏,从而为特定机器实现了一个近乎最佳的实现。See what is generated in godbolt's setup,我认为这是Linux/glibc的一种风格。

您确实需要使用优化进行编译才能将它们内联,否则它会生成一个普通的函数调用。但即使是-Og也会将它们内联起来,不会把调试搞得一团糟。无论如何,如果您在编译时完全没有进行优化,那么整个程序的效率将非常低,因此调用htons的额外指令肯定是您最不担心的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/66935920

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档