【问题标题】:"static char" vs. "char" in CC中的“静态字符”与“字符”
【发布时间】:2015-06-12 16:35:16
【问题描述】:

为了练习变量声明、占位符和 I/O 调用,我在正在学习的书中做了一个示例作业。但是,我一直遇到一个特殊的问题,即当我尝试声明多个字符变量用于输入时,即使编译器没有捕获任何语法错误,程序在执行时也只会返回一个字符变量.这是有问题的代码:

#include <stdio.h>

int main()

{
double penny=0.01;
double nickel=0.05;
double dime=0.1;
double quarter=0.25;

double value_of_pennies;
double value_of_nickels;
double value_of_dimes;
double value_of_quarters;
double TOTAL;
int P;
int N;
int D;
int Q;
char a,b; 

//used "static char" instead of "char", as only using the "char" type caused a formatting error where only the latter character entered in its input would appear

printf("Please enter initials> \n");
printf("First initial> \n");
scanf("%s", &a);
printf("Second initial> \n");
scanf("%s", &b);

//"%s" was used as the input placeholder for type "char"

printf("%c.%c., please enter the quantities of each type of the following coins.\n", a, b);


printf("Number of quarters> \n");
scanf("%d", &Q);
printf("Number of dimes> \n");
scanf("%d", &D);
printf("Number of nickels> \n");
scanf("%d", &N);
printf("Number of pennies> \n");
scanf("%d", &P);

printf("Okay, so you have: %d quarters, %d dimes, %d nickels, and %d pennies.\n", Q, D, N, P);

value_of_pennies=penny*P;
value_of_nickels=nickel*N;
value_of_dimes=dime*D;
value_of_quarters=quarter*Q;

TOTAL=value_of_quarters+value_of_dimes+value_of_nickels+value_of_pennies;

printf("The total value of the inserted coins is $%.2lf. Thank you.\n", TOTAL);

//total field width omitted as to not print out any leading spaces
return(0);
}

这是转录的输出(“a”、“e”和四个“1”是样本任意输入值:

Please enter initials>
First initial>
a
Second initial>
e
.e., please enter the quantities of each type of the following coins.
Number of quarters>
1
Number of dimes>
1
Number of nickels>
1
Number of pennies>
1
Okay, so you have: 1 quarters, 1 dimes, 1 nickels, and 1 pennies.
The total value of the inserted coins is $0.41. Thank you.

我输入了字符“a”和“e”作为字符变量“a”和“b”的输入值,但只显示了“e”。另一方面,如果我在“char”变量声明中放置“静态”,则输入的char 值都将显示在相关的打印调用中。

为了将来参考,我想问一下为什么会发生这样的事情,以及声明中“静态”一词的价值。

(顺便说一句,我知道我可以简单地将“value_of_(在此处插入硬币)”变量作为常量宏。)

【问题讨论】:

  • 我看不到您在代码中使用静态的位置。而且由于您只在 main 内部工作,静态不会有任何区别,除了使用 0 初始化变量。也许您将 static 称为静态以外的东西。
  • 整篇文章没有一个问号。
  • @bolov 等人:我没有声明我在此代码示例中放置了“静态”。我说,如果我插入了这个词,它就会按预期工作。我的问题是指我在此处发布的代码示例中的问题,特别是因为这对我来说是一个反复出现的问题。

标签: c static char scanf


【解决方案1】:

有这样的定义

char a,b; 

写一个类似的语句

scanf("%s", &a);
scanf("%s", &b);

调用undefined behaviour%s 不是 char 的格式说明符。使用错误的格式说明符会导致 UB。您应该使用%c扫描char

详细说明,

  • %s 格式说明符需要一个相应的参数,它是指向 char 数组的指针。它scans 多个字符,直到遇到space(空白字符,是迂腐的)或换行符或EOF。
  • %c 格式说明符需要一个相应的参数,它是指向 char 变量的指针。它只从输入缓冲区中读取一个char

因此,对于%s,如果您提供char 变量的地址,它将尝试访问超出分配的内存区域以写入扫描 数据,这将调用UB。

在继续之前,您可能需要阅读更多关于 printf()scanf()format specifiers 的内容。

【讨论】:

  • 不反对你所说的,但我很好奇——真的是UB吗?我觉得它应该定义得很好——scanf 将写入该指针,就好像它是格式中指定的类型的指针一样。例如,这会是 UB:uint32_t buffer[1024]; scanf("%s", buffer); 吗?
  • @mtijanic 我理解你的疑问,很高兴你问。您能否阅读C11 标准,章节§7.21.6.1,第 8 和第 9 段,说“参数应是指向字符类型数组的初始元素的指针”......和“如果任何参数不是对应转换规范的正确类型,行为未定义。"
  • @mtijanic 整个段落太大,无法在此处引用。希望你不会介意在网上阅读相同的内容。 :-)
  • 谢谢,这完美地回答了我的问题。现在我很好奇在这种情况下是否有任何主流编译器实际做了一些奇怪的事情。当我找到时间时,我会在所有这些上进行测试。再次感谢。
  • 实际上,我认为这只是一个 CYA,以防您传递大于预期的参数,例如 scanf("%d %d", MyLargerThanPointerStruct, &amp;myInt);,这显然会将结构的一部分解释为 int*,它是UB。由于其中一些是 UB,标准没有必要定义它的一部分,所以他们只是说一切都是 UB。再次感谢您提供 n1570 参考。
【解决方案2】:

您为char 使用了错误的格式说明符。 char 使用 %c 而不是 %s。至于static,我对你的问题有点困惑。您在评论中说您正在使用static char,但我没有看到任何声明为static char 的变量。

【讨论】:

    猜你喜欢
    • 2020-07-31
    • 1970-01-01
    • 2014-11-21
    • 1970-01-01
    • 1970-01-01
    • 2019-07-06
    • 1970-01-01
    • 1970-01-01
    • 2020-06-14
    相关资源
    最近更新 更多