我注意到在C中,我的布尔变量以某种我不理解的方式被改变了.
#include <stdio.h>
#include <stdbool.h>
int main(void) {
bool x, y;
printf("x: ");
scanf("%d", &x);
printf("x is %d\n", x);
printf("y: ");
scanf("%d", &y);
printf("x is %d\n", x);
printf("y is %d\n", y);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果我输入1for的x值和y(1在此示例中)的任何值:
Run Code Online (Sandbox Code Playgroud)x: 1 x is 1 y: 1 x is 0 y is 1
最后,y输出正确的原始值,但x神奇地改变0之间!
这不是一个问题,当用于输入x是0因为对于两个输出x和y如预期的是其各自的原始值.
请解释发生了什么!
您正在将boolean变量的地址传递给scanf()期望变量类型int*.这将调用未定义的行为,您可能会得到错误的结果甚至崩溃.
要解决此问题,请使用临时int存储扫描布尔值(作为int),然后将其存储为布尔变量.
演示
bool x, y;
int tmp;
printf("x: ");
scanf("%d", &tmp);
x = tmp;
Run Code Online (Sandbox Code Playgroud)
另一方面,打印boolan变量是不同的故事,其中布尔值被赋予int而没有任何问题并且正确打印.
好的,这里有两点.
bool是实现定义的.bool标准中没有为类型定义格式说明符.因此,尽管扫描值,传递的地址bool作为参数%d不好见注为所提供的类型是不一样的预期类型.
您可以使用中间整数,将值扫描到该值,并且(在验证或转换为true和falseMACRO之后)将结果分配回bool类型变量.
但是,对于打印,由于默认参数提升,a bool可以成为参数的候选者%d而没有问题.
注意:
%d与*scanf()预计的说法是一个int *,而不是提供一个bool*会导致 不确定的行为.
相关的,引用章节第7.21.6.2节第10段
[....]除非由a指示赋值抑制,否则
*转换的结果将放置在format尚未收到转换结果的参数后面的第一个参数所指向的对象中.如果此对象没有适当的类型,或者无法在对象中表示转换结果,则行为未定义.
A bool不是int.使用%d格式说明符读取它int是未定义的行为.
根据7.21.6.2 fscanfC标准第13段的功能:
如果转换规范无效,则行为未定义.
注意7.21.6.1fprintf第9段的功能说明:
如果转换规范无效,则行为未定义.如果任何参数不是相应转换规范的正确类型,则行为未定义.
但这是为了fprintf(),而不是fscanf().格式说明符对于scanf()函数来说要严格得多,因为没有参数提升允许一种格式,例如%d"为"工作"工作",char或者bool被提升为int一个printf()调用.该scanf()函数传递的地址参数的,如果有什么地址指的是从什么是每个格式说明符预期错误的大小,不确定的行为会导致-如不明原因更改另一个变量.
bool然后是一种不同的数据类型int,它可能是一个单字节.
scanf不是类型安全的函数,你用%d转换说明符告诉它需要指向int的指针,并且scanf无法知道你已经传递pointer to bool而不是指向int的指针.然后,您将获得未定义的行为.
clang编译生成警告:
source_file.c:8:16: warning: format specifies type 'int *' but the argument has type 'bool *' [-Wformat]
scanf("%d", &x);
~~ ^~
source_file.c:13:16: warning: format specifies type 'int *' but the argument has type 'bool *' [-Wformat]
scanf("%d", &y);
~~ ^~
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
628 次 |
| 最近记录: |