Re: 構造体のメンバの記憶域の順
とりあえず、Newsgroups:に
fj.comp.lang.cobol
fj.comp.lang.fortran
fj.comp.lang.pascal
fj.comp.oldies
を加えますが、Followup-To:からはfortranとpascalを外しておきます。
In article <bic3a2$nsg$2@newsserv.ics.es.osaka-u.ac.jp> saitoh@ist.osaka-u.ac.jp writes:
>> そもそも、構造体の歴史的起源ってCOBOLのものだと思うんですが、
>> (それ以前が存在することを御存知の方は御教示ください)
>Cのstructは、PDP-11のアセンブラの FRAME疑似命令が
>起源だと思いますが。
直接の起源をターゲット機のアセンブラに求めますか……
いくらC言語が「高級アセンブラ」だからって、
それだけが起源だと断定するのはどうでしょうね。
また、アセンブラにそういう疑似命令を準備したというのが、
過去の高級言語からの発想という可能性もありそうですし……
私の断片的な知識を、ざっとまとめてみました。
(1)algolには構造体に相当する概念は無い。
FORTRANのCOMMONブロックは、
バイナリレベルでは外部構造体(C言語のextern struct)と
同等に扱われることが多いと思われるが、発想は違いそう。
即ち、1950年代に開発された高級言語の「御三家」で、
構造体に相当する概念があるのはCOBOLだけである。
(2)しかし、COBOLでは「構造体(structure)」という用語は用いていない。
この用語が規格レベルで出てきたのは、PL/I(1964年)ではないかと
思われるが、確かな証拠は今のところ得られていない。
(3)Pascal(1968年)では構造体に相当するものを「record型」と呼んでいる。
この呼称は、COBOLの構造体がファイル入出力における「record」の概念と
密接に結びついているところから来ているのではないかとの推測が成り立つが、
あくまで推測に過ぎない。
ちなみに、C言語は1972年に開発されたことになっており、
前身を遡るとB言語(1970年)←BCPL(1967年)←CPL(1963年)となるようです。
(CPLの前身はalgolまで行き着いてしまう)
COBOLにおける構造体の概念がファイル入出力と密接に結びついている
ということは、前電でも
In article <bi73b2$u5m$1@bluegill.lbm.go.jp> I write:
>COBOLの構造体は「ファイル入出力の単位」という性格を
>明確に主張する仕様になっています。
>そもそも、COBOLは「磁気テープ上のデータを読み込んで、加工して、
>別の磁気テープに書き出す」処理を行うという発想で設計されていて、
>変数は入出力デバイスにリンクしているのが「フツー」であり、
>そうではない「作業用一時変数」は継子扱いです。
と説明した通りですが、もう少し詳しく説明してみます。
COBOL以外のほとんどの高級言語のファイル入出力では、
例えば出力の場合には、プログラム中で記述された変数領域のデータを、
プログラムでは直接見えない「入出力バッファ」領域に複写して
(書式つき出力の場合には、書式に従った変換結果をバッファ領域に書込んで)、
その(直接見えない)データをデバイスに引き渡すという手順だと思います。
ところが、COBOLでは「入出力バッファ」の中に、
当該入出力デバイス専用の(プログラムから見える)変数を確保する
という発想になっています。
(実際には、デバイスとの間にワンクッション置く実装が多いと思われるが、
言語の習得に際しては、そのことを意識しない方が解りやすい)
書式つき出力にしても「出力バッファ内の変数」への
代入に際して書式に従った変換が行われるという発想です。
(つまりバッファ内の各変数の属性の1つとして“書式”がある)
そうすると、入出力単位である「レコード」は、
「内容は多種多様だが、組(前田さんのいう“tuple”)として
まとまっているデータ群」になりますから、
その中身は自ずから構造体の性格を有することになります。
そのため、COBOLでは他の構造体の要素ではない「一番上のレベルの」構造体と、
入出力単位である「レコード」が同義語になるんですね。
なお、「一番上のレベル」に限らない、中間レベルも含めた構造体のことは、
COBOLでは集団項目(group item)と呼んでいます。
FORTRANだと、バイナリ入出力にも「入出力並び」があって、
レコードは個々の入出力文の並びで「1回ごとに定義される」
「偶々その場に居合せたというだけの集団」という感覚ですが、
COBOLではそれが「恒常的な社会集団(??)」であることを要求しているわけです。
この点、PL/Iでは書式なしのREAD/WRITE(RECORD入出力)では
「並び」ではなく「1個の変数(=構造体を想定)」を引数とするのに対して、
書式つきのGET/PUT(STREAM入出力)では引数は「並び」と使い分けられています。
C言語でもfread/fwriteで入出力されるデータは「1個の引数」なのに対して、
fscanf/fprintfでは「不定数の引数」になるというのは似たような発想ですね。
ただ、PL/IにしてもC言語にしても、
変数が言語仕様上は「当該デバイス専用」ではないというところが、
COBOLと異なります。
戸田 孝@滋賀県立琵琶湖博物館
toda@lbm.go.jp
Fnews-brouse 1.9(20180406) -- by Mizuno, MWE <mwe@ccsf.jp>
GnuPG Key ID = ECC8A735
GnuPG Key fingerprint = 9BE6 B9E9 55A5 A499 CD51 946E 9BDC 7870 ECC8 A735