隐式类型转换 —— 整型提升

本文解释了整型提升的概念,即char或short类型在运算前自动转换为int类型的过程。介绍了为何需要整型提升及其对负数和正数的不同处理方式,并列举了几种常见应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

        目录

1、为什么要整型提升

2、如何整型提升

(1) 负数整型提升

(2) 正数整型提升

3、发生整型提升的几种场景

(1) 算术运算过程

(2) 比较运算过程


简单来说,整型提升指的是 字符型(char)或者短整型(short) 在被使用之前 先转换成 普通整型(int),这就是整型提升。

1、为什么要整型提升

表达式整型运算要在CPU对应的运算器(ALU)中运行,比如表达式 1 + 2 。整型运算器(ALU)要求操作数的字节长度一般是 int 的字节长度,如果是 加法,那就要求加数和被加数的字节长度都是 4 个字节。

但是如果是两个 char 类型的字符相加,char类型的字符仅占 1 个字节,为了满足要求,需要将 char 类型临时提升为 int类型,这个过程就是整型提升。

注意:整型提升仅仅只是在运算的时候,临时提升类型,不会改变char类型变量原本的值。比int类型短的,也就只有 char 、short 两种类型。

2、如何整型提升

整型提升是按照变量的符号位来进行提升的,因此整型提升分为 负数 和 正数 的整型提升。(char 类型、int类型等默认都是有符号类型,即最高位都是符号位)

(1) 负数整型提升

char a = -1;   

第一步,先转换成二进制形式(即原码)。原码 = 10000001

第二步,转换成补码(内存中存放的形式)。补码 = 反码 + 1 = 11111110 + 1 = 11111111

第三步,高位补充。char类型是1个字节(8 bit),int类型是4个字节(32 bit),所以需要补上缺少的24 bit,char类型默认是有符号类型,最高位是符号位,补0还是补1由符号位决定。因为 a 的补码最高位符号位为 1,所以要 补 1 。

第四步,变量 a 整型提升以后的结果为 11111111  11111111  11111111  11111111

(2) 正数整型提升

char b = 1;   

第一步,先转换成二进制形式(即原码),然后转成补码。补码 = 原码 = 00000001

第二步,高位补充。char类型是1个字节(8 bit),int类型是4个字节(32 bit),所以需要补上缺少的24 bit,补0还是补1由符号位决定。因为 b 的补码最高位符号位为 0,所以要 补 0 。

第四步,变量 b 整型提升以后的结果为 00000000 00000000 00000000 11111111

3、发生整型提升的几种场景

(1) 算术运算过程

a 进行整型提升以后的二进制补码 = 原码 = 00000000 00000000 00000000 00001010  

                         对应的十进制为 10

b 进行整型提升以后的二进制补码 = 11111111 11111111 11111111 10001000 

                        对应的十进制为 -120

此时 a + b = 10 + (-120)= -110

后面需要重新转换成 char类型,然后再赋值给 c

char a = 10;

char b = -8;

char c = a + b;     //a,b发生整型提升

printf("%d\n", a);    //a 发生整型提升

(2) 比较运算过程

a 转换成二进制是 10110110,整型提升二进制补码形式:11111111 11111111 11111111 10110110

原码为 10000000 00000000 00000000 01001010 ,转换成十进制是 -74 

而等号右边的值转换成十进制是 182

因此,if 语句的判断结果为假

char a = 0xb6;
if(a == 0xb6)
{
    //...
}
### SystemVerilog 中的隐式类型转换规则 在 SystemVerilog 中,隐式类型转换通常发生在表达式的求值过程中或不同数据类型之间的赋值操作中。这些转换遵循一定的规则以确保程序的行为可预测并减少潜在的错误。 #### 1. **基本隐式转换规则** 当两个不同类型的操作数参与运算时,SystemVerilog 尝试将它们转换为相同的类型以便执行计算。以下是常见的隐式转换规则: - 如果其中一个操作数是实数(`real` 或 `shortreal`),另一个操作数会被转换为实数[^2]。 - 对于整型数据类型(如 `int`, `byte`, `longint` 等),如果目标类型具有更大的位宽,则源类型会扩展到位宽较大的类型[^2]。 - 当目标类型较小而发生截断时,高位部分可能会丢失,这可能导致数据精度下降[^2]。 #### 2. **逻辑类型与二进制类型的隐式转换** - `logic` 类型可以隐式地转换为 `bit` 类型,在此过程中,所有的未知状态 (`x`) 和高阻态 (`z`) 均被替换为零 (`0`) [^2]。 - 反之,从 `bit` 到 `logic` 的转换不会改变任何值,因为 `bit` 是一种特殊的两值逻辑形式[^2]。 #### 3. **符号扩展与无符号扩展** - 在涉及有符号和无符号混合的情况下,默认情况下,无符号数值优先级更高[^2]。 - 如果需要将一个较短的有符号数扩展成更长的目标类型,则会发生符号扩展;而对于无符号数来说则是简单的零填充。 #### 4. **数组索引中的隐式转换** 即使数组索引通常是整数类型,某些时候浮点数也可以作为临时替代品来访问特定位置上的元素——不过在此之前它必须先经过取整处理再转化为合适的地址偏移量。 #### 示例代码展示 下面是一些关于如何应用上述原则的例子: ```systemverilog // Example of implicit conversion between real and integer types. program automatic test; initial begin real r_val = 5.7; int i_val; // Implicitly converts the floating-point value to an integer by truncation. i_val = r_val; $display("Real Value: %f", r_val); $display("Integer after Conversion: %d", i_val); // Output will be '5' end endprogram ``` 在这个例子当中,我们看到尽管原始变量是一个带有小数部分的真实数字(`r_val=5.7`) ,但在将其分配给整型变量之后只保留了它的整数成分。 另外还有这样一个情况涉及到不同的宽度以及是否有标记属性的不同组合下的行为表现差异: ```systemverilog module example(); logic signed [7:0] a = -8'd128; // Signed byte (-128) bit unsigned [9:0] b; always_comb begin : proc_b b = a; // Sign extension occurs here due to difference in size & signess // Resulting assignment would yield '-1' as decimal equivalent (all ones pattern). end always @(posedge clk) begin if(b == 10'b1111_1111_11) ... end endmodule ``` 在这里可以看到由于两者之间存在长度差加上一个是带标志版本另外一个却是非负定版故而在复制之前进行了必要的签署延展动作从而使得最终结果呈现出全‘1’的形式即十进制意义上的最大负数值(-1). --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值