当前位置: 首页 > java >正文

隐式/显式类型转换?编程语言的类型转换?其它类型转换成数值类型?其它类型转换成字符串?类型转换?

目录

隐式/显式类型转换

隐式转换

不同的显式类型转换

显示转换一定会成功?

数值和布尔类型转换

编程语言的类型转换

float类型变量任何时候都会转换成double类型吗?

强制类型转换

检测数据类型

其它类型转换成数值类型

转换成数值的API

其它类型转换成字符串

类型转换

隐式转换和强制转换

父类子类转换

枚举

浮点数和整数的转换


隐式/显式类型转换

编译器为了简化不同类型变量互操作,引入隐式转换。

隐式转换

  • C/ObjC/C++/C# 等都支持隐式转换,"小"类型和"大"类型操作,"小"类型自动转换成"大"类型。但隐式转换很可能带来风险。
    • 浮点数类型可以隐式转换成unsigned long long, 注意可能损失精度。
  • Swift为了消除隐式转换的风险,规定不同类型变量运算,必须强制转换成相同类型
    - 比如In8和Int32相加,Int8必须强制转换成Int32才能相加:a是Int8, b是Int32, b = Int32(a) + b
    - 字面量运算不受如上限制,编译器会自动推导,例如var c = 1 + 0.1
  • 仓颉 同样不支持隐式类型转换,对于二元运算符(除了幂运算符),两个操作数类型必须一致。包括但不限于算术运算符、关系运算符等。

不同的显式类型转换

  • 仓颉
    • Type(val)
      例如Int64(3.5)
  • Swift
    • Type(val)
  • C/ObjC/C++/C#
    • (Type)val

显示转换一定会成功?

  • C# 显示转换只是程序员的一种想法,运行时遇到问题一样会抛出异常。

数值和布尔类型转换

  • C/ObjC 布尔类型_Bool本质是整型,二者可以互相转换。
  • C# 不允许数值和布尔互相转换。

编程语言的类型转换

  • C/ObjC/C++
    • 对于大小在int范围内的整型(包括char/short和枚举)的类型使用时都自动转换成int.
      • 汇编示例:char和int类型变量相加,char类型会使用movsx符号位扩展为int大小再参与计算。
    • int和unsigned运算,int隐式转换成unsigned int.
      • 假设都是4字节,对于汇编代码,并不会有特别的指令区分int和unsigned,只会通过形如eax或edx寄存器计算。
    • int/unsigned int和long类型运算,前者自动转换成long类型。
      • 假设int是4字节,long是8字节。汇编语言可能通过cdqe指令自动将32位有符号数转换成64位(保持符号位不变)。但需要注意,形如int_val = int_val + long_val, 编译器可能不会遵循前面的规则,因为最终结果保存在int类型,右边表达式不一定会将int_val扩展为64位。
    • float类型和double类型运算,float会自动转换成double类型参与运算。
      • 汇编语言会使用cvtss2sd将单精度转换成双精度浮点数指令完成float自动转换成double.
    • 大小在long范围内和double类型运算,前者自动转换成double类型。
    • 大小在long范围内和float类型运算,前者自动转换成float类型。

float类型变量任何时候都会转换成double类型吗?

  • 这是错误的!在C语言中,如果long类型和float运算,long类型转换成float一起参与运算,而不是都转换成double类型。float_val = long_val + float_val; 对应汇编会是cvtsi2ss指令将long类型转换成float类型参与计算,而不是转换成double类型的cvtsi2sd指令.

强制类型转换

  • C/ObjC/C++/C#/Java/PHP 等支持用 (new_type) 强制转换已有类型的变量。
  • PHP 还支持settype函数转换为特定类型,这也提现PHP动态语言的特征。

检测数据类型

  • C/ObjC/C++ 不支持获取基本变量的类型(C++ typeid除外)。
  • PHP 提供is_*系列函数获取变量的类型,例如:is_string('abc')

其它类型转换成数值类型

很多静态类型编程语言,不允许将非数值类型转换成数值类型,一些脚本语言为了简化复杂度,允许非数值类型按照特定规则转换成数值类型。

  • JS
    • Undefined类型 --> NaN.
    • Null类型 --> 0.
    • Boolean类型 true --> 1, false --> 0.
    • String类型根据是十进制还是十六进制或者浮点数,转换成对应数值。注意,这里没有八进制数值,字符串"012"转换成数值是十进制的12,而不是八进制的012.
      如果是空字符串或者多个空格,数值是0,如果是除了如上的其他字符串,即是非法数值,转换结果是NaN.
    • Object类型转换为数值经过2个步骤,先调用valueOf()函数,按照如上规则,有合法数值即返回,如果返回NaN, 继续调用toString()函数,同样按照如上规则得到数值,如果没有数值类型返回,返回NaN.
  • C#
    • 基本类型提供隐式转换或者强制转换。
    • 字符串转换成基本类型:
      • <Type>.Parse(<String>)
        例如int.Parse("123")
      • <Type>.TryParse(<String>, out <Val>) (C# 2.0 ?)
        和Parse的区别是,此函数转换失败不会抛出异常。
    • 字符串转换成基本类型:
      • System.Convert.ToXXX(<String>)
        例如ToInt, ToFloat, ...
  • VB
    • Val(str) 将str转换成数值,如果str包含不能转换为数值的字符,转换就此终止,返回已解析的数值。例如:
      Val("a12") 返回 0,Val("-123ab") 返回 -123.

转换成数值的API

  • JS
    Number函数用于将任何类型转换成数值。
    parseInt函数和parseFloat函数都可以将字符串转换为数值。要特别注意,传入字符串和数值类型将导致结果不同,数值类型的参数会先转换为字符串再参与转换。例如parseInt(0x10, 16)和parseInt('0x10', 16)结果分别是22和16.

其它类型转换成字符串

大部分编程语言将一个变量转换成字符串,一般会经过toString方法或者类型转换方法,形如C语言的itoa.

  • Swift提供一种极其优雅的方法,可以用 \(VAR) 做转换。

var i = 10

let str = "I have \(i) apples"

print(str)

  • JS
    • 基本类型
      null --> "null", undefined --> "undefined" (注意不是空字符串), 布尔类型分别是"true"和"false", 字符串本身就返回自身,Number类型转换成对应的字符串,比如12 --> "12", 1.23 --> "1.23".
    • 引用类型:先调用toString函数,如果得到基本类型,按上面规则转换字符串;如果不满足,继续调用valueOf函数,如果还是基本类型,再次重复上面的转换;如果还不满足,抛出异常。
  • 仓颉
    基本类型可调用toString()函数转换成字符串。
  • C#
    • 语言定义了基本类型ToString()方法,自定义类可以重写ToString()方法。
  • VB
    • Str(num) 函数可以将数值转换成字符串,num可以是整数或浮点数,不能是非数值字符。注意,如果num是正数,字符串会有前导空白字符。CStr(num) 函数基本和Str(num)一样,除了它在num是正数时不会有前导空白字符。

类型转换

编程语言中必然有很多情况需要转换类型。比如引入const的概念就为了提高安全性,编译器提前检查,避免一些意外修改。当然,有时,我们希望手动转换一个变量的类型,让其变成常量,可以利用编译器提供的cast方法。

  • C++早期提供了const_cast,写法繁琐,C++17引入std::as_const写法更轻松,C++20引入bit_cast可实现位级别复制,而非普通float和int转换后丢失小数位的问题。

隐式转换和强制转换

编译器为了简化不同类型变量互操作,引入隐式转换,可以安全转换(不损失数据)数据,此过程由编译器自动完成。当不满足如上条件,需要程序员手动用强制类型转换。

  • C/ObjC/C++ 语言大小小于int的整型(包括char和枚举)的类型使用时都自动转换成int. 有人有疑问,这样不是占用空间变大吗?事实上,仅仅是使用时,数据保存依然按对应类型。为什么使用时要转换成int呢?因为CPU操作int最自然,换成char或short一样会使用int大小的寄存器,没好处。下图push eax保存字符c,并传递给printf做参数。

  • Swift 是一门相对安全的语言,没有隐式类型转换。

父类子类转换

子类本身就是父类的一种,转换成父类很自然,但父类转换成子类就需要考虑对不对。

  • C++提供dynamic_cast主要为了继承体系转换,比static_cast更智能。虽然C++支持强制转换,必要时也可以通过typeid判断类型是否一致。
  • Java默认也不允许父到子转换,但如果确定父对象引用确实是子对象,可用强制类型转换。
  • C#不提供基类强转成派生类的方法。
  • Python提供了简单的转换方式type(<Derived Class>)(<Base Class>).
  • JS ES6虽然引入了类,一般无必要做父类子类转换。
  • Go/Rust并不是纯粹的OOP语言,需要做一些手脚。

枚举

  • C/C++常规枚举可以和整形做隐式转换,C++11引入作用域为类的枚举,不允许此行为以加强安全性,但可以使用显式转换。

浮点数和整数的转换

  • C/ObjC/C++/仓颉
    浮点数转换成整数,会丢弃小数。


若文章对您有帮助,欢迎关注 程序员小迷 。助您在编程路上越走越好!

微风不燥,阳光正好,你就像风一样经过这里,愿你停留的片刻温暖舒心。

我是 程序员小迷 (致力于C、C++、C#、Android、iOS、Java、Kotlin、Objective-C、Swift、Shell、JavaScript、TypeScript、Python等编程技术的技巧经验分享),若作品对您有帮助,请关注、分享、点赞、收藏、在看、喜欢,您的支持是我们为您提供帮助的最大动力。

http://www.xdnf.cn/news/5459.html

相关文章:

  • 【和春笋一起学C++】数组名作为函数参数实例
  • STM32f103 标准库 零基础学习之按键点灯(不涉及中断)
  • vim配置代码文档格式化
  • Http2多路复用的静态表和动态表
  • CSS专题之自定义属性
  • 记录学习《手动学习深度学习》这本书的笔记(十一)
  • Docker:安装配置教程(最新版本)
  • 元组类型的特性与应用场景:深入理解元组在 TypeScript 中的使用
  • Python训练营打卡DAY22
  • LVGL(lv_label实战)
  • 《设计模式之禅》笔记
  • 使用PHP对接印度股票市场API
  • AARRR用户增长模型(海盗指标)详解
  • C/C++跳动的爱心
  • 云计算-容器云-KubeVirt 运维
  • 【Tools】Visual Studio使用经验介绍(包括基本功能、远程调试、引入第三方库等等)
  • 深入理解 Pinia:状态管理的利器
  • [思维模式-29]:《本质思考力》-9- 两种相反的构建与解构系统的思维模式:①自顶向下的规划、分解、牵引;②自底向上的堆叠、聚合。
  • 【stata代码】地方政府驱动企业参与乡村振兴的机制——乡村振兴注意力视角的分析
  • 数据可视化大屏——智慧社区内网比对平台
  • 基于SpringBoot的抽奖系统测试报告
  • 49.EFT测试与静电测试环境和干扰特征分析
  • 2025御网杯wp(web,misc,crypto)
  • #Redis黑马点评#(五)Redisson详解
  • 并发笔记-条件变量(三)
  • 第二十一周:项目开发中遇到的相关问题(二)
  • 使用Visual Studio将C#程序发布为.exe文件
  • java加强 -Collection集合
  • Java基础语法之循环结构
  • immutable.js介绍