ページ 11

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月22日(土) 18:10
by Math
#9 にきしてある本ををお読みください

18刷まででたベストセラーであり 新版はC11 対応です

この本によると
Cは演算子が 多言語に比べ極端に多く しかもその優先順位が15段階もあります。
規格は BNF( Backs-Naur Form ) と呼ばれる記法により構文規則を定義しており 演算子の優先順位も構文規則のなかに含まれます。(とても素人にゃーよめませんよ)

このかたは自分で ライブラリをつくって ソフト会社で教えておられます。
私も C でライブラリを作ってコンピューター基板で制御するのが最初だった。
C は Unix 作るための 高級アセンブラーだった。それまでOSはアセンブラでしかつくられてなかった。

printf なんてCの規格にゃなかった。

著者によると 「Cの問題点 Cのいい加減さ を指摘しているため嫌っていると誤解されるが
Cは偉大な言語であり 長年現場で実用されてきた言語には それだけの実力がある」とかいてます。

いまやC は大型コンピューターから小型の制御基板まで広くつかわれ われわれは一部 パソコンにつかわれているものの話をしてるだけです。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月22日(土) 18:22
by Math
ところでアセンブラでブートストラップから書けるひといる(^^;

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月22日(土) 18:47
by Math
Cの本体は小さくて 表示 も 入力 もライブラリーです。
自分で一からつくると面白いですよ。(制御用マイコンがそうだね)
CでCを改良できるよ。まあ当たり前だけど。


ちなみに VB は VBをつかって 2千万行で 作り変えたよ
「Visual Basic 2015
2015年に.NET Framework 4.6とともに公開。Visual Studio 2015に同梱される。Roslynと呼ばれるコンパイラレイヤーにより、Visual C#と同等のIDE機能を備えるに至った」(ウキペディア より)

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月23日(日) 13:51
by かずま
ISLe さんが書きました:
6年前
オフトピック
int a, b;
a = 1;
b = a + 1;
ここに出てくるaは全部意味が違うのにどうして同じ記号(記号なし表記)なの?教えて偉い人

その上で、C言語のポインタが宣言と演算子で同じ記号を使うことの何が問題なの?教えて偉い人
出てくる場所によって意味の違いを認識できるから、
同じオブジェクトを指示(designate)する識別子 a は同じ記号でよい。
a はポインタではないので、オブジェクトを指す(point to)とか、
参照する(refer to)とは言わないことにします。

int a の場合、int の後なので、オブジェクトの宣言だと分かります。

a = 1 の場合、「=演算子」の左オペランドなので、左辺値として処理
します。オブジェクト a の値は使用しません。

a + 1 の場合、「+演算子」のオペランドなので、左辺値である a から
値を取り出して使用します。


「C言語のポインタが宣言と演算子で同じ記号を使うこと」に何の問題も
ないと私は思っています。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月23日(日) 14:13
by かずま
Math さんが書きました:
6年前
また、この宣言の読み方を見ればわかるように、 C言語には多次元配列は存在しない。 int a[10][10]; という宣言は、多次元配列ではなく、 「配列の配列」を意味する。
# Cの規格書では、脚注に「多次元配列」という言葉が最初に出現し、
# それ以後はちょこちょこ使われているから、「多次元配列は存在しない」
# という言い方はきつ過ぎるかも知れませんが、Cの宣言を理解するには、
# そう考えた方が得なのは間違いないと思います。”
Cの規格書には、多次元配列、n次元配列、3次元配列という用語が出てきます。
トピック「3次元配列」の #4 に引用しました。

・C には、「配列の配列」はあるが、「多次元配列」はない。
というのは無理があると思います。
・C では、「多次元配列」があって、それは「配列の配列」で表現する。
と言えばよいと思います。

ところで、Cの規格書には「変数」という用語がほとんど出てこないことは
ご存知でしょうか?
JIS X 3010:2003 プログラム言語C - 日本工業規格の簡易閲覧
「変数」を検索すると 10個あることはありますが、
関数、定数、型、式、文、配列、ポインタなどの用語は何百何千と登場し、
目次や索引にも含まれているのに比べて、あまりにも少ないと思いませんか?

・C には、「変数」があって、規格書ではそれは「オブジェクト」と書かれている。
と言っていいと思います。
・C には、「オブジェクト」はあるが、「変数」はない。
とは誰も言いませんよね。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月23日(日) 14:48
by かずま
Math さんが書きました:
6年前
"K&Rによれば、Cの宣言は、「変数が現われ得る式の構文を真似た(P.114)」 そうである。しかし、本質的に全く異なるものを無理に似せようとしたため、 結局わけのわからない構文になってしまっている。 「宣言の形と使用時の形を似せる」というのはC(およびCから派生したC++, Javaなどの言語)に特有の「変な構文」である。"
と前橋さんはかいておられます。
わけの分からない構文になったのは、
宣言時の形と使用時の形を似せたからではありません。

ポインタの「*」を前置にし、配列の [] と関数の () を後置にした
ことによるものです。

x : array [3] of pointer to function returning pointer to array [5] of char
x は、charの配列(要素数5)へのポインタを返す関数へのポインタの配列(要素数3)

ポインタの「*」が前置だと、char (*(*x[3])())[5];
ポインタの「^」が後置だと、char x[3]^()^[5];

これは、C を開発した Dennis M. Ritchie が後に反省点として挙げている点です。
The Development of The C Programming Language

コード:

	char s[] = "abcdef";
	for (char p^ = s; p^ != '\0'; p++)
		putchar(p^);
後置でも何の問題もありません。

コード:

	struct Point { int x, y; } a, p^:
	p = a;
	p^.x = 24;
	p^.y = 32;
(*p).x と書くのは面倒で分かりにくいから
-> という演算子を用意し、p->x と書けるようにしました。
でも、後置ならご覧のように新しい演算子は要りません。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月23日(日) 21:00
by Math
第一級オブジェクト

https://ja.wikipedia.org/wiki/%E7%AC%AC ... F%E3%83%88

やり直しC言語:配列はファーストクラスではなかった

http://blog.tojiru.net/article/426593261.html

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月24日(月) 08:23
by Math
#36 などは   #9でPascal との比較をすればわかる等 #9のCの型モデルなどにに詳述してある。

Dennis M. Ritchie が後に作った言語にはPascal流に改良されている。

ところで Win32API の WINAPI は最初のころ PASCAL を使っていました。(いまでも使えます)
これは少し意味合いが違って関数の呼び出し 後処理がPascal風なのですね。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月24日(月) 09:39
by Math
#9 の説明より

「メモリー上で一定の領域をしめ sizeof 演算子でサイズが特定できる型のことを、規格では

オブジェクト型 とよんでいる」

(^^;

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月24日(月) 09:54
by Math
Cかた は 次のように 分類できる

・オブジェクト型 (char int 配列 ポインタ 構造体 など)

・関数型

・不完全型( 構造体タグ など)

(#9より)

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月26日(水) 05:57
by ISLe
Math さんが書きました:
6年前
#9 にきしてある本ををお読みください

18刷まででたベストセラーであり 新版はC11 対応です
#9のリンク先にこうあります。
こういった混乱の原因は、「ポインタはアドレスだ」ということを理解していないところにあるのではありません。本当の理由は、

 ・C の「奇怪な」宣言の構文
 ・配列とポインタの間の「妙な」交換性

にあるのです。
#10のリンク先にこうあります。
 C言語では、「ポインタが難しい」と良く言われますが、 実際に初心者がCを学習する過程を見ると、以下のことだけは すぐに理解しているようです。
 「ポインタっつーのは、要するにアドレスのことなんだな」
 ここまでは簡単、誰でもすぐに理解します。

# 大体、いつだって、低レベルな概念の方が理解が速いものです。
# アセンブラなんて、誰だってすぐに理解できますよね。
# それでまとまったプログラムを組むには別な才能が必要だ、
# というだけで。

 問題はそこから先です。
これをわたしなりに整理してみて

初心者でも「ポインタはアドレスだ」というのはすぐに理解できる
→だから、ポインタは難しくない
→なのに、ポインタでハマる者があとを絶たない
→ポインタが分からないのは、「ポインタはアドレスだ」と理解できないのが理由ではなく、文法が奇怪であることが理由である

というふうに書いてあると理解しました。

そこで疑問が…
「ポインタはアドレスだ」ってどういうことすか。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月26日(水) 07:56
by Math
#9 の本と アセンブラでレジスターでデータであるメモリーを取り込む仕組みを理解すりゃ 字ずら通り(リテラルな)意味だとわかるはず。

この本は過去ログで何度も勧めてきたし その本をもっているはずの回答者も頓珍漢なことをいってるから
人間の思い込みはなかなか解けないみてえだな!

本代はやすいものだし著者が損はさせないといってるから買ってよむこと。厳命です(^^;

それでも不思議におもうならどんな点かこちらがしりたいね。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月26日(水) 08:18
by Math
老婆心でいえば
#9では
CのまえねB をつくるときBCPL(ベーシック コンパイラーだったと思う)を参考にしていた
Bはスカラーしかなくポインター も アダレス カウンター も 整数型みたいなものも おなじ レジスターのおおきさで おなじだった。インクリメントすれば 1 アドレスすすんだわね。

それをCもうけついで sizeof だけすすめるようになったよね。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月26日(水) 10:16
by Math
まあ初心者なみの説明ですがここは有名でっせ。
https://www.sejuku.net/blog/25094

いまはアマがプロを簡単に追い抜く時代です。スマホで幼稚園のこが音声検索やカメラで映像検索するし
私もスマホの音声検索を主に使うけどPCよりよっぽど便利よ。検索リテラシーいまは決めてですよね。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月26日(水) 10:51
by usao
オフトピック
【世の中に「ポインタがわからん」という人々が溢れている】
という話が真なのであれば(個人的にはこれ系の話自体が偽なんじゃないかと疑ってるけど)

これからそうなるかもしれない対象たる初心者に向けた文章に
> 「ポインタはアドレスだ」
なんていう ふわっとした フレーズが
時に,「ポインタは難しいぞぉ!」だの「文法がどうのこうのっ!」だのいう刷り込み目的としか思えない謎の呪文句を添えた形で
存在したりしていることがそもそもの元凶なんじゃないか? とか思えてしまう.

(個人の感想です)

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月26日(水) 11:11
by usao
オフトピック
つまり,初心者をポインタで迷子にしないための方法として,以下が考えられる.

【「ポインタは難…」とか「Cの文法が…」とかいう話を展開しているような本なりサイトに出くわした場合,それは読まずに別のを探すこと】
という指針を前もって与える,という方法.

この篩はうまく機能する気がしてならない.

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月27日(木) 08:43
by ISLe
オフトピック
ポインタは、慣れるまで難しいのは事実で、ポインタをある程度扱うようになった、あるいは扱わざるを得なくなったヒトがハマるパターンも。

デバイスを扱うライブラリの初期化関数に、ダブルポインタで、デバイスを定義した構造体へのポインタを取得する、みたいなのがよくある。
そういうライブラリを初めて使うようなヒトが、ダブルポインタで宣言した変数を実引数としてしまうミスをしがち。
正しくは、シングルポインタで宣言した変数に、アドレス演算子付けたのを実引数にする。

深く考えず*や&を付けてしまう第一の壁。
*や&を付ける必要性に悩む第二の壁。

そこに「ポインタはアドレスだ」というフレーズの影響力。
オフトピック
ここの 補足:ポインタは配列より高速か? という見出し(タグがないけど)の文章がタイムパラドックス。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月27日(木) 11:17
by Math
#47

http://wisdom.sakura.ne.jp/programming/c/c25.html

のように具体例でしめしてね。

でないと#45、#46 でいわれていることに該当するようにみえまっせ。

抽象論でおどかすなよ!
それしマイナーなハードよりアセブラよりな内容でしょ。
#9に説明があるようにポインターをつかっても配列でも”最適化”されるから同じ事ならわかりやすくということ。
PDP-11の機械語の名残り 3項演算子 なんていまはつかわないだろ。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月27日(木) 17:23
by ISLe
オフトピック
Direct3DのCreateDeviceとか具体例に思い当たらなかったら突っかかってこないでほしいなあ。
Direct3Dは、マイナーなハードのアセンブラよりの内容だったかあ。

深く考えずに入門書のコードをコピペしてた人が、コピペをやめると途端にやらかすのを、けっこう見掛けるんですけどねえ。
オフトピック
オフトピック
江戸時代の手紙は、飛脚という職業の人が徒歩や馬で運んだらしいですよ。
なんで、自動車や電車を使わなかったんでしょうね。
C言語の最適化が大きなブームになっていたのは、わたしが20代のころでしたね。
DOSエクステンダで、コンパイラが潤沢なメモリを使えるようになったころからです。
当時、Cコンパイラは有償で高価だったので、無償で利用できるgccが人気でした。
マニア以外に浸透したのはウィンドウズ95の登場でプロテクトモードが当たり前になって以降ですかね。
K&Rが最初に出版されてから実に20年近く経ってのことです。

当時わたしはX68000でgccを使っていて、割と早くからコンパイラの最適化の恩恵にあずかってました。
配列演算とポインタ演算で同様のコードを生成するループ最適化の実装には感動しましたね。
逆に言えば、それ以前は、なかったわけですけどね。

いまはこうなんだから、最初からやっとけよってのは、かなり頭の悪い発言じゃあないですかね。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月27日(木) 18:44
by Math
そうだったのですか”愛する”さん(^^;

たしかシャープに X68000 のマシンがありましたね。

懐かしい!

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月28日(金) 23:32
by かずま
ISLe さんが書きました:
6年前
そこで疑問が…
「ポインタはアドレスだ」ってどういうことすか。
(1)「ポインタはアドレスだ」
(2)「ポインタは変数だ」
(3)「ポインタは型だ」

(4)「int は整数だ」
(5)「int は変数だ」
(6)「int は型だ」

(3) と (6) は誰でも正しいと思うのではありませんか?

(5) は変だと思いますよね。
int i = 3; という宣言があった時、
・i は int で、変数です。
・3 は int ですが、変数ではありません。定数です。
・i + 5 は int ですが、変数ではありません。+演算子の式です。
変数でない int があるのです。int は型ですから。

(2) も同じです。
int i = 3; int *p = &i; という宣言があったとします。
・p はポインタで、変数です。
・&i はポインタですが、変数ではありません。単項&演算子による式です。
 i が静的変数(グローバル変数、または static がついた変数)の場合、
 &i を「アドレス定数」ということが規格書に記述されています。
・p + 5 はポインタですが、変数ではありません。+演算子の式です。
変数でないポインタもあるのです。ポインタは型ですから。

(4) は「int は型だが、その保持する値は整数だ」という意味では正しい。
もちろん個数が無数である数学の整数とは異なりますが。

(1) は「ポインタは型だが、その保持する値は(ある変数の)アドレスだ」と
言えます。関数のアドレスは今は考えないことにします。

アドレスとは何か、というのは規格書には記述されていないのですが、
メモリのどの位置かを表す値であるということは認識されていると思います。

ポインタはアドレスを値として保持しますが、さらにメモリのその位置に
どんな型のオブジェクトがあるのかを確定できます。
int へのポインタ、char へのポインタ、double へのポインタなど。

アドレスには、その位置に何があるかという情報がないのが
ポインタとは異なることです。

なお、初心者が「ポインタはアドレスだ」とどういう意味で言っているのかは
私にはわかりません。

Re: 配列へのポインタ (*a)[10] について

Posted: 2019年6月29日(土) 08:23
by Math
ポインターは基本型ではない。
K&R に詳述されているように
 
基本型を先頭に派生型を再帰的にくりかえし 無限の型を作り出すことができる。

http://www.officeuchida.com/pdt/pdtsamp2.html

Re: 配列へのポインタ (*a)[10] について

Posted: 2020年4月07日(火) 21:01
by あたっしゅ
>ところでアセンブラでブートストラップから書けるひといる(^^;

川合秀美さんの x86 で OS を作る本(複数)を参考にして、8086 の Real モードで IPL、書いてますよ。