#include <stdio.h>
#include <stdlib.h>
int main()
{
char buf[100];
snprintf(buf, sizeof(buf), "C %s %s %u %zu", "aaa","bbb",0,0);
printf("%s\n", buf);
}cc -o测试测试
C aaa血bbb 0 140733193388032
c++ -o测试测试
C aaa bbb 0 0
两个人有什么区别?
环境
发布于 2017-10-30 00:42:47
您使用了错误的说明符-- %zu应该使用size_t类型的打印值,但您正在尝试打印int类型的值。从技术上讲,你的程序是错误的,它的行为是没有定义的。
现在,关于这里实际发生的事情,以及为什么你会看到这些结果。你必须了解64 ABI的以下情况
int类型为4个字节,而size_t类型为8个字节。rdi、rsi、rdx、rcx、r8、r9传递,并以反向顺序在堆栈上传递进一步的值。请记住,140733193388032是0x7fff00000000 (较低的4个字节是0)。
在您的情况下,编译器生成的代码是:
mov DWORD PTR [rsp], 0 ; <-- seventh arg passed on stack
mov r9d, 0 ; <-- sixth arg
mov r8d, OFFSET FLAT:.LC0 ; <-- fifth arg
mov ecx, OFFSET FLAT:.LC1 ; <-- fourth arg
mov edx, OFFSET FLAT:.LC2 ; <-- third arg
mov esi, 100 ; <-- second arg
mov rdi, rax ; <-- first arg
mov eax, 0
call snprintf 注意最后一个参数是如何使用4字节mov指令编写的。这意味着上面的4个字节没有被初始化,并且包含一些垃圾值。但是,由于您使用的是指定的%zu打印它,snprintf需要8个字节,在较低的4个字节中打印零,从上4个字节中输出垃圾。这也意味着这种行为只能在第七次和进一步的争论中才能注意到。
为什么gcc和gc++的产出是不同的?因为不同的运行时在启动时执行不同的代码。对于C运行时,它只是随机地在这个内存位置的上字节处有零,而C++运行时在那里存储了一些非零值。
要避免这种错误,请使用-Wformat参数,甚至用-Wall -Wextra编译代码。这将给您以下警告:
1.c: In function ‘main’:
1.c:7:47: warning: format ‘%zu’ expects argument of type ‘size_t’, but argument 7 has type ‘int’ [-Wformat=]
snprintf(buf, sizeof(buf), "C %s %s %u %zu", "aaa","bbb",0,0);
~~^
%uhttps://stackoverflow.com/questions/46972186
复制相似问题