有关C参数促销的问题

时间:2011-05-15 13:57:42

标签: c types specifier

好吧,实际上我已经研究了如何使用循环来使我的代码更高效,这样我就可以使用一个特殊的代码块,这些代码块应该重复而不必一遍又一遍地输入,并且在尝试使用我之后到目前为止,我已经学会了编程,我觉得现在是时候进入下一章学习如何使用控制语句来学习如何指导程序做出决定。

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


:一种。字符类型

  1. 我从C primer Plus 5th ed:
  2. 一书中提取以下内容
      

    奇怪的是,C对待角色   constans类型为int而不是。{   char。例如,在ASCII系统上   使用32位int和8位char   ,代码:

    char grade = 'B';
    
         

    表示'B'作为数值   66以32位为单位存储,grade   结束了66存储ub ab 8位   单元。这种性格特征   常量使得定义成为可能   一个字符常量,例如'FATE',   带有四个独立的8位ASCII码   存储在32位单元中。但是,   试图分配这样一个角色   常量为char变量结果   仅使用最后8位,   所以变量得到值'E'

    1. 所以我读完之后接下来要做的就是按照它提到的内容,即尝试将FATE存储在带有char grade的变量上并尝试编译看看它将使用printf()存储什么,但不是打印出来的字符'E',而是获得的是'F'

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

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

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

    5. 但不是打印356,而是提供100,这是最后的8位值。

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


    7. B中。 Int和浮动类型

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

      2. 这也发生在浮点类型上,当传递float类型的浮点数时,它将被转换为double类型,这就是为什么没有说明符的原因float类型,但%f只有double%Lf只有long double

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

4 个答案:

答案 0 :(得分:2)

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

  

字符常量的这一特性使得可以定义一个字符常量,例如'FATE',其中四个独立的8位ASCII代码以32位为单位存储。但是,尝试将这样的字符常量赋给char变量仅导致使用的最后8位,因此变量的值为'E'。

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

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

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

  

如果表示被调用函数的表达式具有不包含原型的类型,则对每个参数执行整数提升,并将类型为float的参数提升为double。这些被称为默认参数促销。

和C99 6.5.2.2/7“函数调用”

  

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

因此,实际上,将printf()传递给float是不可能的 - 它将始终被提升为printf()。这就是为什么浮点值的格式说明符期望double

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

答案 1 :(得分:1)

首先,char 按照定义正好是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位,因此它会切断所有其他位。

答案 2 :(得分:0)

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

7。)一个char只能容纳8位,所以在你将int赋给char变量的那一刻,其他所有内容都会被截断,以后永远不能从char变量中恢复。

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

答案 3 :(得分: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位。