我在大学测试中偶然发现了这个C代码,当我在Dev-C ++ 5.11编译器上测试它时,它打印出随机字符。我无法理解这段代码的工作原理或原因。有人可以开导我吗?
int main() {
char a[10] = "%s" ;
printf( a ) ;
}
答案 0 :(得分:1)
printf
函数签名是:
int printf(const char *format, ...);
它希望格式字符串作为第一个参数和可变数量的参数,这些参数是根据格式字符串中的格式说明符处理和打印的。你问题中的变量a
正在为它提供格式字符串。随机字符的原因是缺少格式说明符%s
的参数。以下将正确打印字符串:
printf( a, "Hello World!" );
这里可以看到格式说明符列表https://en.wikipedia.org/wiki/Printf_format_string
为什么要编译?
因为printf
接受的可变参数在运行时被处理。并非所有编译器都会编译时间检查以验证格式字符串的参数。即使他们这样做,他们最多也会发出警告,但仍然会编译程序。
答案 1 :(得分:1)
它使用字符串“%s”作为格式字符串,并使用未初始化的内存作为“数据”。
它做“某事”的唯一原因是因为编译器显然不够聪明,无法识别格式字符串需要一个参数并且提供了零参数。或者因为忽略了编译器警告和/或关闭了错误。
对于任何碰到这个问题的人来说只是一个FYI:“始终保持启用所有警告和错误并修复代码,直到它们消失为止”这不保证正确的行为,但确实使“神秘”问题不太可能发生。
答案 2 :(得分:1)
这个问题有两个部分:缺少引号和随机字符。
printf()
只是一个功能。您可以将字符串和其他值作为参数传递给函数。你不必使用文字。您可以同时使用char *a = "something"; printf(a)
(将变量作为参数传递)和printf("something")
(将字符串文字作为参数传递)。printf()
也是enter image description here。这意味着它可以接受任意数量的参数。您可以使用printf("hello world")
,printf("%s", "hello world")
甚至printf("%s %s", "hello", "world")
。一些较旧的编译器不会根据第一个参数(即格式字符串)验证您是否实际传递了正确数量的参数。这就是为什么你的代码编译即使它缺少一个参数。当程序运行时,代码遍历格式字符串,看到"%s"
并查找第二个参数以将其作为字符串打印。由于没有第二个参数,它基本上读取随机内存,你会得到垃圾字符。