布尔类型的值在C中更改

时间:2017-08-31 10:57:06

标签: c boolean scanf

我注意到在C中,我的布尔变量以某种我不明白的方式改变了。

    var notification = {
TableName: "Tablename", 
KeyConditionExpression:"#userId =:userid and #datetime <=:datetime", 
ScanIndexForward: false,
ExpressionAttributeNames: {
    "#userId": "userId",
    "#datetime":"datetime"
},
ExpressionAttributeValues: {
    ":userid"    :userId,
    ":datetime"  :datetime
}
}; 

docClient.query(notification, function(err, result) {

if (err) {
    context.succeed({success: false, message : JSON.stringify(err, null, 2),method:"notification",type:type});
}else{

    result = result.Items;

    if (result.length>0) { 
        for(var i=0;i<result.length;i++){
            result[k]['CafeDetail']=getDetail(result[k].CafeID,function (data) { 

            });

            if (k ==(result.length -1)) { 
                context.succeed({success: true,data:result, message : "Notification list",method:"notification",type:type}); 
            }

        }
    }

}

});

function getDetail(CafeID,callback) {
    var param = {
        TableName: "Tablename",
        ProjectionExpression:"CafeName,Cafe_MainImage",
        KeyConditionExpression:"CafeID =:cafeID", 
        ExpressionAttributeValues: {
            ":cafeID"    :CafeID
        }
    };

    docClient.query(param, function(err, CafeDetail) {
        if (err) {
            console.log (err)
            callback(err);
        } else {
            callback(CafeDetail.Items);
            console.log(CafeDetail.Items);
        }
    });
} 

如果我为#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; } 输入1的值,并为此示例中的xy)输入任何值:

1

最后,x: 1 x is 1 y: 1 x is 0 y is 1 输出正确的原始值,但y神奇地更改为x

0的输入为x时,这不是问题,因为0x的输出都是预期的原始值。

请解释发生了什么!

7 个答案:

答案 0 :(得分:8)

您将布尔变量的地址传递给scanf(),其中需要int*类型的变量。这将调用未定义的行为,您可能会得到错误的结果甚至崩溃。

要解决此问题,请使用临时int来存储布尔值的扫描(作为int),然后将其存储为布尔变量。

<强>演示

bool x, y;
int tmp;

printf("x: ");
scanf("%d", &tmp);
x = tmp;

另一方面,打印boolan变量是不同的故事,其中布尔值被引导到int而没有任何问题并正确打印。

答案 1 :(得分:7)

好的,这里有两点。

  1. bool的大小是实现定义的。
  2. 标准中没有为bool类型定义格式说明符。
  3. 因此,当扫描值时,将bool的地址作为%d的参数传递为,请参阅注释作为提供的type与预期类型不同。

    您可以使用中间整数,将值扫描到该值,并且(在验证或转换为truefalse MACRO之后)将结果分配回bool类型变量。

    但是,对于打印,由于默认参数提升,bool可以成为%d参数的候选者而没有问题。

    注意:

    带有%d

    *scanf()期望参数为int *,而提供bool*会导致undefined behavior

    相关,引用章节§7.21.6.2,第10段

      

    [....]除非*表示分配抑制,否则   转换结果放在下面第一个参数指向的对象中   尚未收到转换结果的format参数。 如果是这个对象   没有合适的类型,或者无法表示转换结果   在对象中,行为未定义。

答案 2 :(得分:7)

bool不是int。使用%d的{​​{1}}格式说明符读取它是未定义的行为。

7.21.6.2 int函数,第13段of the C standard

  

如果转换规范无效,则行为未定义。

请注意 7.21.6.1 fscanf函数第9段规定:

  

如果转换规范无效,则行为为   未定义。如果任何参数不是正确的类型   相应的转换规范,行为是   未定义。

但是fprintf的那个,而不是fprintf()。对于fscanf()函数,格式说明符要严格得多,因为没有参数提升 允许使用scanf()到&#34;工作&#34;等格式。对于%dcharbool呼叫被提升为intprintf()函数传递参数的地址,如果地址引用的是与格式说明符所预期的大小不一致,将导致未定义的行为 - 例如,未解释的更改另一个变量。

答案 3 :(得分:5)

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);
          ~~   ^~

答案 4 :(得分:3)

所有其他答案在技术上都是正确的,但并不能真正帮到你。

你的主要问题不是x或y,而是你自己无法调试最琐碎的编程问题。这很容易修复 - 启用编译器警告(如果使用gcc,添加-Wall选项)。编译器会告诉你这样的错误,还有很多错误。无需每次都进行stackoverflow:)

答案 5 :(得分:0)

考虑以下计划

#include <stdio.h>
#include <stdbool.h>

int main(void) {
  int z, s;
  printf("int  z: %p\nint  s: %p\n", &z, &s);

  bool x, y;
  printf("bool x: %p\nbool y: %p\n", &x, &y);

  return 0;
}

输出:

int  z: 0028FF3C
int  s: 0028FF38
bool x: 0028FF37
bool y: 0028FF36

现在,在zs之间存在4个字节的差异,这是我案例中int的大小。

xy之间,只有1个字节的差异。

现在有了这一行:

scanf("%d", &y);

您告诉我%dscanf您需要一个4字节长的输入,int

如果int来自地址y并且输入0028FF36,则0x0001将存储00028FF37将是x存储在65535。这就是y的地址。

您可以使用其他输入值进行检查。例如,如果您将0xFFFF提供给x 0xF,则255将为USER(),即CURRENT_USER()十进制。

答案 6 :(得分:0)

或者可能(如果输入字符串包含true或1将返回1 - 否则0

int getBool(char *message)
{
    char input[20];
    printf("%s", message);
    fgets(input, 20, stdin);
    return !!strstr(strlwr(input), "true") || strtol(input, NULL, 10);
}