3

好吧实际上我已经研究了如何使用循环来使我的代码更高效,这样我就可以使用应该重复的特定代码块而无需一遍又一遍地输入它,并且在尝试使用我学到的东西之后编程太远了,我觉得是时候进入下一章学习如何使用控制语句来学习如何指示程序做出决定了。

但问题是,在我推进自己之前,我还有一些问题需要任何专家帮助解决以前的问题。实际上它是关于数据类型的。


A. 字符类型

  1. 我从 C 入门书 Plus 5th ed 中提取以下内容:

有点奇怪的是,C 将字符常量视为类型int而不是 char. 例如,在具有 32 位int和 8 位的 ASCII 系统上char ,代码:

char grade = 'B';

表示'B'为存储在 32 位单元中的数值 66,grade 以 66 存储的 ub ab 8 位单元结束。字符常量的这一特性使得定义一个字符常量成为可能,例如'FATE',在一个 32 位单元中存储四个单独的 8 位 ASCII 代码。但是,尝试将这样的字符常量分配给char变量会导致仅使用最后 8 位,因此变量会获取值'E'

  1. 因此,我在阅读完这篇文章后做的下一件事当然是按照它提到的内容进行操作,即我尝试将单词存储在FATE变量中char grade并尝试编译并查看将使用 存储printf()的内容,而不是'E'打印字符出来,我得到的是'F'

  2. 这是否意味着书中有一些错误?或者有什么我误解了吗?

  3. 从上面的句子中,有一行说 C 将字符常量视为 type int。因此,为了尝试一下,我为该类型分配了一个大于255, (ex 356) 的数字char

  4. 由于356在 32 位范围内int(我正在运行 Windows 7),因此我希望356在使用说明符时它会打印出来%d

  5. 但它不是打印356,而是给我100,这是最后 8 位值。

  6. 为什么会这样?我想char == int == 32-bits?(虽然它确实在 char 只是一个字节之前提到)。


B. Int 和 Floating 类型

  1. 我知道当short类型变量中的数字存储传递给可变参数函数或任何隐式原型函数时,它将自动提升为int类型。

  2. 浮点类型也会发生这种情况,当传递带有类型的浮点数时float,它将被转换为double类型,这就是为什么没有float类型说明符而只有%ffordouble%Lffor 的原因long double

  3. 但是为什么有一个short类型说明符,虽然它也被提升但不是float类型?为什么他们不只是给float带有修饰符之类的类型的说明符%hf?这背后有什么逻辑或技术吗?

4

4 回答 4

2

一个问题中有很多问题......以下是一对夫妇的答案:

字符常量的这一特性使得定义诸如 'FATE' 之类的字符常量成为可能,其中四个单独的 8 位 ASCII 代码存储在一个 32 位单元中。但是,尝试将这样的字符常量分配给 char 变量会导致仅使用最后 8 位,因此变量获取值“E”。

这实际上是实现定义的行为。所以是的,书中有一个错误。许多关于 C 的书籍都假设世界上唯一的 C 编译器是作者在测试示例时使用的编译器。

作者使用的编译器将“FATE”中的字符视为整数的字节,“F”是最重要的字节,“E”是最不重要的字节。您的编译器将文字中的字符视为整数的字节,其中“F”是最低有效字节,“E”是最高有效字节。例如,第一种方法是 MSVC 如何处理值,而 MinGW(针对 Windows 的 GCC 编译器)以第二种方式处理文字。

就期望没有格式说明符而言,在printf()期望float的说明符上double- 这是因为传递给printf()用于格式化的值是变量参数列表的一部分(...inprintf()的原型)。没有关于这些参数的类型信息,因此正如您所提到的,编译器必须始终提升它们(来自 C99 6.5.2.2/6“函数调用”):

如果表示被调用函数的表达式的类型不包含原型,则对每个参数执行整数提升,而浮点类型的参数将提升为双精度。这些称为默认参数提升。

和 C99 6.5.2.2/7“函数调用”

函数原型声明器中的省略号会导致参数类型转换在最后一个声明的参数之后停止。默认参数提升是在尾随参数上执行的。

所以实际上,不可能将 a 传递floatprintf()- 它总是会被提升为double. 这就是为什么浮点值的格式说明符需要一个double.

同样由于将应用于 的自动提升,short老实说,我不确定h格式化 a 的说明符是否short是绝对必要的(尽管n如果您想获取写入流的字符数,则必须与说明符一起使用放在一个short)。它可能在 C 中,因为它需要在那里支持说明n符、历史原因或我没有想到的东西。

于 2011-05-15T18:46:17.123 回答
1

首先,根据定义char,a正好是 1 个字节宽。然后标准或多或少说尺寸应该是:

sizeof(char) <= sizeof(short) <= sizeof(int) <= sizeof(long)

确切的大小因系统和编译器而异(除了char),但在 32 位 Windows 上,GCC 和 VC 的大小是(AFAIK):

sizeof(short) == 2 (byte)
sizeof(int) == sizeof(long) == 4 (byte)

在这种情况下,您对“F”与“E”的观察是一个典型的字节序问题(小字节序与大字节序,“单词”如何存储在内存中)。

现在你的价值会发生什么变化?你有一个 8 位宽的变量。您分配了一个更大的值('FATE'356),但编译器知道它只允许存储 8 位,因此它会切断所有其他位。

于 2011-05-15T14:18:34.430 回答
0

char是 1 个字节长。一个字节的位长可以是 8、16、32 位。在通用计算机中,字符的位长通常为 8 位。所以字符可以表示的最大数量取决于字符的位长。要检查字符检查头文件的位长,它在此文件limits.h中定义。CHAR_BIT

char x = 'FATE'可能取决于机器/编译器将解释 'FATE' 的字节顺序。所以这取决于系统/编译器。有人请确认/纠正这一点。

如果您的系统有 8 位字节,那么,当您这样做时,c = 360只有 360 的二进制表示的低 8 位将存储在变量中,因为char数据总是分配 1 个字节的存储空间。所以%d将打印 100,因为当您在变量中分配值时,高位丢失了,剩下的只有低 8 位。

于 2011-05-15T14:24:38.850 回答
0

回答: 3.) 这是由于大端和小端 CPU 架构的不同字节顺序。您在小端(即 x86)上获得第一个字节,在大端 CPU(即 PPC)上获得最后一个字节。实际上,当完成从 int 到 char 的转换但 int 中的字符以相反的顺序存储时,您总是得到最低的 8 位。

7.) 一个 char 只能容纳 8 位,因此在您将 int 分配给 char 变量的那一刻,其他所有内容都会被截断,以后永远无法从 char 变量中恢复。

To B: 3.) 您有时可能只想打印 int 变量的最低 16 位,而不管高半部分是什么。为了某些优化,将多个整数值打包在一个变量中并不罕见。这适用于整数类型,但对于不直接支持按位运算的浮点类型没有多大意义,这可能是 printf 中没有单独的 float 类型说明符的原因。

于 2011-05-15T14:17:39.953 回答