C 从大小\u t到整数的转换

C 从大小\u t到整数的转换,c,assembly,type-conversion,C,Assembly,Type Conversion,接下来 对于这段代码: #include <stdio.h> int main(void) { int i; size_t u; for (i = 0; i < 10; i++) { u = (size_t)i; printf("i = %d, u = %zu\n", i, u); } return 0; } 是转换u=(size\u t)i消耗额外的周期?是的,因为代码已发布,当然。您的转换在这里:

接下来

对于这段代码:

#include <stdio.h>

int main(void)
{
    int i;
    size_t u;

    for (i = 0; i < 10; i++) {
        u = (size_t)i;
        printf("i = %d, u = %zu\n", i, u);
    }
    return 0;
}

是转换
u=(size\u t)i消耗额外的周期?

是的,因为代码已发布,当然。您的转换在这里:

movl    -4(%rbp), %eax
cltq
movq    %rax, -16(%rbp)
当然,这段代码是未优化的,所以这不是一个非常公平的比较。如果您使用优化方法编译它,编译器可能会意识到这些值总是正的,并且只需从存放第三个参数的
i
寄存器移到存放第三个参数的
%rdx

编辑:


正如所怀疑的那样,优化后的代码基本上没有开销。在这种情况下,编译器将循环转换为向上计数
u
,并从
u
派生
i
,而不是反过来,因此
%rbx
用于循环,
i
的值仅使用
%ebx
,这是
%rbx
的较低32位-因此在本例中没有开销。我强调这一点,因为在其他情况下,从
int
转换为
size\u t
可能会受到惩罚。这完全取决于具体情况

是的,因为它将内部表示从32位更改为64位。 具体来说,

.L3:
    movl    -4(%rbp), %eax
    cltq
    movq    %rax, -16(%rbp)
    movq    -16(%rbp), %rdx
读取
i
,执行符号扩展并复制到
%rdx
。我不确定为什么这个值必须通过堆栈——正如mats指出的,这看起来像是来自非优化编译器运行的代码

编辑


在优化的汇编代码中,循环计数器保持为更宽的数据类型。afair,
mov
s寄存器之间的运行时周期wrt quad或dword没有差异(事实上,它们没有差异:请参见表C-16,参考。

不确定这是否是您消耗周期的实际分配 我相信这是一项消耗生命周期的任务

比如说 在这个t1.c上

#include <stdio.h>

int main(void)
{
    int i;
    size_t u;

    for (i = 0; i < 10; i++) {
        printf("i = %d, u = %zu\n", i, u);
    }
    return 0;
}
在上述情况下,暂时不允许分配atall

第二个案例t2.c

#include <stdio.h>

int main(void)
{
    int i;
    size_t u;

    for (i = 0; i < 10; i++) {
        i = (size_t) u;
        printf("i = %d, u = %zu\n", i, u);
    }
    return 0;
}
检查上面的陈述

movl    28(%esp), %eax
movl    %eax, 24(%esp)
现在来看最后一个示例t3.c

#include <stdio.h>

int main(void)
{
    int i;
    int u;

    for (i = 0; i < 10; i++) {
        i = u;
        printf("i = %d, u = %zu\n", i, u);
    }
    return 0;
}

现在,您可以观察t2和t3,并在这里看到差异,但每个拱门之间的差异确实不同,尽管

看起来您并没有打开优化器,这使它成为一个无意义的练习。谢谢,汉斯,请参见编辑谢谢Mats,现在它在编译时启用了-O2标志(请参见编辑)谢谢,现在我明白了
        .file   "t2.c"
        .section        .rodata
.LC0:
        .string "i = %d, u = %zu\n"
        .text
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $32, %esp
        movl    $0, 24(%esp)
        jmp     .L2
.L3:
        movl    28(%esp), %eax
        movl    %eax, 24(%esp)
        movl    $.LC0, %eax
        movl    28(%esp), %edx
        movl    %edx, 8(%esp)
        movl    24(%esp), %edx
        movl    %edx, 4(%esp)
        movl    %eax, (%esp)
        call    printf
        addl    $1, 24(%esp)
.L2:
        cmpl    $9, 24(%esp)
        jle     .L3
        movl    $0, %eax
        leave
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.6 20110731 (Red Hat 4.4.6-3)"
        .section        .note.GNU-stack,"",@progbits
movl    28(%esp), %eax
movl    %eax, 24(%esp)
#include <stdio.h>

int main(void)
{
    int i;
    int u;

    for (i = 0; i < 10; i++) {
        i = u;
        printf("i = %d, u = %zu\n", i, u);
    }
    return 0;
}
        .file   "t3.c"
        .section        .rodata
.LC0:
        .string "i = %d, u = %zu\n"
        .text
.globl main
        .type   main, @function
main:
        pushl   %ebp
        movl    %esp, %ebp
        andl    $-16, %esp
        subl    $32, %esp
        movl    $0, 24(%esp)
        jmp     .L2
.L3:
        movl    28(%esp), %eax
        movl    %eax, 24(%esp)
        movl    $.LC0, %eax
        movl    28(%esp), %edx
        movl    %edx, 8(%esp)
        movl    24(%esp), %edx
        movl    %edx, 4(%esp)
        movl    %eax, (%esp)
        call    printf
        addl    $1, 24(%esp)
.L2:
        cmpl    $9, 24(%esp)
        jle     .L3
        movl    $0, %eax
        leave
        ret
        .size   main, .-main
        .ident  "GCC: (GNU) 4.4.6 20110731 (Red Hat 4.4.6-3)"
        .section        .note.GNU-stack,"",@progbits