C 程序,用于输出的 printf() 和 strlen() 参数格式

C Program, printf() and strlen() argument format for output

为什么当我尝试 运行 这个 C 程序时我的终端会崩溃?

这是编程练习的说明。

#include <stdio.h>
#include <string.h>
 
int main(void)
{

char fname[20], lname[20];

printf("Please enter your first name:\n");
scanf("%s", fname);
printf("Please enter your last name:\n");
scanf("%s", lname);


printf("%s %s\n", fname, lname);
printf("%*d %*d\n", strlen(fname), strlen(lname));

printf("\n%s %s\n", fname, lname);
printf("%-*d %-*d", strlen(fname), strlen(lname));

return 0;
}

但是当我运行这样的时候它工作正常吗?我不明白为什么有两个格式说明符的控制语句后有 4 个参数。

#include <stdio.h>
#include <string.h>

int main(void)
{

char fname[20], lname[20];

printf("Please enter your first name:\n");
scanf("%s", fname);
printf("Please enter your last name:\n");
scanf("%s", lname);


printf("%s %s\n", fname, lname);
printf("%*d %*d\n", strlen(fname), strlen(fname), strlen(lname), 
strlen(lname));

printf("\n%s %s\n", fname, lname);
printf("%-*d %-*d", strlen(fname), strlen(lname), strlen(lname), 
strlen(lname));

return 0;
}

Salut,(为什么我不能在消息开头说“你好”?)

Why does my terminal crash when I attempt to run this C Program?

因为您没有在 printf 函数中提供足够的参数。突然 printf 试图读取一个禁止的内存区域

I do not understand why there are 4 arguments

也许这个例子可以帮助你理解:

#include <stdio.h>
#include <string.h>

int main(void)
{

char fname[20], lname[20];

int val = 9;
    printf("%d   stop\n", val);


val = 1;
    printf("%-3d stop\n", val);
    /*printf("%-6d stop\n", val);
    printf("%-9d stop\n", val);
    printf("%-12d stop\n", val);*/

val = 2;
    printf("%-*d stop\n", 3, val);
    /*printf("%-*d stop\n", 6, val);
    printf("%-*d stop\n", 9, val);
    printf("%-*d stop\n", 12, val);*/

char *fill = "##############################";
    printf("3%.*s stop\n", 3, fill);// 3 != 3-1
    /*printf("3%.*s stop\n", 6, fill);
    printf("3%.*s stop\n", 9, fill);
    printf("3%.*s stop\n", 12, fill);*/


return 0;
}

输出:

9   stop
1   stop
2   stop
3### stop

PS : 什么导致堆栈溢出错误?

问题是您在以下四个独立实例中调用了未定义行为

printf("%*d %*d\n", strlen(fname), strlen(fname), strlen(lname), 
strlen(lname));

strlen() 的函数原型是 size_t strlen(const char *s);,return 类型是 size_t 而不是 int

C11 Standard - 7.21.6.1 The fprintf function(p5) 指定:

... a field width, or precision, or both, may be indicated by an asterisk. In this case, an int argument supplies the field width or precision.

根据 C11 Standard - 7.21.6.1 The fprintf function(p8)"%*d" 中的 d 转换说明符指定:

The int argument is converted to signed decimal...

因此在您的格式字符串中,两个 '*' 字段宽度参数中的每一个所需的类型之间以及两个 d 转换说明符中的每一个之间存在不匹配。 (size_t 的转换说明符是 zu

C11 Standard - 7.21.6.1 The fprintf function(p9) 还提供:

If a conversion specification is invalid, the behavior is undefined. If any argument is not the correct type for the corresponding conversion specification, the behavior is undefined.

所以在调用未定义的行为之后程序做什么不是由标准指定的。任何事情都可能发生。它可能看起来正常打印,根本不打印任何东西,或 SegFault(或介于两者之间的任何东西)

参见:Undefined, unspecified and implementation-defined behavior and What is indeterminate behavior in C++ ? How is it different from undefined behavior? and Undefined behavior