Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
当c是字符时,使用scanf(";%d";,&;c)会发生什么?_C_Types - Fatal编程技术网

当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的结果相当清楚,一旦你完成了,你就不能再依赖任何可以预测的方式工作了