“类型安全”是什么意思?


当前回答

类型安全不仅是编译时约束,也是运行时约束。我觉得即使过了这么久,我们也可以进一步明确这一点。

与类型安全相关的主要问题有两个。内存**和数据类型(与其对应的操作)。

内存* *

一个字符通常需要每个字符1个字节,或者8位(取决于语言,Java和c#存储unicode字符需要16位)。 int需要4个字节,或32位(通常)。

视觉:

字符 : |-|-|-|-|-|-|-|-|

int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

类型安全语言不允许在运行时将int类型插入到char类型中(这会抛出某种类型的类强制转换或内存溢出异常)。但是,在一种类型不安全的语言中,您将覆盖现有数据的相邻内存多3个字节。

Int >> char:

|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|

在上面的例子中,右边的3个字节被覆盖,所以任何指向该内存的指针(比如3个连续的字符),希望得到一个可预测的char值现在都是垃圾。这将导致您的程序中出现未定义的行为(或者更糟,可能会在其他程序中出现,这取决于操作系统如何分配内存——目前不太可能)。

**虽然第一个问题在技术上不是关于数据类型的,但类型安全语言固有地解决了这个问题,并且它向那些不知道内存分配“看起来”如何的人直观地描述了这个问题。

数据类型

更微妙和直接的类型问题是两种数据类型使用相同的内存分配。取int型和unsigned int型。两者都是32位。(也可以是char[4]和int,但更常见的问题是uint vs. int)。

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

类型不安全语言允许程序员引用正确分配的32位span,但当将无符号整型的值读入整型的空间时(反之亦然),我们再次遇到未定义的行为。想象一下这可能会给银行项目带来的问题:

“伙计!我透支了30美元,现在我还剩65,506美元!!”

...当然,银行程序使用更大的数据类型。,)哈哈!

正如其他人已经指出的,下一个问题是对类型的计算操作。这一点已经得到了充分的讨论。

速度vs安全

今天的大多数程序员都不需要担心这些事情,除非他们使用的是C或c++之类的东西。这两种语言都允许程序员在运行时轻易地违反类型安全(直接内存引用),尽管编译器尽最大努力将风险降至最低。然而,这也不全是坏事。

这些语言计算速度如此之快的一个原因是它们不需要像Java那样在运行时操作期间验证类型兼容性。他们认为开发人员是一个很理性的人,不会把字符串和int放在一起,因此,开发人员获得了速度/效率的奖励。

其他回答

这里的许多答案将类型安全与静态类型和动态类型混为一谈。动态类型语言(如smalltalk)也可以是类型安全的。

简单的回答是:如果没有操作导致未定义的行为,则该语言被认为是类型安全的。许多人认为显式类型转换的要求对于严格类型的语言是必要的,因为自动转换有时会导致定义良好但意想不到/不直观的行为。

类型安全的代码只访问它被授权访问的内存位置,并且只能以定义良好的、允许的方式访问。 类型安全代码不能在对象上执行对该对象无效的操作。c#和VB。NET语言编译器总是生成类型安全的代码,这些代码在JIT编译期间被验证为类型安全的。

类型安全不仅是编译时约束,也是运行时约束。我觉得即使过了这么久,我们也可以进一步明确这一点。

与类型安全相关的主要问题有两个。内存**和数据类型(与其对应的操作)。

内存* *

一个字符通常需要每个字符1个字节,或者8位(取决于语言,Java和c#存储unicode字符需要16位)。 int需要4个字节,或32位(通常)。

视觉:

字符 : |-|-|-|-|-|-|-|-|

int : |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

类型安全语言不允许在运行时将int类型插入到char类型中(这会抛出某种类型的类强制转换或内存溢出异常)。但是,在一种类型不安全的语言中,您将覆盖现有数据的相邻内存多3个字节。

Int >> char:

|-|-|-|-|-|-|-|-| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?| |?|?|?|?|?|?|?|?|

在上面的例子中,右边的3个字节被覆盖,所以任何指向该内存的指针(比如3个连续的字符),希望得到一个可预测的char值现在都是垃圾。这将导致您的程序中出现未定义的行为(或者更糟,可能会在其他程序中出现,这取决于操作系统如何分配内存——目前不太可能)。

**虽然第一个问题在技术上不是关于数据类型的,但类型安全语言固有地解决了这个问题,并且它向那些不知道内存分配“看起来”如何的人直观地描述了这个问题。

数据类型

更微妙和直接的类型问题是两种数据类型使用相同的内存分配。取int型和unsigned int型。两者都是32位。(也可以是char[4]和int,但更常见的问题是uint vs. int)。

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

|-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-| |-|-|-|-|-|-|-|-|

类型不安全语言允许程序员引用正确分配的32位span,但当将无符号整型的值读入整型的空间时(反之亦然),我们再次遇到未定义的行为。想象一下这可能会给银行项目带来的问题:

“伙计!我透支了30美元,现在我还剩65,506美元!!”

...当然,银行程序使用更大的数据类型。,)哈哈!

正如其他人已经指出的,下一个问题是对类型的计算操作。这一点已经得到了充分的讨论。

速度vs安全

今天的大多数程序员都不需要担心这些事情,除非他们使用的是C或c++之类的东西。这两种语言都允许程序员在运行时轻易地违反类型安全(直接内存引用),尽管编译器尽最大努力将风险降至最低。然而,这也不全是坏事。

这些语言计算速度如此之快的一个原因是它们不需要像Java那样在运行时操作期间验证类型兼容性。他们认为开发人员是一个很理性的人,不会把字符串和int放在一起,因此,开发人员获得了速度/效率的奖励。

类型安全

在现代c++中,类型安全是非常重要的。类型安全意味着正确使用类型,因此避免不安全的类型强制转换和合并。c++中的每个对象都是根据其类型使用的,并且在使用之前需要对对象进行初始化。

安全初始化:{}

编译器在类型转换过程中防止信息丢失。例如, int {7};初始化没问题 \ . int b{7.5}编译器显示错误,因为信息丢失

不安全的初始化:=或()

编译器不会在类型转换期间防止信息丢失。 int a = 7初始化正常 int a = 7.5初始化正常,但信息丢失。a的实际值将变为7.0 int c(7)初始化OK int c(7.5)初始化是可以的,但是会发生信息丢失。a的实际值将变为7.0

类型安全意味着在编程上,变量、返回值或参数的数据类型必须符合特定的标准。

实际上,这意味着7(整数类型)不同于"7"(字符串类型的引号字符)。

PHP, Javascript和其他动态脚本语言通常是弱类型的,因为它们将转换(字符串)如果您尝试将“7”+ 3添加为“7”到(整数)7,尽管有时您必须显式地这样做(Javascript使用“+”字符进行连接)。

C/ c++ /Java不会理解,或者会将结果连接到“73”中。类型安全通过明确类型需求来防止代码中出现这些类型的错误。

类型安全非常有用。上述“7”+ 3的解决方案是类型转换(int)7 + 3(等于10)。