gpt4 book ai didi

c - 在 C 中,将结构作为参数传递给 printf 的预期行为是什么?

转载 作者:行者123 更新时间:2023-12-03 23:17:49 30 4
gpt4 key购买 nike

第二次尝试

好吧,也许我第一次尝试问这个问题太困惑了。所以,我们又来了……

在一个接受可变数量参数的函数中,比如 printf,当你传递一个结构体时,你应该期望生成什么样的代码?

我根据这段代码问这个:

#include <stdio.h>

struct edge{
int v1, v2;
};

int main(void){
struct edge edges;

edges.v1=5;
edges.v2=20;

printf("'%d'\n", edges);

return 0;
}

在我的 windows 机器上编译时,它传递了 2 个整数参数:

    .file   "simple_test_case2.c"
.def ___main; .scl 2; .type 32; .endef
.section .rdata,"dr"
LC0:
.ascii "'%d'\12\0"
.text
.globl _main
.def _main; .scl 2; .type 32; .endef
_main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $32, %esp
call ___main
movl $5, 24(%esp)
movl $20, 28(%esp)
movl 24(%esp), %eax
movl 28(%esp), %edx
movl %eax, 4(%esp)
movl %edx, 8(%esp)
movl $LC0, (%esp)
call _printf
movl $0, %eax
leave
ret
.def _printf; .scl 2; .type 32; .endef

但是我的linux机器生成的代码,只是传递一个内存地址给它:

    .file   "simple_test_case2.c"
.section .rodata
.LC0:
.string "'%d'\n"
.text
.align 2
.globl main
.type main, @function
main:
.LFB2:
pushq %rbp
.LCFI0:
movq %rsp, %rbp
.LCFI1:
subq $16, %rsp
.LCFI2:
movl $5, -16(%rbp)
movl $20, -12(%rbp)
movq -16(%rbp), %rsi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
leave
ret
.LFE2:
.size main, .-main
.globl __gxx_personality_v0
.section .eh_frame,"a",@progbits
.Lframe1:
.long .LECIE1-.LSCIE1
.LSCIE1:
.long 0x0
.byte 0x1
.string "zPR"
.uleb128 0x1
.sleb128 -8
.byte 0x10
.uleb128 0x6
.byte 0x3
.long __gxx_personality_v0
.byte 0x3
.byte 0xc
.uleb128 0x7
.uleb128 0x8
.byte 0x90
.uleb128 0x1
.align 8
.LECIE1:
.LSFDE1:
.long .LEFDE1-.LASFDE1
.LASFDE1:
.long .LASFDE1-.Lframe1
.long .LFB2
.long .LFE2-.LFB2
.uleb128 0x0
.byte 0x4
.long .LCFI0-.LFB2
.byte 0xe
.uleb128 0x10
.byte 0x86
.uleb128 0x2
.byte 0x4
.long .LCFI1-.LCFI0
.byte 0xd
.uleb128 0x6
.align 8
.LEFDE1:
.ident "GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-48)"
.section .note.GNU-stack,"",@progbits

所以这是我的问题,当你只将一个结构传递给像 printf 这样的函数时,生成的代码应该只传递一个参数还是将所有结构成员推送给它?

第一次尝试

我的一个 friend 遇到了一些问题,该程序在 Windows 上无法按预期运行。所以我看了一下源代码并将测试用例精简为:

#include <stdio.h>

struct edge{
int v1, v2;
};

int main(void){
struct edge edges;

edges.v1=5;
edges.v2=20;

//This is the expected behavior for me:
printf("'%d' '%d' '%d' '%d'\n", edges.v1, edges.v1, edges.v1, edges.v1);

//This is supposed to work like this? It should pass the whole struct to printf?
printf("'%d' '%d' '%d' '%d'\n", edges, edges, edges, edges);
printf("'%d' '%d' '%d' '%d'\n", edges, edges);

return 0;
}

在 Windows 7 机器上进行了测试

gcc (tdm-1) 4.5.0
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

输出是这样的:

'5' '5' '5' '5'
'5' '20' '5' '20'
'5' '20' '5' '20'

在带有

的linux机器上
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-48)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

我得到了这个输出:

'5' '5' '5' '5'
'5' '5' '5' '5'
'5' '5' '229971840' '-641776368'

linux box 一的输出,是我所期望的...

然后,我查看了每个编译器生成的汇编代码,发现在我的 Windows 机器上,代码将整个结构传递给 printf,包括 v1 和 v2 成员(这证明了结果的合理性)。但在 Linux 机器上,生成的代码只传递了结构的第一个成员,正如我所料。

那么在这种情况下应该怎么做呢?

对我来说,预期的是 Linux,但也许我错了,这是未定义行为的情况。

最佳答案

预期的行为是未定义的行为。 C 语言要求您将正确类型的参数(匹配格式字符串)传递给 printf,并且没有可以匹配 struct 类型的格式字符串。

您可以通过这种方式传递结构来获得用于打印有意义数据的 C 实现,但它是不可移植的,依赖于调用约定并且不可靠。不要这样做。只需传递您要打印的单个成员即可。

关于c - 在 C 中,将结构作为参数传递给 printf 的预期行为是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6480815/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com