为什么编程语言允许从整数到shortint的赋值?

时间:2010-01-17 16:22:37

标签: programming-languages strong-typing weakly-typed

program TypeCategory;
{$R+}
var
    sInt : shortint;
    iInt : integer;
begin
    readln(iInt);
    sInt := iInt;
    writeln(sInt);
end.

考虑到上面的示例,pascal语言确实允许从integershortint,甚至longintshortint进行分配而不进行明确的类型转换。也就是说,pascal允许类型类别内的赋值(这是整数类型)。

Pascal以其strongly typed而闻名,但为什么它允许这种weakly typed的东西?我认为这种语法会鼓励不一致的代码。

这种语法的优点是什么?除了着名的C和C ++之外,还有其他语言应用这种语法吗?

感谢。

修改
我只测试了turbo pascalfree pascal with fpc/objfpc/tp/delphi model。此外,gcc/g++msvc会产生相同的结果。也就是说,来自int的分配(大小为我的计算机上的4个字节)到short int(大小为2)不会触发任何编译错误,而您可以设置适当的选项以使编译器生成possible lose of data警告。

5 个答案:

答案 0 :(得分:8)

答案 1 :(得分:2)

无论使用哪种语言,程序员总有办法在脚下射击自己。使用变量时,您需要了解要存储的数据类型以及如何使用它们。强类型使这更安全,但你仍然可能错误地从较大的变量转换为较小的变量。

答案 2 :(得分:0)

我认为这种行为并不是弱类型的,因为你永远无法获得指向真正指向shortint的{​​{1}}的指针。它也永远不会导致崩溃(尽管第二个变量中的数值可能与您的预期不同)。

你的意思是,帕斯卡显然没有检查溢出。例如。 C#,您可以从代码(http://msdn.microsoft.com/en-us/library/khy08726(VS.71).aspx)设置检查行为,但通常不会出于性能考虑而这样做。我认为这也适用于pascal。

答案 3 :(得分:0)

如果语言从不允许从int到short int的赋值,那么就不可能编写这段代码

var
sInt : shortint;
iInt : integer;

if (iInt < 100 && iInt > -100)
{
   sInt := iInt; // this would not compile
}

或者

var
sInt : shortint;
iInt : integer;

sInt := (iInt & 0xFFFF); // this would not compile

在使用短整数进行数学运算时,你无法编写使用整数作为临时值的代码,如下所示。

var
sInt1 : shortint;
sInt2 : shortint;
iInt : integer;

/* I want to multiply sInt2 by sInt1 and then divide by 100 */
iInt = sInt2;
sInt2 := (iInt * sInt1) / 100; // this would not compile

但是在临时值中使用更多位是一种常见技术,可确保您不会因临时值溢出而出错。

答案 4 :(得分:0)

据我所知,有几件事需要考虑:

  1. 经典Pascal意义上只有 ONE 整数类型,整数。其他只是子范围,因此不是严格意义上的完全独立的类型。允许分配 取决于范围,运行时范围检查是执行它的标准的一部分。
  2. 通常,只要范围匹配,Pascal就允许为数字类型赋值。这就是允许向实数添加整数的原因。 (real被认为包含整数范围),但不是相反。这是一个特殊的例外,(一种语言 定义转换为易于使用)因为真实甚至不是一种序数类型。
  3. Classic Pascals经常定义与机器字大小不同的基本整数类型。 (通常是两倍大),最大的类型可以在机器上处理,并使用 所有变量类型的子范围。这意味着各种计算,即使偶尔超过机器字大小,运行时间和编译时间(常量)也将保持工作,但代价是某些性能。它们只会被升级为更大的整数类型。我只从新闻组获得这个,但对此没有太多经验。我不知道是否有任何乘法自动放大。可能现在这种情况不太适用,大多数处理都不是批处理的,具有明确的输入和工程师来处理它。

    在所有变量上设置范围使得范围检查也更有效

    e.g。

    var x : 0..10;
    
    x:=10;
    x:=x+1; // runtime range check error  here.
    

    然而,由于DOS时代引入了一种更为随意的程序员类型,因此使用子范围来定义变量已经减少了。在Turbo Pascal中,几乎所有东西都被输入“整数”,因此出于效率原因必须是机器字(或更小)。

    必须引入两倍范围大小的longint(后来在Delphi中使用int64。对于x86_64及时可能是int128),但这总是有点特殊(并且正常的测距规则不适用。还有问题。对应于最大签名类型的无符号类型从未完全解析(因为Pascal基类型已签名,因此不能包含最大的无符号类型)