1

我读过的大多数代码都使用int标准错误处理(从函数等返回值)。但是我想知道使用uint_8will a compiler 是否有任何好处——阅读:大多数架构上的大多数 C 编译器——使用立即地址模式生成指令——即将 1 字节整数嵌入到指令中? 我正在考虑的关键指令是函数返回后的比较,使用 uint_8 作为其返回类型。

我可能会错误地思考事情,因为引入 1 字节类型只会导致对齐问题——编译器喜欢将东西打包成 4 字节可能是完全理智的原因,这可能是每个人都只使用整数的原因——并且因为这是与堆栈相关的问题,而不是堆,所以没有真正的开销。

做正确的事是我的想法。但是,为了争论,可以说这是一种流行的廉价微处理器,用于智能手表,它配置有 1k 的内存,但在其指令集中确实有不同的寻址模式:D

另一个稍微专门化讨论的问题(x86)是:文字是:

uint_32 x=func(); x==1;

uint_8 x=func(); x==1;

同类型?或者编译器会在第二种情况下生成一个 8 字节的文字。如果是这样,它可以使用它来生成一个比较指令,该指令将文字作为立即值,并将返回的 int 作为寄存器引用。请参阅 CMP 指令类型。.

x86 指令集的另一个参考。

4

4 回答 4

4

以下是一个特定的编译器将对以下代码执行的操作:

extern int foo(void) ;
void bar(void)
{
        if(foo() == 31) { //error code 31
                do_something();
        } else {
                do_somehing_else();
        }
}

   0:   55                      push   %ebp
   1:   89 e5                   mov    %esp,%ebp
   3:   83 ec 08                sub    $0x8,%esp
   6:   e8 fc ff ff ff          call   7 <bar+0x7>
   b:   83 f8 1f                cmp    $0x1f,%eax
   e:   74 08                   je     18 <bar+0x18>
  10:   c9                      leave
  11:   e9 fc ff ff ff          jmp    12 <bar+0x12>
  16:   89 f6                   mov    %esi,%esi
  18:   c9                      leave
  19:   e9 fc ff ff ff          jmp    1a <bar+0x1a>

cmp 的 3 字节指令。如果 foo() 返回一个 char ,我们得到 b: 3c 1f cmp $0x1f,%al

如果您正在寻找效率。不要假设比较 %a1 中的内容比比较 %eax 更快

于 2009-12-02T18:10:17.403 回答
3

特定架构上的不同积分类型之间可能存在非常小的速度差异。但是你不能依赖它,如果你移动到不同的硬件,它可能会改变,如果你升级到更新的硬件,它甚至可能运行得更慢。

而且,如果您在给出的示例中谈论 x86,那么您会做出错误的假设:立即数需要是 type uint8_t

实际上嵌入到指令中的 8 位立即数属于类型int8_t,可以与字节、字、双字和四字一起使用,用 C 表示法:charshort和.intlong long

所以在这个架构上根本没有任何好处,代码大小和执行速度都没有。

于 2009-12-02T14:12:31.567 回答
3

您应该使用 int 或 unsigned int 类型进行计算。仅对化合物(结构/数组)使用较小的类型。原因是 int 通常被定义为处理器的“最自然”的整数类型,所有其他派生类型可能需要处理才能正常工作。我们在 Solaris for SPARC 上使用 gcc 编译的项目中,访问 8 位和 16 位变量的情况在代码中添加了一条指令。从内存中加载较小的类型时,必须确保正确设置了寄存器的上部(有符号类型的符号扩展或无符号的 0)。这使代码变长并增加了寄存器的压力,从而恶化了其他优化。

我有一个具体的例子:

我将结构的两个变量声明为 uint8_t 并在 Sparc Asm 中获取该代码:

    if(p->BQ > p->AQ)

被翻译成

ldub    [%l1+165], %o5  ! <variable>.BQ,
ldub    [%l1+166], %g5  ! <variable>.AQ,
and     %o5, 0xff, %g4  ! <variable>.BQ, <variable>.BQ
and     %g5, 0xff, %l0  ! <variable>.AQ, <variable>.AQ
cmp     %g4, %l0    ! <variable>.BQ, <variable>.AQ
bleu,a,pt %icc, .LL586  !

当我将这两个变量声明为 uint_t 时,我得到了什么

lduw    [%l1+168], %g1  ! <variable>.BQ,
lduw    [%l1+172], %g4  ! <variable>.AQ,
cmp     %g1, %g4    ! <variable>.BQ, <variable>.AQ
bleu,a,pt %icc, .LL587  !

减少两个算术运算,增加 2 个寄存器用于其他东西

于 2009-12-02T17:11:45.533 回答
1

处理器通常喜欢使用其自然寄存器大小,在 C 中是“int”。

尽管有例外,但您在一个不存在的问题上考虑得太多。

于 2009-12-02T13:36:51.717 回答