K.Maebashi's BBS

ご自由に書き込んでください。雑談も可。
テスト書き込みの類はテスト用掲示板にどうぞ

[日付順表示] [日付順インデックス] [スレッド順インデックス]

新規投稿 | 開設者ホームページへ戻る | ヘルプ

[801] Re:左辺値としての配列名
投稿者:774RR
2007/02/20 02:13:25

あう sizeof は右辺値でもいいのか。 だったら「sizeof の係る式が左辺値の場合には右辺値変換するな」って旨を コンパイラ作者に通知する条文でもあるわけだな。 結論は変わらん。
[この投稿を含むスレッドを表示] [この投稿を削除]
[800] Re:左辺値としての配列名
投稿者:774RR
2007/02/20 02:13:25

規格書の一部はコンパイラ作者向けに、一部はユーザ向けに書かれている。 で、当該項はユーザ向けだと、俺は思う。 俺がコンパイラ作るなら、左辺値が必要とされる文脈で右辺値変換するなんて無駄なことはしない。 単項 & や sizeof はまさに左辺値が必要とされるところであるから、そこで 無駄な右辺値変換を行わなければ規格書どおりの動作となるわけだ。 同じことが代入式の左辺でもいえる。 だから、俺的には配列名が代入式の左辺に現れたときに右辺値変換されるとは思わない。 「変更不可能」だから左辺におくとエラーと考えるほうが自然。 まあどう解釈しても結果は同じだからどうでもいいけど。
[この投稿を含むスレッドを表示] [この投稿を削除]
[799] Re:左辺値としての配列名
投稿者:yuya
2007/02/20 02:13:25

前橋さん、774RRさん、ありがとうございます。 > 配列に代入できないのは変更可能な左辺値ではないから なるほど、 「配列に代入できないのは、配列は左辺値だが変更不可能だから」 と考える必要はないんですね。 「『変更可能な左辺値』ではないもの」には、 「変更不可能な左辺値」だけでなく「右辺値」も含まれますから。 (a)変更可能な左辺値 (b)変更不可能な左辺値 (c)右辺値 (d)その他 に分けたとして、 ・「ポインタ完全制覇」での説明:    「配列に代入できないのは、(c)だから」 ・私が[796]で書いた説明:    「配列に代入できないのは、(b)だから」 ・おそらく最も正確な説明:    「配列に代入できないのは、(a)でないから」 「(a)でない」を満たしさえすれば 配列に代入ができないことには変わりなく、 その実態が(b)なのか(c)なのか、あるいは(d)なのかは 別問題である、ということですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[798] Re:左辺値としての配列名
投稿者:774RR
2007/02/20 02:13:25

char a[10]; char (*p)[10]=&a; // である場合に *p=0; あるいは *p={0}; であれなんであれ *p は代入式の左辺に置けません。 JIS X 3010:2003 6.5.16 代入演算子 [制約] 変更可能な左辺値でなければならない。 JIS X 3010:2003 6.3.2.1 変更可能な左辺値とは...[配列を含まない] なので >配列に代入できないのは変更可能な左辺値ではないから であり、それ以上でも以下でもないです。 ただしこの話はスレ題の「左辺値が要求される場所においても読み替えが起こるか」とは無関係。 無関係ではありますが、やはり同じく JIS X 3010:2003 6.3.2.1 型"~の配列"を持つ式は、型"~へのポインタ"の式に型変換する。 それは配列オブジェクトの先頭の要素を指し、左辺値ではない。 とありますから、スレ題に関して言えば「どちらでもいい」となります。 起こると解釈しても起こらないと解釈しても、いずれにせよ代入式の左辺に置けないことに違いは無い。 ところで JIS X 3010 は 2003 版が発行済で 2003 版には 6.2.2.1 が無かったです。 引用元は 1990 版でしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[797] Re:左辺値としての配列名
投稿者:(ぱ)
2007/02/20 02:13:25

>配列名は式の中では先頭要素へのポインタ(右辺値)に読み替えられる、 >という規則は、代入演算子の左側のような、 >「左辺値が要求される場所」においてもそうなのでしょうか? JIS X3010の6.2.2.1によれば、 | 左辺値がsizeof演算子のオペランド、単項&演算子のオペランド、文字配列を初期化 | するのに使われる単純文字列リテラルまたはwchar_tに適合する要素型をもつ配列を | 初期化するのに使われる文字列リテラルである場合を除いて、型"~型の配列"をもつ | 左辺値は、型"~型へのポインタ"を持つ式に型変換する。 とあります。 もし、代入演算子の左側のような「左辺値が要求される場所」においては配列から ポインタへの読み替えが行われないのだ、とするのなら、上記の3つの条件の中に 単項&演算子のオペランドを含める必要はないはずです。&演算子のオペランドは もともと左辺値が要求される場所だからです。 ということで、上記3つの箇所を除いて、(左辺値が要求されようがされまいが) 式の中では配列はポインタに読みかえられる、と解釈するのが自然ではないでしょうか。 # とはいうものの、「変更可能な左辺値」の定義からわざわざ配列が除かれている # ところからすると、配列に代入できないのは変更可能な左辺値ではないからだ、 # という解釈もできるような気が…
[この投稿を含むスレッドを表示] [この投稿を削除]
[796] 左辺値としての配列名
投稿者:yuya
2007/02/20 02:13:25

こんにちは。Cの「配列名」について、質問があります。 「ポインタ完全制覇」には、 char hoge[5]; hoge = "abcd"; がダメな理由は、hogeが右辺値だから、とあります。 配列名は式の中では先頭要素へのポインタ(右辺値)に読み替えられる、 という規則は、代入演算子の左側のような、 「左辺値が要求される場所」においてもそうなのでしょうか? 配列名は、右辺値(先頭要素へのポインタ)に読み替えられる前は、 配列オブジェクトそのものを表す変更不可能な左辺値なので、 「hoge = "abcd";がダメなのは、hogeは左辺値だけど変更不可能だから」 という説明であれば納得できるのですが、 どちらの説明が正しいのでしょうか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[795] Re:ポインタってそんなに難しいか?
投稿者:774RR
2007/02/20 02:13:25

>ところで、ポインタの概念は難しくないですが、使いこなすのは大変だ 禿げ上がるほど御意。 むかーーーーしの自分のソースを見ると良くわかったりします。 >実行時に型情報を持っていると誤解する人が出そうです。 今までに扱ったCPU/コンパイラ全てで「実行時型情報をもつポインタ」って無いですね。 無駄っぽなので。ただ、規格書は何も言及してないので「あっても違反ぢゃない」です。 # CPU 何種類使っただろう? 両手ぢゃ足らんくらいだな。 メモリアドレスをどう扱うか、ソースレベルで指定してる。と言うべきだったかな。 C++ の dynamic_cast/typeid 系が扱う型情報は、ポインタ自体にではなく、 その指す先のオブジェクトにあるワケで、やはりポインタには型情報は無いな。
[この投稿を含むスレッドを表示] [この投稿を削除]
[794] Re:ポインタってそんなに難しいか?
投稿者:(ぱ)
2007/02/20 02:13:25

>タイトルのとおりなのですが、ポインタってそんなに難しいですか? 難しいのでは。少なくとも難しいと思う人がいるからこそポインタ本の需要が生まれ、 私が日々の酒代を稼ぐ余地が生まれたというものです。ありがたいことです(ぉぃ) >正確には「ポインタの概念が」難しいと思ったこと無いというべきかな。 >ポインタ関連の表記が難しいとは思ったけど。 これはそう思います。私のそのへんに関する認識は、以下のページの冒頭に書きました。 http://kmaebashi.com/programmer/pointer.html だからこそ、ポインタ完全制覇では、宣言の構文やら配列とポインタの関係やらに 力を入れたつもりなのでして、「負け組一号」さんがまだわからないところがあるのなら、 具体的にどこがどうわからないと言っていただければ、アドバイスできるかもしれませんし、 私にとっても参考になるわけなのですが。 ところで、ポインタの概念は難しくないですが、使いこなすのは大変だ、というのも ありますね。同じオブジェクトを複数箇所から指して思わぬ書き換えをしてしまったり、 Cだと、free()しすぎや領域破壊の危険も高いです。 >メモリアドレスに、その扱い方の情報を付帯してるだけぢゃん。 774RRさんは当然わかって書いていると思うのですが、この言い方だと、ポインタが 実行時に型情報を持っていると誤解する人が出そうです。
[この投稿を含むスレッドを表示] [この投稿を削除]
[793] ポインタってそんなに難しいか?
投稿者:774RR
2007/02/20 02:13:25

タイトルのとおりなのですが、ポインタってそんなに難しいですか? 俺なんかは Z80 のアセンブラから入った口なので、ポインタが難しいと思ったこと無いです。 正確には「ポインタの概念が」難しいと思ったこと無いというべきかな。 ポインタ関連の表記が難しいとは思ったけど。 難攻不落なんて言うほどのものぢゃ糸色文寸無い。 メモリアドレスに、その扱い方の情報を付帯してるだけぢゃん。
[この投稿を含むスレッドを表示] [この投稿を削除]
[792] Re:ポインタ完全制覇
投稿者:774RR
2007/02/20 02:13:25

>もしsetjmp/longjmpがcreate_jmp()してから使うような形であったら、&なしがきれいですよね。 御意。 > 今まで考えなしに付けてなかったですけど、概念的には付けるべきだったのかしら。 俺なんかはその昔の &array が規定されてなかった頃からCをやってる人ですから 「配列名が先頭要素へのポインタに変換される」仕様が本能レベルで染み付いているので memset 等のポインタが必要な関数が使われてて引数に & が無い場合にはむしろ 「& がないから、これって配列なんだ」と解釈しがちな傾向がありますな。 # よく読んだら、ポインタ変数だったりすると後からびっくり。 概念的には & があるべきなのだと思う。ただ歴史的事情により 配列であることが明確な場合には & を書かないソースのほうが圧倒的多数だと思います。 > 例えば「配列へのポインタ」と「配列の先頭要素へのポインタ」の > 表現方法が異なるような処理系において > ...では、やっぱりmemset()の使用は推奨されないのかなぁ? void* は、内部表現が最大サイズとなるポインタを保持できなければならず、なおかつ、 必要な時には内部表現を失わずに元の型に戻せることが必須とされていますから、 問題ないです(問題あったら大変だ) # テスト略
[この投稿を含むスレッドを表示] [この投稿を削除]
[791] Re:ポインタ完全制覇
投稿者:本多
2007/02/20 02:13:25

#テストの(略) >>jmp_buf の場合は「set/longjmp で使うハンドル」と考えれば & なしにも違和感なし >handle = CreateWindow(...); >みたいなのだと思うので、戻り値ではなく引数で返すならやっぱり&が付くのではないかと。 もしsetjmp/longjmpがcreate_jmp()してから使うような形であったら、&なしがきれいですよね。 jmp_buf myjmp = create_jmp(); if ( (ret = setjmp(myjmp)) == 0 ) { ... } else { ... } ~略~ longjmp(myjmp, ret); >memset()の場合でも、&を付けない人のほうが多いんじゃないかなあ。 今まで考えなしに付けてなかったですけど、概念的には付けるべきだったのかしら。 例えば「配列へのポインタ」と「配列の先頭要素へのポインタ」の 表現方法が異なるような処理系において ...では、やっぱりmemset()の使用は推奨されないのかなぁ?
[この投稿を含むスレッドを表示] [この投稿を削除]
[790] Re:ポインタ完全制覇
投稿者:(ぱ)
2007/02/20 02:13:25

# テストに反応してみるテスト >jmp_buf の場合は「set/longjmp で使うハンドル」と考えれば & なしにも違和感なし ハンドルといえば、 handle = CreateWindow(...); みたいなのだと思うので、戻り値ではなく引数で返すならやっぱり&が付くのではないかと。 >memset の場合は要求されるのが void* だから &array のほうが適切な場合多し >strcpy の場合は要求されるのが char* だから array と書かなきゃいけない >scanf+%s の場合も同様 memset()の場合でも、&を付けない人のほうが多いんじゃないかなあ。 適当にぐぐって見たけど付いてない例が多いようです。 http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vclib/html/_CRT_memset.asp http://www.cppreference.com/stdstring/memset.html >C/C++ はエラーメッセージの読み方が難しいのが減点ポイント (馬から落馬) まあ、エラーメッセージの良し悪しはコンパイラによるところもあるとは思いますが、 C言語自体が多様な書き方を許すためにエラーメッセージがわかりにくくなるところは ありますね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[789] Re:難解不落のポインタ すべてはプログラマにゆだねられ プログラマはポインタに揺らされる
投稿者:(ぱ)
2007/02/20 02:13:25

>char* p,p2; >とするとp2は >char p2;となってしまうと理解させていただいています。 この問題だけであれば、一度に複数の変数を宣言するなゴルアで回避できるのですが、 Cではたとえば配列なども型の一部ですから、どっちみち 型 変数名; の形では変数宣言を解読できないんですね。CESさんが出した問題がそうであるように。
[この投稿を含むスレッドを表示] [この投稿を削除]
[788] Re:面白い本を探しているのですが……
投稿者:(ぱ)
2007/02/20 02:13:25

>前橋さんの本やこのホームページは、 >扱っている技術の内容が高く、 >現場のプログラミングにおいても、 >ものすごく役に立つのでよく見ています。 ありがとうございます。 >さて、私も「Java謎+落とし穴」を最近読んだのですが、 >少し内容が古くなってきたように感じます。 これは確かにそう思います。 >特に進化のスピードが速いJavaでは、 >本書で前橋さんが苦言を呈している >ジェネリックやenumなどの機能については、 >現在、ほとんど盛り込まれています。 そうですね。 >そこで、ここ最近、話題になっている? >「疑い深いあなたのためのオブジェクト指向再入門」 >の内容に加筆したものを新規に書き起こして、 >加筆修正した改訂版を出してはどうでしょうか。 >(単に私が読みたいだけですが。) 「疑い深いあなたのためのオブジェクト指向再入門」にあることは、言いっぷりは ともかくとして「謎+落とし穴」にも書いたつもりですから、J2SE5.0対応の改訂版、 ということになるのだと思いますけれど。 書いてみたいネタではあります。ただ、J2SE5.0は仕事で使っていないので、 本が書けるところまで私自身わかっているか、という問題はありますね。 # 仕事じゃまだまだJDK1.3が現役だったりします。
[この投稿を含むスレッドを表示] [この投稿を削除]
[787] Re:ポインタ完全制覇
投稿者:774RR
2007/02/20 02:13:25

# あれこれ言ってみるテスト jmp_buf の場合は「set/longjmp で使うハンドル」と考えれば & なしにも違和感なし なまじ buf という文字列が見えてしまっているのが名前付けに失敗した例と思う memset の場合は要求されるのが void* だから &array のほうが適切な場合多し strcpy の場合は要求されるのが char* だから array と書かなきゃいけない scanf+%s の場合も同様 GCC はフォーマット文字列がリテラルな場合に警告してくれます。 scanf("%s", &buf); に対して gcc -Wformat hoge.c で piyo.c:4: warning: char format, different type arg (arg 2) みたいに。 C/C++ はエラーメッセージの読み方が難しいのが減点ポイント (馬から落馬) たいていの原因はエラー表示のある行の直前にあったりするし。 template 多用時は俺でもエラー判別がめんどくさかったりするですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[786] 難解不落のポインタ すべてはプログラマにゆだねられ プログラマはポインタに揺らされる
投稿者:負け組一号
2007/02/20 02:13:25

Thank you for res. >char *p; > >よりも > >char* p; > >と書くほうがわかりやすい、という意味でしょうか? >それはそれで否定しませんが、それで問題は解決しない、ということもポインタ完全制覇は これについては、著書で理解しております。 char* p,p2; とするとp2は char p2;となってしまうと理解させていただいています。 あと、char *p;としてprintf("%p",p);としたとき参照されてない というエラーがでましたが、まぁ、ただ、もう理解してますので、蛇足です。 あと、他の言語では、配列とポインタは、”ほぼ別格”というのは、新たな知識として ありがとうございます。 とりあえず、今は構造体のリストを理解するために、脳をこねくりまわしている状態です。 しっかし、まぁ、I study hard and more hard to purogramming-Cってなことですな~ ついでの蛇足で int dt = (a = 20,b=10);とすると dt=10となるなんていう、たぶん一生必要ない知識ですが、まぁ、なんというか・・・ 色々あるな~・・・と思う、日々。 年々歳々花相似たり、年々歳々人同じからず
[この投稿を含むスレッドを表示] [この投稿を削除]
[785] Re:面白い本を探しているのですが……
投稿者:七氏
2007/02/20 02:13:25

>>こんにちは。はじめまして。 >>Java謎+落とし穴を読ませていただきました。 > >どうもです。 > >>他の著者の方や他の言語でもこういう「面白い」本はあるのでしょうか。 > >分野がわからないとアレですが、アスキーの256倍シリーズとかですかねえ。 はじめまして。 前橋さんの本やこのホームページは、 扱っている技術の内容が高く、 現場のプログラミングにおいても、 ものすごく役に立つのでよく見ています。 さて、私も「Java謎+落とし穴」を最近読んだのですが、 少し内容が古くなってきたように感じます。 特に進化のスピードが速いJavaでは、 本書で前橋さんが苦言を呈している ジェネリックやenumなどの機能については、 現在、ほとんど盛り込まれています。 そこで、ここ最近、話題になっている? 「疑い深いあなたのためのオブジェクト指向再入門」 の内容に加筆したものを新規に書き起こして、 加筆修正した改訂版を出してはどうでしょうか。 (単に私が読みたいだけですが。) 結構、売れると思いますw(余計なお世話ですか?)
[この投稿を含むスレッドを表示] [この投稿を削除]
[784] Re:ポインタ完全制覇
投稿者:CES
2007/02/20 02:13:25

>ポインタの読み方から頑張って導こうとしなくても、こんなのを書いちゃうと一発だと、散々悩んでから気がついた。 > >template< typename ReturnType > >ReturnType Test(); > >std::cout << typeid( Test< char(*)[10] > ) << std::endl; マチガヘタ。 std::cout << typeid( Test< char(*)[10] > ).name() << std::endl; が正しい。
[この投稿を含むスレッドを表示] [この投稿を削除]
[783] Re:ポインタ完全制覇
投稿者:CES
2007/02/20 02:13:25

>>問: >>char 型の配列へのポインタを返す関数の宣言を記述しなさい。 >>関数名、引数、戻り値の要素数は任意とする。 > >用途としては、「\0込みで30文字以内の文字列を可変の個数返す関数」とかですかね。 ポインタの読み方から頑張って導こうとしなくても、こんなのを書いちゃうと一発だと、散々悩んでから気がついた。 template< typename ReturnType > ReturnType Test(); std::cout << typeid( Test< char(*)[10] > ) << std::endl; ちなみに、皆さんご存知だと思うけれど、正解はこう(N は要素数)。 char ( * f() )[ N ]; なんでこんなもので悩んでいたかというと、VC++ に奇怪なソースを発見したから。 配列の要素数を数えるコード。 template< typename _TypeOfArray, size_t _SizeOfArray > char ( * __countof_helper( _TypeOfArray ( & )[ _SizeOfArray ] ) )[ _SizeOfArray ]; #define _countof( _Array ) sizeof( * __countof_helper( _Array ) ) __countof_helper は、日本語で言うと「_TypeOfArray 型の配列(要素数は _SizeOfArray 個)の参照を引数に取り、char 型の配列(要素数は _SizeOfArray 個)のポインタを返す関数」の宣言。 返ってきたポインタを間接参照して sizeof すれば、引数に渡した配列と同じ要素数の char 型の配列のサイズ、すなわち引数の要素数が手に入るというカラクリ。 テンプレートに引数配列の要素数まで推測させているのにビックリ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[782] Re:ポインタ完全制覇へはまだ遠し
投稿者:(ぱ)
2007/02/20 02:13:25

>これなら、配列に書き込む時オーバーフローしてもしかたがないと思う反面 >過去にどっかで、誰か偉い人が、配列というものをポインタとはまた別の物として >規定をなぜしてくれなかったのかと思います。 配列とポインタがこんなふうにこんがらがった変な言語はC/C++くらいなものであり、 たいがいの言語では、明確に別なものとして定義されています(ポインタではなく 参照と呼んでいるかも知れないけれど)。 ポインタ完全制覇にも書いたように、Cはもともと現場の要求を満たすために でっちあげられた言語なので、「ベストな言語」どころか「ベストを目指した言語」 でもないように思います。でも、そこそこよくできていたため広く使われてしまった、 というのが世の常であるわけで。 デザインの「悪い方がよい」原則 http://chasen.org/~daiti-m/text/worse-is-better-ja.html >ついでに、初期化で >char array[] = "abcd"; >char *p = array; >の意味が最初僕はわかりませんでした。「*pの内容にarray?どういうこと?」と思いました >これもchar* p = array;とすれば意味がすんなりわかりました。 これは、 char *p; よりも char* p; と書くほうがわかりやすい、という意味でしょうか? それはそれで否定しませんが、それで問題は解決しない、ということもポインタ完全制覇には 書きました。
[この投稿を含むスレッドを表示] [この投稿を削除]
[781] Re:面白い本を探しているのですが……
投稿者:(ぱ)
2007/02/20 02:13:25

>こんにちは。はじめまして。 >Java謎+落とし穴を読ませていただきました。 どうもです。 >他の著者の方や他の言語でもこういう「面白い」本はあるのでしょうか。 分野がわからないとアレですが、アスキーの256倍シリーズとかですかねえ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[780] Re:ポインタ完全制覇
投稿者:(ぱ)
2007/02/20 02:13:25

本多さん: >「&a」で取得できる「配列へのポインタ」って使い道ってあります? 私の認識は、こっちに書いた通り。 http://kmaebashi.com/programmer/pointer.html | 配列から読み換えられたポインタは左辺値を持たないため、 & 演算子の | オペランドにはならないはずであるが、この例外規則のため、 & でアドレス | (配列の先頭要素のアドレスではなく、配列全体のアドレス)が 取得できる。 | この規則は初心者を混乱させることがある (例えば scanf("%s", buf) でなく、 | scanf("%s", &buf)と書いても 正常に動いてしまう(正常に動いたように見えて | しまう)が、 メリットは今ひとつわからない。 774RRさん: >int a[10]; >memset(&a, 0, sizeof a); >配列だから &a にせずとも a とだけ書けば事足りるのだが、配列の場合だけ & 不要ってのは >(単なる表記の問題ではあるが)初心者を惑わすもととなりうるんで。 strcpy(dest, src)とかでもdestに&は付きませんから、これは付けないほうが むしろ統一が取れるのではないでしょうか。 >typedef int i10[10]; // これは .h ファイルにあって >i10 a; memset(&a, 0, sizeof a); // こっちは .c ファイルにある >の場合には & ありのほうが自然で、ないのは不自然。 MinGWのsetjmp.hより: typedef _JBTYPE jmp_buf[_JBLEN]; でも、setjmp()を使うときは、 jmp_buf buf; if (setjmp(buf) == 0) { ... なのであって、&は付けません。 まあ、前から書いているように、私もこれって不自然だと思うんですが。
[この投稿を含むスレッドを表示] [この投稿を削除]
[779] Re:ポインタ完全制覇
投稿者:(ぱ)
2007/02/20 02:13:25

>問: >char 型の配列へのポインタを返す関数の宣言を記述しなさい。 >関数名、引数、戻り値の要素数は任意とする。 用途としては、「\0込みで30文字以内の文字列を可変の個数返す関数」とかですかね。 CADやってたころは、たとえば3次元ポリラインなどで、「double3つの可変長配列」を よく受け渡ししたものです。また、4×4の行列もしょっちゅう引数で受け渡ししました。 配列を引数で渡すとき、 void func(double a[]) のように書けるシンタックスシュガーは、私は混乱を招くだけだと思うのですが、 やっぱりこれを使ったほうが読みやすい、という主張もわからなくはないです。 特に多次元配列では。 でも、仮引数の宣言でしか使えない(戻り値とか、一時変数に代入する時には使えない) んじゃやっぱ中途半端だよなあ。
[この投稿を含むスレッドを表示] [この投稿を削除]
[778] ポインタ完全制覇へはまだ遠し
投稿者:負け組一号
2007/02/20 02:13:25

レスありがとうございます 私は 技術評論社の入門本物志向が身に付く本(浅井 淳さん 著)とウェブの初心者ページ で初心者としての知識を身につけ 初心者用問題集(確か~望洋さん 著)の本を一通り解いて C言語ポインタ完全制覇(前橋 和弥さん 著)と C言語文字列操作+ファイル入出力完全制覇(山地 秀美さん 著)を買い C言語文字列操作+ファイル入出力完全制覇の構造体を使ったリストの所で 頭がこんがらがり、今は、C言語入門シニア編(林 晴比古さん 著)by ソフトバンク で勉強中で、かつ、プログラムはなぜ動くのか(矢沢 久雄さん 著)by 日系BPを読み アセンブラを勉強した方が良いのか?と思いつつ、とにかくC言語をという感じで 勉強中です。 以上駄文ですが、なにかお勧めの本はありますか?あれば教えて頂きたいです。 このBBSにふさわしくない内容でしたら削除します。駄文もうしわけない。 ちなみに、ポインタに関しては、さし棒と考える事にしてます そんで、array[index]=*((array)+(index))だし これなら、配列に書き込む時オーバーフローしてもしかたがないと思う反面 過去にどっかで、誰か偉い人が、配列というものをポインタとはまた別の物として 規定をなぜしてくれなかったのかと思います。 ついでに、初期化で char array[] = "abcd"; char *p = array; の意味が最初僕はわかりませんでした。「*pの内容にarray?どういうこと?」と思いました これもchar* p = array;とすれば意味がすんなりわかりました。 で、勉強すればするほど、シンタックスシュガーなるもの、プログラミング言語に 存在してはいけないのじゃないのか?と初心者ながらに思いつつ 「まぁ、偉い人がこう決めたんだから、必要性もあるんだろう」と思っています。 以上、失礼します。
[この投稿を含むスレッドを表示] [この投稿を削除]
[777] Re:ポインタ完全制覇
投稿者:774RR
2007/02/20 02:13:25

たとえばこんなのとか int a[10]; memset(&a, 0, sizeof a); 配列だから &a にせずとも a とだけ書けば事足りるのだが、配列の場合だけ & 不要ってのは (単なる表記の問題ではあるが)初心者を惑わすもととなりうるんで。 typedef int i10[10]; // これは .h ファイルにあって i10 a; memset(&a, 0, sizeof a); // こっちは .c ファイルにある の場合には & ありのほうが自然で、ないのは不自然。 個人的には char (*)[N] を単体で使うってのは他ではナイなぁ。 二次元(以上)配列を使うときに現れるだけだと思う。
[この投稿を含むスレッドを表示] [この投稿を削除]
[776] 面白い本を探しているのですが……
投稿者:もつ
2007/02/20 02:13:25

こんにちは。はじめまして。 Java謎+落とし穴を読ませていただきました。 難しい話がなぜか面白い文章になっていて読むのがとても楽しかったのですが、他の著者の方や他の言語でもこういう「面白い」本はあるのでしょうか。
[この投稿を含むスレッドを表示] [この投稿を削除]
[775] Re:ポインタ完全制覇
投稿者:本多
2007/02/20 02:13:25

>「配列へのポインタ」の存在価値がわからんという人も居たな。 >多次元配列(より正確には配列の配列)を考えれば存在価値がわかるだろう。 「配列へのポインタ」という型はもちろん存在価値があるのですが、 読んでてふと思ったことがあります。 「int a[10];」という配列に対して、 「&a」で取得できる「配列へのポインタ」って使い道ってあります? っていうか実務で使った経験ってありますか? int a[10][20]を受け取る関数の引数とかでなく、 配列自身に「&」をつけて、それを使うプログラムを使ったことが、です。 言語仕様を確認しようとしたチョイプロとかじゃなくて 何か明確な意図を持って、それを使わなくちゃいけない または使うほうが適切と判断するような場面ってありましたか?
[この投稿を含むスレッドを表示] [この投稿を削除]
[774] Re:ポインタ完全制覇
投稿者:774RR
2007/02/20 02:13:25

カンペキだ... もう何も言うことは無い。俺が書かなかった内容まで指摘済み。以下蛇足。 > ポイント先は「50バイト分のヒトカタマリ」であって、 これが理解できない人がいる、ってのが理解に苦しむというかなんというか。 int* だって 2byte なり 4byte なりの塊を指すワケだし、何一つ違わないと思うのだが。 もっと言うなら char* だって 8bit の塊 (もっと大きいこともあるが) を指すのだし。 「配列へのポインタ」の存在価値がわからんという人も居たな。 多次元配列(より正確には配列の配列)を考えれば存在価値がわかるだろう。 char a[10]; char (*p)[10]=a; なとき *p=0; と書けないから理解できんのだろうか。そりゃ無謀ってもんだが... っと、先の [772] は yuya さん宛てに書いたのではなくって ROM 者のための課題だったので そこの ROM なあなた、自分で一度考察してみると理解が深まって吉ですぜ。 # 774 げっと
[この投稿を含むスレッドを表示] [この投稿を削除]
[773] Re:ポインタ完全制覇
投稿者:yuya
2007/02/20 02:13:25

頭の整理のために、ということで。 A1'. char(*)[10] はchar配列(要素数10)へのポインタ。 char*[10] はcharへのポインタの配列(要素数10)。 A1". char (*hoge)[10]; Q3. 暗黙の変換前は 「charの配列(要素数10)の配列(要素数5)」型であり、 b[0]~b[4]の5つ(配列が5つ)のこと。 暗黙の変換後はその先頭要素へのポインタになるので、 「charの配列(要素数10)へのポインタ」型の右辺値となり、 そのポイント先はb[0]です。 「b + 1」はb[1]を、つまり10バイト離れたところをポイントします。 Q4. &bの「b」は暗黙の変換が行なわれないので、 配列そのもの(この場合は「配列の配列」という配列そのもの)になり、 それに「&」を付けた「&b」は「charの配列の配列へのポインタ」型の右辺値です。 「&b」のポイント先は「50バイト分のヒトカタマリ」であって、 「&b + 1」はもはや配列外をポイントするので、 ここを書き換えると何が起こるか分かりません。それこそ >「配列へのポインタ」で示される先に実体が1つあるだけ という状態ですね。
[この投稿を含むスレッドを表示] [この投稿を削除]
[772] Re:ポインタ完全制覇
投稿者:774RR
2007/02/20 02:13:25

こたえ書いちゃうのは簡単なので、書かずに盛り上げるテスト # この辺、ポインタ中級レベルになるのでしょうか?それとも上級? ここはまず「配列へのポインタ」っつーものがあることを理解しなければならない。 char a[10]; という配列があるとき &a[0] = 配列先頭要素へのポインタ右辺値 (char*) &a = char [10] 配列へのポインタ右辺値 (Q1. この型の表記を行え) である。これも概念レベルの問題なので理解できない人は一生理解しないままだったりする。 # A1.char(*)[10] 型。 Q1'. char(*)[10] と char *[10] の違いを述べよ Q1". char(*)[10] 型の変数を作るにはどう記述するといい? 先の例は「配列へのポインタ」で示される先に実体が1つあるだけ。つまりよくある char c; char* p=&c; と同じレベルの些細でつまらない例に該当する。だからより実用的な例に変えよう。 Q2.char b[5][10]; とするとき &b[0] の型を述べよ (答えは char[10] へのポインタ右辺値) Q3.では b とだけ書いたら何型で何を指す? (暗黙の変換前と変換後の両者を答えよ) Q4.では &b と書いたら何型で何を指す? このへんがすらすら答えられるようになるなら CES さんの問題も簡単。
[この投稿を含むスレッドを表示] [この投稿を削除]