RError.com

RError.com Logo RError.com Logo

RError.com Navigation

  • 主页

Mobile menu

Close
  • 主页
  • 系统&网络
    • 热门问题
    • 最新问题
    • 标签
  • Ubuntu
    • 热门问题
    • 最新问题
    • 标签
  • 帮助
主页 / 问题 / 627522
Accepted
MaximPro
MaximPro
Asked:2020-02-14 07:47:47 +0000 UTC2020-02-14 07:47:47 +0000 UTC 2020-02-14 07:47:47 +0000 UTC

隐式数据类型转换

  • 772

似乎这里没有什么复杂的:

int a = 5; /// Тут при сложении int + float логично получить float, но мы получаем double (почему?)
float b = 3.14; /// когда идет присвоение смотрится тип и к нему притирается ответ (тут все ясно)
float c = a + b; /// Не ясно когда выполняются операции между типами иногда не понимаешь какой тип в результате операции мы имеем

问题是在不同情况下转换后会获得哪些数据类型:

char+int
char+float
char+double
int+float
int+double
char+unsigned char
int+unsigned int
float+unsigned float
итд

PS我没有在互联网上找到明确的答案

c
  • 2 2 个回答
  • 10 Views

2 个回答

  • Voted
  1. Best Answer
    AnT stands with Russia
    2020-02-14T08:15:37Z2020-02-14T08:15:37Z

    在这里,当添加 int + float 时,得到一个 float 是合乎逻辑的,但是我们得到一个 double(为什么?)

    我不明白你在说什么样的“这里”,但添加int后,float结果完全一样float。在你下面的例子中,你写

    int+float // операнд типа int приводится к типу float
    

    这是真的(并且与你上面写的相矛盾)。

    在语言中 自恐龙时代以来(尽管可能在 K&R 中),类型操作数确实已自动float转换为 type double,但那些日子早已一去不复返了。float在标准化 C 中从来没有出现过这种情况,尽管在调用类型参数仍被转换为类型的非原型或可变参数函数时,这种行为的回声仍然存在double。

    无法在互联网上找到明确的答案。

    尽管该算法是多级的,但该行为在语言标准中进行了描述。在我的[简化]翻译中

    • 如果其中一个操作数的类型为long double,则将第二个操作数转换为类型long double
    • 否则,如果其中一个操作数的类型为double,则第二个操作数被强制转换为 typedouble
    • 否则,如果其中一个操作数的类型为float,则第二个操作数被强制转换为 typefloat
    • 否则,两个操作数都将进行整数提升1并进一步考虑提升后的类型。

      • 如果两个操作数属于同一类型,则什么也不做。
      • 否则,如果两个操作数都是有符号类型或两个操作数都是无符号类型,则将具有较低等级2的操作数转换为具有较高等级的操作数的类型。
      • 否则,如果一个操作数具有无符号类型且秩大于或等于第二个操作数的秩,则将有符号操作数转换为无符号操作数的类型。
      • 否则,如果有符号操作数的取值范围足以表示无符号操作数的所有值,则将无符号操作数转换为有符号操作数的类型。
      • 否则,两个操作数都转换为对应于有符号操作数类型3的无符号类型。

    1)整数提升- “小”整数类型_Bool, [signed/unsigned] char,[signed/unsigned] short到类型int(如果范围int足够)或到unsigned int(否则)的转换。

    2)排名实际上是该类型在整数类型的“自然”序列中的位置:_Bool, char, short, int, long, long long。(前缀signed/unsigned不影响排名。)

    3)表示类型int对应类型unsigned int,类型long对应类型unsigned long等。

    很容易看出,从形式上看,确定结果类型的机制是平台相关的,因为它依赖于不同整数类型的可表示值范围的比例。

    例如,对于关于 的类型的问题,不可能给出一个普遍明确的答案char+int。在我们习惯使用 8 位char和 32 位的平台上,int它将是int. 但是,在具有无符号 16 位char和 16 位的更奇特的平台上int,它将是unsigned int.


    关于评论中提出的话题:

    为什么这样做而不是相反?云中暗水。然而,作为一个在我的代码中狂热坚持“使用无符号类型来表示自然无符号值”原则的人,我个人看到在我的代码中绝大多数整数值都是无符号的。尽管在计算几何领域工作时,我经常遇到非组合问题和自然非正值(坐标等),但程序通常以组合学为主,而且大多数其中的值自然是非负的。并且在有符号值占主导地位的区域,混合有符号和无符号操作数的问题通常根本不会出现。因此,我选择在混合 "int与unsigned这个操作看起来很自然。

    您还可以引用“C99 基本原理”中关于为什么整数提升以另一种方式进行并且更喜欢将小型类型扩展为带符号 int的相关主题。请注意,这里也提到了“ intvs. ”问题,UNIX 编译器总是首选无符号转换。unsigned(我的翻译。)

    从 K&R 的发布到 C89 的开发,在整数提升规则方面的不同实现之间存在严重差异。实现分为两个不同的阵营,大致可以描述为Unsigned Preserving和Meaning Preserving。这些方法之间的区别在于类型的处理unsigned char以及unsigned short它们在整数提升过程中的扩展。(所做的决定也会影响常量的类型。)

    unsigned保留方法涉及将两个小的 unsigned 类型扩展到unsigned int. 这是一个独立于运行时环境的简单规则。

    值保留方法涉及扩展这些类型,signed int如果该类型可以表示原始类型的所有值,unsigned int否则。因此,如果在某些运行时short它被表示为小于 的东西int,那么它unsigned short会变成int. 否则就变成了unsigned int。

    在绝大多数情况下,这两种方法都会给出相同的答案。在更多情况下,在基于二进制补码算法和发生符号溢出时使用“静默”值换行的实现中,两者都会导致相同的结果。也就是说,在大多数现代实现中。在此类实现中,仅当同时满足两个条件时才会出现方法之间的差异:

    1. unsigned char涉及或unsigned short产生int带有符号位集的宽度结果的表达式。那些。它要么是对这些类型之一的一元运算,要么是第二个操作数是一种int或多种“较窄”类型的二元运算。

    2. 上述表达式的结果用于符号重要的上下文中

      • sizeof(int) < sizeof(long)结果应该扩展为类型long

      • 是实现中的左操作数>>,其中移位是算术

      • 是任何操作数/, %, <, <=,>或>=.

    在这种情况下,解释确实存在歧义。结果可以说是有问题的 signed,因为可以对 signed 和 unsigned 解释进行论证。每次当unsigned int和signed int在二元运算符的相对两侧相遇时,都会出现相同的歧义,同时signed int具有负值。在解决这种歧义方面,这两种选择都不比另一种更好或更差。如果负片突然signed int变成一个巨大的负片unsigned int,这可能会让某些人大吃一惊。反之亦然,这可能正是有经验的程序员想要得到的。(当然,所有这些歧义都可以通过谨慎使用强制转换来避免。)

    Unsigned Preserving方法的规则大大增加了它unsigned int遇到的情况的数量signed int,导致可疑的签名结果,而Value Preserving方法的规则最大限度地减少了这种冲突。出于这个原因,人们发现保值方法对于新手或粗心的程序员来说更安全。经过长时间的讨论,C89 委员会决定支持保值方法,尽管当时 UNIX 系统的 C 编译器已经朝着无符号保持方法发展。

    • 10
  2. Vlad from Moscow
    2020-02-14T08:08:15Z2020-02-14T08:08:15Z

    答案可以在 C 标准或专门讨论 C 标准的论坛中找到,尤其是位于 google.com 或 isocpp.org 的论坛。

    为了计算运算操作数的一般类型,将所谓的普通算术转换应用于算术类型。

    比如在二元运算符+的描述中,C标准中是这样写的(6.5.6加法运算符)

    4 如果两个操作数都是算术类型,则对它们执行通常的算术转换。

    AND(标准 C,6.3.1.8 常用算术转换)

    1 许多期望算术类型操作数的运算符以类似的方式导致转换和产生结果类型。目的是确定操作数和结果的通用实数类型。对于指定的操作数,每个操作数在不改变类型域的情况下被转换为一个类型,其对应的实型是普通实型。除非另有明确说明,否则公共实型也是结果对应的实型,如果操作数相同,则其类型域为操作数的类型域,否则为复数。这种模式称为通常的算术转换:

    首先,如果任一操作数的对应实数类型为 long double,则将另一个操作数转换为对应实数类型为 long double 的类型,不改变类型域。

    否则,如果任一操作数的对应实数类型为双精度,则另一个操作数将在不更改类型域的情况下转换为其对应实数类型为双精度的类型。

    否则,如果任一操作数的对应实数类型为 float,则将另一个操作数转换为对应实数类型为 float 的类型,不改变类型域。

    否则,对两个操作数执行整数提升。然后将以下规则应用于提升的操作数:

    如果两个操作数具有相同的类型,则不需要进一步转换。

    否则,如果两个操作数都具有带符号整数类型或都具有无符号整数类型,则具有较小整数转换等级的操作数将转换为具有较高等级的操作数的类型。

    否则,如果无符号整数类型的操作数的秩大于或等于另一个操作数类型的秩,则将有符号整数类型的操作数转换为无符号整数类型的操作数的类型。

    否则,如果有符号整数类型操作数的类型可以表示无符号整数类型操作数类型的所有值,则将无符号整数类型操作数转换为有符号整数类型操作数类型.

    否则,两个操作数都转换为与带符号整数类型的操作数类型对应的无符号整数类型。

    特别是,如上所述

    否则,如果任一操作数的对应实数类型为 float,则将另一个操作数转换为对应实数类型为 float 的类型,不改变类型域

    也就是说,在这段代码中

    int a = 5;
    float b = 3.14;
    float c = a + b;
    

    a表达式的操作数a + b被转换为类型float,表达式的结果也是类型float。

    如果表达式中没有浮点操作数,则

    否则,对两个操作数执行整数提升。然后将以下规则应用于提升的操作数

    例如,

    char+int // операнд типа char приводится к типу int 
    char+float // операнд типа char приводится к типу float 
    char+double // операнд типа char приводится к типу double 
    int+float // операнд типа int приводится к типу float 
    int+double // операнд типа int приводится к типу double
    char+unsigned char // оба операндв приводятся к типу int
    int+unsigned int // операнд типа int приводится к типу unsigned int 
    float+unsigned float // тип unsigned float отсутствует; ошибка компиляции
    

    关于这个例子

    char+unsigned char // оба операндв приводятся к типу int
    

    我想补充一点,根据编译器选项集,类型char可以表现为类型signed char或类型。unsigned char

    这是一个关于将整数提升应用于整数类型的影响的示例

    unsigned short a = 5; 
    unsigned short b = 10; 
    

    上面声明的变量的值a - b 将是一个负数,因为表达式中的两个变量都将被转换为 type int。而x - y下面声明的变量的值将是一个正数。

    unsigned int x = 5; 
    unsigned int y = 10;
    
    • 3

相关问题

Sidebar

Stats

  • 问题 10021
  • Answers 30001
  • 最佳答案 8000
  • 用户 6900
  • 常问
  • 回答
  • Marko Smith

    Python 3.6 - 安装 MySQL (Windows)

    • 1 个回答
  • Marko Smith

    C++ 编写程序“计算单个岛屿”。填充一个二维数组 12x12 0 和 1

    • 2 个回答
  • Marko Smith

    返回指针的函数

    • 1 个回答
  • Marko Smith

    我使用 django 管理面板添加图像,但它没有显示

    • 1 个回答
  • Marko Smith

    这些条目是什么意思,它们的完整等效项是什么样的

    • 2 个回答
  • Marko Smith

    浏览器仍然缓存文件数据

    • 1 个回答
  • Marko Smith

    在 Excel VBA 中激活工作表的问题

    • 3 个回答
  • Marko Smith

    为什么内置类型中包含复数而小数不包含?

    • 2 个回答
  • Marko Smith

    获得唯一途径

    • 3 个回答
  • Marko Smith

    告诉我一个像幻灯片一样创建滚动的库

    • 1 个回答
  • Martin Hope
    Air 究竟是什么标识了网站访问者? 2020-11-03 15:49:20 +0000 UTC
  • Martin Hope
    Алексей Шиманский 如何以及通过什么方式来查找 Javascript 代码中的错误? 2020-08-03 00:21:37 +0000 UTC
  • Martin Hope
    Qwertiy 号码显示 9223372036854775807 2020-07-11 18:16:49 +0000 UTC
  • Martin Hope
    user216109 如何为黑客设下陷阱,或充分击退攻击? 2020-05-10 02:22:52 +0000 UTC
  • Martin Hope
    Qwertiy 并变成3个无穷大 2020-11-06 07:15:57 +0000 UTC
  • Martin Hope
    koks_rs 什么是样板代码? 2020-10-27 15:43:19 +0000 UTC
  • Martin Hope
    user207618 Codegolf——组合选择算法的实现 2020-10-23 18:46:29 +0000 UTC
  • Martin Hope
    Sirop4ik 向 git 提交发布的正确方法是什么? 2020-10-05 00:02:00 +0000 UTC
  • Martin Hope
    faoxis 为什么在这么多示例中函数都称为 foo? 2020-08-15 04:42:49 +0000 UTC
  • Martin Hope
    Pavel Mayorov 如何从事件或回调函数中返回值?或者至少等他们完成。 2020-08-11 16:49:28 +0000 UTC

热门标签

javascript python java php c# c++ html android jquery mysql

Explore

  • 主页
  • 问题
    • 热门问题
    • 最新问题
  • 标签
  • 帮助

Footer

RError.com

关于我们

  • 关于我们
  • 联系我们

Legal Stuff

  • Privacy Policy

帮助

© 2023 RError.com All Rights Reserve   沪ICP备12040472号-5