当c是字符时,使用scanf(";%d";,&;c)会发生什么?
代码如下所示:当c是字符时,使用scanf(";%d";,&;c)会发生什么?,c,types,C,Types,代码如下所示: char c; scanf("%d", &c); char ch = 1; (i&j)? printf("yes") : printf("no"); 输入3 我的猜测是,当输入3时,它是类型int 然后键入降级为char并分配给c 我在说明符%d中打印c的值,结果为3,似乎与预期一致 但是用说明符%c打印c的值会在终端上产生一个空白;这是一个问题……(1) 为了进行更多测试,我进一步声明了一个类型为char的变量,并将其初始化如下: char
char c;
scanf("%d", &c);
char ch = 1;
(i&j)? printf("yes") : printf("no");
输入3
我的猜测是,当输入3
时,它是类型int
然后键入降级为char并分配给
c
我在说明符%d
中打印c
的值,结果为3,似乎与预期一致但是用说明符
%c
打印c
的值会在终端上产生一个空白;这是一个问题……(1)为了进行更多测试,我进一步声明了一个类型为char的变量,并将其初始化如下:
char c;
scanf("%d", &c);
char ch = 1;
(i&j)? printf("yes") : printf("no");
测试是这样的:
char c;
scanf("%d", &c);
char ch = 1;
(i&j)? printf("yes") : printf("no");
结果是“否”我打印出
I&j
的值,它是0
但是
1和3
应该是1
?这是另一个问题……(2)我的问题是(1)和(2)我在那里看不到变量
j
。因此,i&j
将为0。是的,如果i==1
和j==3
那么i&j==1
我在那里看不到变量j
。因此,i&j
将为0。是的,如果i==1
和j==3
,那么i&j==1
(i&j)?printf(“是”):printf(“否”)语句给出的输出是,对于i=1和j=3 对于(1)问题,ASCII 3是针对无法打印的STX字符。(i&j)?printf(“是”):printf(“否”)
语句给出的输出是,对于i=1和j=3
对于(1)问题,ASCII 3是针对不可打印的STX字符。您实际上是在调用未定义的行为来执行此操作 通过使用格式字符串
%d
,您告诉scanf
希望将int*
作为参数,并向其传递一个指向单个字符的指针。请记住,scanf
除了在格式字符串中输入的内容外,没有关于传递内容的更多类型信息
这将导致scanf
试图在指向char
大小保留的地址处向内存写入int
大小的值,可能(对于大多数体系结构而言)写入越界
在调用UB之后,所有的赌注都将在您的进一步计算上被取消。您实际上是在调用未定义的行为来执行此操作 通过使用格式字符串
%d
,您告诉scanf
希望将int*
作为参数,并向其传递一个指向单个字符的指针。请记住,scanf
除了在格式字符串中输入的内容外,没有关于传递内容的更多类型信息
这将导致scanf
试图在指向char
大小保留的地址处向内存写入int
大小的值,可能(对于大多数体系结构而言)写入越界
调用UB后,所有的赌注都将在您的进一步计算中取消。假设scanf()不是一个varargs函数,而是一个普通函数,将指向int的指针作为第二个参数:
int noscanf(char *format, int *ptr)
{
*ptr = 42;
return 1;
}
int main(void)
{
char ch;
int rc;
// This should *at least* give a warning ...
rc = noscanf("Haha!" , &ch);
return 0;
}
现在,scanf()是一个varargs函数。scanf()确定(指针)参数类型的唯一方法是检查格式字符串。%d表示:下一个参数应该是指向int的指针。因此scanf可以愉快地将sizeof(int)
字节写入*ptr。假设scanf()不是varargs函数,而是一个普通函数,将指向int的指针作为第二个参数:
int noscanf(char *format, int *ptr)
{
*ptr = 42;
return 1;
}
int main(void)
{
char ch;
int rc;
// This should *at least* give a warning ...
rc = noscanf("Haha!" , &ch);
return 0;
}
现在,scanf()是一个varargs函数。scanf()确定(指针)参数类型的唯一方法是检查格式字符串。a%d的意思是:下一个参数应该是指向int的指针。所以scanf可以很高兴地将
sizeof(int)
字节写入*ptr。对不起,我问题中的j在上面声明了ch…只是键入对不起,我问题中的j在上面声明了ch…只是键入,所以没有发生类型升级/降级,但正在覆盖?并说是这样;但我的系统是大还是小endian重要吗?什么时候会像用4字节整数中的最小字节覆盖1字节一样进行覆盖?如果是这样,ch(1)和c(3)应该是1?@J.c.是的,它会无情地覆盖该地址的内存,不会发生任何类型的类型自适应。从逻辑上讲,我会说你应该在一台小小的endian机器上看到你的char中的值3
,但是UB的结果相当清楚,一旦你完成了,你就不能再依靠任何可以预测的方式工作了。我很想给你投票,但我不能因为这个:“假设是32位整数,它将结果写入4个字节。。。“假设您提到printf可能试图将int
值写入足够大的空间以存储char
值,这可能导致写入超出char
变量的范围。这在不提及数字的情况下是有意义的。然而,断言32位整数是4字节是错误的。考虑<代码> CARYBIT==32 & & sieOf(int)=1</Calp>。@ MuffiFabelValk,你是正确的,删除了答案中的大小假设,因为它们只是把事情搞糊涂了。它们是我最初写的一个“内存转储示例”的遗骸,但由于太冗长,决定将其删除。因此,没有发生类型pro/降级,但正在覆盖?并说确实如此;但我的系统是大还是小endian重要吗?什么时候会像用4字节整数中的最小字节覆盖1字节一样进行覆盖?如果是这样,ch(1)和c(3)应该是1?@J.c.是的,它会无情地覆盖该地址的内存,不会发生任何类型的类型自适应。从逻辑上讲,我会说你应该在一台小小的endian机器上看到char中的值3
,但是UB的结果相当清楚,一旦你完成了,你就不能再依赖任何可以预测的方式工作了