微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

类型转换对 printf 函数的影响

如何解决类型转换对 printf 函数的影响

这是我书中的一个问题,

enter image description here

其实我也不知道对printf函数会有什么影响,所以就尝试了C lang原系统中的语句。这是我的代码

#include <stdio.h>

void main() {
  int x = 4;
  printf("%hi\n",x);
  printf("%hu\n",x);
  printf("%i\n",x);
  printf("%u\n",x);
  printf("%li\n",x);
  printf("%lu\n",x);
}

Try it online!

所以,输出很简单。但是,这真的是解决上述问题的方法吗?

解决方法

这道题有很多问题,不适合教授 C。

首先,要解决这个问题,我们必须假设使用了非标准的 C 实现。在标准 C 中,%x 是完整的转换规范,所以 %xu%xd 不能;转换规范已在 ud 之前结束。并且在转换规范中使用 z 会干扰其对 size_t 的标准使用。

尽管如此,我们假设这个 C 变体没有那些标准的转换规范,而是使用表中显示的那些,但这个 C 变体在其他方面符合 C 标准,但改动很小。

我们的下一个问题是,在 Y num = 42; 中,我们有一个普通的 Y,而不是表中显示的 signed Yunsigned Y。让我们假设 signed Y 是有意的。

那么 num 是一个有符号的四位整数。它可以表示的最大值是 01112 = 710。所以它不能代表 42。尝试用 42 初始化它会导致 C 2018 6.3.1.3 指定的转换,部分说明:

否则,新类型是有符号的,值不能在其中表示;要么结果是实现定义的,要么引发实现定义的信号。

结果是我们不知道num中的值是什么,甚至不知道程序是否继续执行;它可能会捕获并终止。

好吧,让我们假设这个实现只采用值的低位。 42 是 1010102,所以它的低四位是 1010。所以如果 num 中的位是 1010,那么它是负数。 C 标准允许使用多种表示负数的方法,但我们将假设最常见的一种,即二进制补码,因此 num 中的位 1010 表示 -6。

现在,我们进入 printf 语句。除了问题文本显示 Printf,这不是由 C 标准定义的。 (你确定这个问题与 C 代码有关吗?)让我们假设它的意思是 printf

printf("%xu",num);中,如果转换规范应该像标准C中的那样工作,那么相应的参数应该是一个unsigned X值,它已经被提升为int 用于函数调用。作为两位无符号整数,unsigned X 可以表示 0、1、2 或 3。未定义传递它 -6。所以我们不知道程序会打印什么。它可能只需要低两位,10,并打印“2”。或者它可能使用所有位并打印“-6”。这两者都符合以下要求:printf 的行为与为 unsigned X 可表示的范围内的值指定的一样。

printf("%xd",num);printf("%yu",num);中,存在同样的问题。

printf("%yd",num); 中,我们为 signed Y 转换规范正确传递了 signed Y 值,因此打印了“-6”。

然后 printf("%zu",num); 有同样的问题,类型的值不匹配。

最后,在 printf("%zd",num); 中,值再次处于正确的范围内,并打印“-6”。

从我们必须做出的所有假设以及未定义行为的所有点来看,您可以看到这是一次糟糕的练习。你应该质疑这本书的质量以及使用它的任何学校的质量。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。