我有一个这样的程序(x86_64 GNU / Linux)
int main()
{
char s[] = "123456789";
char d[] = "123";
strcpy(d, s);
printf("%p, %0p\n", s, d);
printf("%s, %s", s, d);
return 0;
}
,输出为:0xeb6d2930 0xeb6d2910 123456789 123456789 我对结果感到困惑 我认为内存中的程序是这样的:
所以结果应该是* s =" 789",* d =" 123456789"
你能解释为什么结果不像我想的那样吗? 我将格式说明符更改为%p以打印d和s的地址 我知道s和d是重叠的,因此d没有足够的空间 持有可能导致不确定行为的s,但无论如何我都在想 为什么结果是* s =" 123456789" * d =" 123456789"答案 0 :(得分:2)
您的程序在这两个方面有不确定的行为:
strcpy()
:不要写入您不拥有的内存。printf()
的格式说明符错误:使用%p
打印指针地址。仅适用于数据指针。请使用main
的正确原型,你几乎拥有它(这可能是UB,但我没有遵循所有的论点):
int main(void)
int main(int argc, char* argv[])
或兼容或实现定义的扩展有效。
未定义的行为意味着一切都会发生,甚至是鼻子恶魔。
答案 1 :(得分:1)
您的程序会调用未定义的行为,因为:
1. d
没有足够的空间来容纳大于4
字节的字符串(包括\0
)。
2.您使用错误的格式说明符来打印地址。
结果是预期的或意外的。
答案 2 :(得分:0)
从输出中显示地址布局,它的初始内容似乎是:
offset 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
d: 0xeb6d2910 30 31 32 00 xx xx xx xx xx xx xx xx xx xx xx xx | 1 2 3 . . . . . . . . . . . . .
0xeb6d2920 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx | . . . . . . . . . . . . . . . .
s: 0xeb6d2930 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . .
strcpy(d, s)
之后:
offset 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
d: 0xeb6d2910 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . .
0xeb6d2920 xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx xx | . . . . . . . . . . . . . . . .
s: 0xeb6d2930 30 31 32 33 34 35 36 37 38 39 00 xx xx xx xx xx | 1 2 3 4 5 6 7 8 9 . . . . . . .
但是,对于d
,在strcpy()
期间使用的内存分配较少,代码会调用不良行为。