program TypeCategory;
{$R+}
var
sInt : shortint;
iInt : integer;
begin
readln(iInt);
sInt := iInt;
writeln(sInt);
end.
考虑到上面的示例,pascal语言确实允许从integer
到shortint
,甚至longint
到shortint
进行分配而不进行明确的类型转换。也就是说,pascal允许类型类别内的赋值(这是整数类型)。
Pascal以其strongly typed
而闻名,但为什么它允许这种weakly typed
的东西?我认为这种语法会鼓励不一致的代码。
这种语法的优点是什么?除了着名的C和C ++之外,还有其他语言应用这种语法吗?
感谢。
修改:
我只测试了turbo pascal
和free pascal with fpc/objfpc/tp/delphi model
。此外,gcc/g++
和msvc
会产生相同的结果。也就是说,来自int
的分配(大小为我的计算机上的4个字节)到short int
(大小为2)不会触发任何编译错误,而您可以设置适当的选项以使编译器生成possible lose of data
警告。
答案 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)
据我所知,有几件事需要考虑:
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基类型已签名,因此不能包含最大的无符号类型)