5


0

プログラミング言語で整数からshortintへの割り当てが許可されるのはなぜですか?
program TypeCategory;
{$R+}
var
    sInt : shortint;
    iInt : integer;
begin
    readln(iInt);
    sInt := iInt;
    writeln(sInt);
end.

上記の例を考慮すると、pascal言語は明示的な型キャストなしで integer`から shortint`へ、または longint`から shortint`への割り当てを許可します。つまり、pascalは型カテゴリ内の割り当てを許可します(ここでは整数型です) 。

パスカルは「強く型付けされている」ことで有名ですが、なぜこのような「弱い型付け」ができるのでしょうか?

この種の構文の長所は何ですか?この種の構文を適用した他の言語はありますか?有名なCとC ++を除きますか?

ありがとう。

編集:+ fpc / objfpc / tp / delphiモデルで turbo pascal`と free pascal`のみをテストしました。また、 `gcc / g ++`と `msvc`は同じ結果を生成します。 「int」(私のコンピューターでは4バイトのサイズ)から「short int」(サイズ2)にコンパイルエラーはトリガーされませんが、適切なオプションを設定して、コンパイラーに「データの損失」の警告を生成させることができます。

5 Answer


8


パート1。 定義について

まず第一に、どの言語と実装を「pascal」と呼びますか? ISO Pascalについて話しているのであれば、何年も前に死んでいます。 他の言語または実装について話している場合は、詳細情報を提供してください。

第二に(Teun Dが既に述べたように)強い型付けという用語の定義はありませんhttp://en.wikipedia.org/wiki/Strong_typing [厳密なタイピングに関するウィキペディアの記事]をご覧ください。

_ ただし、これらの用語には、コンピューティングの短い歴史にわたって非常に多様な意味が与えられているため、文脈から外れて、個々の著者がそれらを使用するときに何を意味するかを知ることはしばしば困難です。 _

Wikipediaページで以下に説明するLuca Cardelliの記事Typeful Programmingの定義に従うと仮定します。

_ Luca Cardelliの記事「Typeful Programming」では、厳密な型指定について、単純に未チェックの実行時型エラーがないと説明しています。 他の記述では、未チェックの実行時エラーがないことは、安全性または型安全性と呼ばれています。 Tony Hoareの初期の論文では、このプロパティセキュリティを呼び出しています。 _

とにかく、記述された動作は静的(または安全な)タイピング規則として分類できません。 私は個人的にこのうーんが嫌いです…​ まあそれは機能ではありません、それはバグです。 =)

パート2。 回答

問題はこの弱い型付けではなく、いくつかの言語で利用可能な多種多様な整数型にあると思います。

_ この種の構文を適用した他の言語はありますか(有名なCおよびC ++を除く)? _

さまざまな整数型を持つ静的に型付けされたほとんどすべての言語にこのような動作があると思います。 メモリー節約のために、このショーツとジャズを早い時期に用意するのは良い考えでした。 しかし、ほぼすべてのPCに約1 GB以上のRAMがある場合…​ 2バイトのSHORTINTではなく、100万の4バイトINTEGERがあるとします。 2 MBではなく、約4 MBのRAMのみです。 あなたが説明したこのすべての奇妙な振る舞いを持たないことは、合理的な価格だと思います。

WirthのOberon-07(http://www.inf.ethz.ch/personal/wirth/Articles/Oberon/Oberon07.Report.pdf[Language Report、PDF])をご覧ください。 整数型は1つだけです-32ビットINTEGER。

また、利用可能な(仮想)メモリのみを条件として、無制限の範囲の数値を表すint型のPython(または他の近代的な動的型付け言語)に言及することができます。

だから、傾向を見ることができます-整数型の多様性は70年代の生存です。 = )

_ この種の構文の長所は何ですか? _

長所は(おそらく)冗長性の削減です。 この静的に型付けされた言語は既に非常に冗長であるため、WerthがOberon-2で行ったような明示的な整数型変換を追加すると(SHORT()およびLONG()関数を見て)、さらに冗長になります。 妥協案として、暗黙的な変換を許可できます。 また、多くの言語では、整数型変数の実際のサイズは固定されておらず、実装ごとに異なります。 利用可能な情報は、size(shortint)⇐ size(int)のみです。 等式の場合、明示的な変換は非常に奇妙に見えます。

パート3 DithyrambからOberon-2 =)

*ところで、Pascalについてはあまり警戒しないでください。*死んでいますが、http://en.wikipedia.org/wiki/Oberon-2 [Oberon-2]で、Niklaus Wirthは彼の間違いを修正しました。

Language Reportのhttp://www-vs.informatik.uni-ulm.de:81/projekte/Oberon-2.Report/Chapter06.html[Chapter 6]では、タイプに関する情報を見つけることができます。 私たちの議論にとって重要な声明は次のとおりです。

_ タイプ3から5は整数タイプ、タイプ6および7は実数タイプであり、これらを合わせて数値タイプと呼びます。 それらは階層を形成します。 *大きい型には小さい値(の値)が含まれます:LONGREAL> = REAL> = LONGINT> = INTEGER> = SHORTINT * _

http://www-vs.informatik.uni-ulm.de:81/projekte/Oberon-2.Report/Chapter09.html [第9章]では、割り当てについて読むことができます。

_ 式は、変数と*割り当て互換*である必要があります _

最後に付録Aで:

_ _ 割り当て互換

タイプTeの式eは、次の条件のいずれかが当てはまる場合、タイプTvの変数vと代入互換性があります。

TeとTvは同じタイプです。

TeとTvは数値型で、* TvにはTe *が含まれます。

…​ _ _

だからここにいます。 INTEGER式をSHORTINT変数に割り当てることはできません。 興味がある場合は、http://en.wikipedia.org/wiki/Component_Pascal [Component Pascal]、Oberon-2のマイナーバリアントおよび改良版もご覧ください。 BlackBox Component BuilderはWindows用のIDEです。

'' '' '

ジャスティン・スミスのコメントへの回答

_ 私は、大きな型には小さな型(の値)が含まれていると驚いています:LONGREAL> = REAL> = LONGINT> = INTEGER> = SHORTINT。 _

私はあなたの声明について少し混乱しています

_ 「REAL」として表現できないLONGINTSがあります _

実際、上記のIDEでは

_ _ MAX(LONGINT)= 9223372036854775807

MAX(REAL)= 1.797693134862316E + 308 _ _

*したがって、すべてのLONGINTを実数として表すことができます。 しかし、表現は正確ではないかもしれません。*あなたは実際にそれについて話していたと思いますが、ここでは異なる整数型の変換について話しています。 そして、REALとINTEGERの間の変換は別の話です。 悪いと混乱を招くネーミングの物語。 REAL番号は、数学的な観点からは実際にはhttp://en.wikipedia.org/wiki/Real_number[real numbers]ではありません。 これらはおおよその表現です。 rational numbers近似(分子と分母を整数として保存)を使用できますが、一般的な方法は浮動小数点近似の使用です。 IEEE浮動小数点演算の標準(IEEE 754とも呼ばれます)は、浮動小数点計算で最も広く使用されている標準です。

REAL番号は実数ではないが、IEEE 754標準で記述されている番号であることを誰もが知っているはずです。 また、http://docs.sun.com/source/806-3568/ncg_goldberg.html [「すべてのコンピューター科学者が浮動小数点演算について知っておくべきこと」]を読んで、いくつかのポイントを明確にしてください。

しかし、それは別の話です…​ =)


2


どの言語が使用されているかに関係なく、プログラマーが自分自身の足で撃つ方法は常にあります。 変数を使用するときは、保存しているデータの種類と、その使用方法に注意する必要があります。 強い型付けはこれをより安全にしますが、それでも大きな変数から小さな変数に誤ってキャストする可能性があります。


0


本当に「整数」を指す「shortint」へのポインタを取得できないという意味で、この動作は弱い型ではないと思います。 また、クラッシュを引き起こすこともありません(2番目の変数の数値は予想と異なる場合があります)。

つまり、Pascalはオーバーフローをチェックしないようです。 例えば。 C#では、コード(http://msdn.microsoft.com/en-us/library/khy08726(VS.71).aspx)からチェック動作を設定できますが、これはパフォーマンスを考慮して行われないことがよくあります。 これはパスカルにも当てはまると思います。


0


言語_never_が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

このように、短いintで計算を行っている間、intを一時的な値として使用するコードを書くことはできませんでした。

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

しかし、一時的な値でより多くのビットを使用することは、一時的な値のオーバーフローによるエラーが発生しないようにするための一般的な手法です。


0


私の知る限り、考慮すべきことがいくつかあります。

  1. 古典的なPascalの意味では、整数型は_ONE_のみです。 その他は単なるサブレンジであり、厳密に完全に分離したタイプではありません。 範囲に応じて割り当てが許可され、実行時の範囲チェックはそれを実施するための標準の一部です。

  2. 一般に、Pascalは次の場合に数値型の割り当てを許可します。 範囲が一致します。 これが実数に整数を追加することが許可される理由です。 (実数は整数の範囲を含むと見なされます)、しかし逆ではありません。 ただし、realは順序型ではないため、これは特別な例外です(使いやすいように言語で定義された変換)。

従来のPascalでは、マシンのワードサイズとは異なる基本整数型が定義されることがよくありました。 (通常は2倍)、マシンで処理できる最大のタイプまで、すべての変数タイプにサブ範囲を使用します。 これは、パフォーマンスを犠牲にして、マシンワードサイズがときどき超えられても、実行時とコンパイル時(定数)のさまざまな計算が機能し続けることを意味します。 それらは単に、より大きな整数型にアップスケールされます。 私はこれをニュースグループから得ただけであり、あまり経験はしていません。 乗算が自動的にアップスケールされたかどうかはわかりません。 おそらく、これはあまり適切ではありません。ほとんどの処理は、適切に定義された入力とそれを処理するエンジニアのスタッフによるバッチ処理ではありません。

すべての変数に範囲を設定すると、範囲チェックも効率的になりました

e.g.

var x : 0..10;

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

しかし、DOS時代がよりカジュアルなタイプのプログラマーをもたらしたため、変数を定義するためのこのサブ範囲の使用は減少しました。 Turbo Pascalでは、ほぼすべてが「整数」と入力されていたため、効率上の理由から機械語(またはそれ以下)である必要がありました。

範囲サイズの2倍の倍長整数を導入する必要がありました(Delphiのint64以降)。 x86_64の場合はint128かもしれません)が、それは常に多少独特なままでした(通常のレンジングルールは適用されません)。 また、最大の符号付きタイプに対応する符号なしタイプの問題は完全に解決されませんでした(Pascalベースタイプは符号付きであり、したがって最大の符号なしタイプを含むことができないため)