- ベストアンサー
情報処理技術者試験は本当にC89?
情報処理技術者試験でのC言語の規格はC89とされています。 しかし、 int *p; p=(int *)malloc(sizeof(int)); のように,mallocの返り値をキャストしている問題文が過去にあります。一方、Wikipediaのmallocで調べてもC89のようなANSI規格ではキャストすべきでないとあり、あるサイトには「このキャストはC++との互換性のため」とも書かれています。初心者が受験する際に混乱します。 情報処理技術者試験でのC言語の規格は本当にC89なのでしょうか。「C++のことを気にしないとC言語が勉強できない」と誤解を与えるのでは。
- みんなの回答 (14)
- 専門家の回答
質問者が選んだベストアンサー
"一般的に"キャストをつけるかつけないかということに話がそれていませんか? 本題は情報処理試験であり、お堅い試験問題かと思います。 「どちらかが明白に正しいという命題ではない」というのは、一般的には そうかと思いますが、 試験問題として「どちらかが明白に正しいという命題ではない」 ものを問題(問題の一部)にするのはいかがなものかと思います。
その他の回答 (13)
- R32C
- ベストアンサー率39% (115/290)
C:\WorkSpace\test2\test2\test2.c(19) : [Error(ccom)] invalid '=' operand です。 回答しました。 いったいどこが愚痴なのかお答えください。
お礼
sakusaker7さんへの問いかけになっていますが、私からお礼させてください。 回答ありがとうございます。 このような流れになり私の力不足と反省しています。 私の力ではR32Cさんとsakusaker7さんのやり取りの内容を理解するまでに至りませんでした。申し訳ありません。 ただ、情報処理技術者試験を受ける方々が参考にされるであろう教科書ならびに参考書でどうなっているかを、本屋さんと図書館で調べました。 結果としては、最新のものほど、また、海外のものほど、キャストなしになっていました。時代の流れと感じます。 柴田望洋さんの著書では、過去の本ではキャストありでしたが、最新のものではキャストなしです。 また、海外の著名な本と思われるものでは、OSの説明(計算機システム)に近い本ではかなり早い段階でキャストなし、アルゴリズムの説明の本では最新ではキャストなしに変更されていました。 amazon で「ポインタ C言語」で検索して上位を占めているのは前橋和弥さんと柴田望洋さんの著書ですが、どちらも現時点ではキャストなしです。現状では、専門学校や大学等ではWeb等から推測するとキャストありで教えていると思われますから、対照的です。 また、他の方々にもお聞きした調べる中で強く感じたのは、Cのバイブル「K&R」の影響の大きさです。また、キャストありで育った方々は(私も含め)キャストなしでもよいことを知らない、ことも多くあるようでした。不勉強と言われればそうでしょうが。また、両者の違いをわかった上で、キャストありでまず教え、次の段階(時期の見極めが問題らしいのですが)としてキャストなしを教える、という意見をお持ちの方もおられました。ただ、教育方針(組織によりけり)と試験問題(色々な組織の人が受ける)をどうするかはまた別と思います。 以上です。
- sakusaker7
- ベストアンサー率62% (800/1280)
・lvalue のキャストは「しちゃいけない」ことです。 「必要ない」こととは違うと思います。 ・現実に生きのびて使われてるんだから、国語で出てくる「古文」とは違うでしょう。 いずれなくなっていくにしても、現状はそうじゃない。 #キャストなしのスタイルで書くなとは言ってない ・プロプラのソースなんて出せるわけないじゃない。 自分のハードディスクに展開されてたソースで見ただけなので、 もっと新しいプロダクトならこうだというのを 調べたいのならどうぞ。 ・試験問題なり参考書なりの記述に疑問を感じそれを正すべきだと お考えならお好きに運動なされば良いでしょう。 ただし少なくともこういうところで愚痴をぶちまけてるだけじゃ 状況は(自分の望むようには)変わらないと思います。 あと#5の例は自分でも書いている通り極端すぎ。 参考までに、キャスト抜きでエラーになるときって どんなメッセージが出るのでしょう?
- R32C
- ベストアンサー率39% (115/290)
オープンソースの記述が模範的なので 情報処理試験問題の問題としてふさわしいと、ひょっとしてお考えなんですか??? ちょっと格が違うかもしれませんが 例えばTOPPERS/JSPのソースにしても、コンパイラの進化によって 通らないコードとかもあります。 例) M16c-renesas/cpu_config.h Inline void activate_context(TCB *tcb) { VW *sp; VW return_point = (VW)ext_tsk; sp = (VW *)(((VB *) tcb->tinib->stk) + tcb->tinib->stksz); *--sp = (VW)(tcb->tinib->exinf); *--((VB*)sp) = (VB)(return_point >> 16); *--((VH*)sp) = (VH)return_point; *--sp = (VW)(tcb->tinib->task); tcb->tskctxb.pc = activate_r; /* cpu_support.a30 */ tcb->tskctxb.sp = sp; } これは、lvalue のキャストができないということでエラーになります。 たぶんコンパイラがGCC4.0と同様の [代入文(lvalues)の左辺に置ける項目の制限] によるものかと思います。 #TOPPERSの公開しているコンパイラバージョン(現在入手できない) #では問題なかったかと思います。 これはたぶんメンテナンスされれば、左辺キャストは除かれていくかと 思います。往々にしてそれなりの時代を越したソースはメンテナンスされていきます。その過程であるソースが多くあるのが実情でしょう。 ですので、今あるオープンソースが模範的かというとそうでない というのが私の見解です。 質問者の言う 古文といえばそれにあたると思います。
- sakusaker7
- ベストアンサー率62% (800/1280)
> 最近ですが Ruby の作者さんのインタビューを読んでからです。 > C++は嫌い、と言ってました。また、個性的な方なのでソースのCは他の部分でもANSI(C89)ではない古い方式なのでは(google 頼みの結果です。間違っているかも)。 まつもとさんは確かにC++は好きではないです(実際に話したことありますから)。 また、ANSIの関数定義のスタイルが気に入らないということで K&Rスタイルを使いつづけていましたが、そのことによって 発生したバグが絶えないことで、Rubyの開発に携わるメンバーから圧力を受けて 現在では修正ミスがなければ、基本的にすべて ANSIスタイルを使っています。 ruby-trunk-20071108>grep -i ansi changelog modification trans -> transitive. [ruby-dev:32040] * util.c: updated for ANSI C only. applied a patch from * regparse.c, etc.: K&R to ANSI code cleanup patch from Stefan * thread.c (rb_thread_run): fix to ANSI style. * eval.c: fixed to use ANSI function style. * inits.c: fix to ANSI prototype style and reorder Init_*(). * ext/socket/socket.c: ANSIfied. [ruby-core:08601] * math.c (domain_check): ANSI style function arguments splat expansion. * missing.h (isinf): avoid macro expansion * configure.in: define IA64 for portability. (HP aC++/ANSI C doesn't ANSI compatible interface. * util.c: almostly ANSI styled. (except for functions depending on ANSI compatible strtol and strtoul, and ANSI styled other functions. * ruby.h: ANSI styled. * missing.h, missing/strchr.c, missing/strstr.c: ANSI styled. * util.h (qsort): removed the definition incompatible to ANSI. * parse.y: changed to ANSI function style. * win32/win32.c (cmdglob): enable brace expansion. * array.c: moved to ANSI function style from K&R function style. * missing/vsnprintf.c: ANSI compiler supports const keyword. declaration. (I recommend ANSI-style function) * io.c (argf_forward): use ANSI style. * instruby.rb: use path name expansion of cmd.exe. lists using BS and ANSI modes. ANSI macro instead of hard coded value. あなたがC++を使わないで済ませるのもあなたの自由ですから そのことには何もいいません。 ただそれを拡大解釈して参考書だの試験問題をなおせというのは止めて欲しいです。 > また、Ruby(勉強しようとは思うのですが最初の例題をコンパイルした程度)の特徴は、 > 型がないと聞いています。キャストで型変換とは逆方向の言語なのでは、と思うのは素人の浅はかさでしょうか。 なんでRubyの言語仕様の話がここで出てくるんですか? 使う道具が違えばプログラミングのスタイルだって変わります。 #あとRubyに「型がない」っては間違い。 #「型宣言がない」「静的な型チェックをしない」という意味ならそうですが > また、かなり前から作り続けられてきたプログラムの古い部分を読めることは大事だとは思うのですが、 > 「古文」が先か「現代文」が先かの話のように思えます。 > 「基本情報の問題文に古文を出されても」というのが率直な感想です。 古文というと今は(実用にはほぼ)使われないというイメージなのですが、 だとしたら、それは違うでしょう。 今も生み出されつづけているコードでも使われているんですから。 確かに「必要ない」ことでそうしないスタイルもあるでしょうし それを採用しているプロダクトもあるかもしれません。 再三書いているように、どちらかが明白に正しい という命題ではないのですから、あなた個人の心情を拡大解釈して 他人に押し付けないでください。
お礼
休憩時間なのでなんとかお返事します。 「他人に押し付けてはいません」 他にも書いたように、情報処理技術者試験での問題作成者側に疑問をもち初めてはいます。ですから、「C++との互換性のためにこの問題文ではキャストを用いる」とどうして、堂々と出題文の注意等に書いてくれないのかが疑問です。また調べが途中ですが、少なくとも米国でのFAQ等において、例文として「キャストあり」はほとんど用いられていないように思えます。だからこそ、試験問題作成側は「今の日本は米国とは違う」と書けばいいのにと思い始めています。ですから、質問の答えとして、実はJIS(情報処理技術者試験の範囲はJISの番号しか書かれていない。wikipediaがなければ何のことかもわかりませんでした)とANSIではこの部分が異なる、といった答えを頂くことさえ思い描いていました。どうか勘違いしないで欲しいのは、「試験問題文以外の場所でキャストを使うべきでない」とは言っていません。まさに、あなたのスタイルを変えろとは一言も言っていないはずです。だからこその質問です。主張ではありません。技術者試験の問題文に注意が数行加わることが、あなたにどう影響するのでしょうか?ひょっとして出題に関わっておられるのでしょうか?
- crew21
- ベストアンサー率26% (58/222)
ちょっと回答じゃなくなっちゃうけど、補足。 俺も始めはTacosanさん派だった。 けど、たとえば char *a = malloc(3); とかならその場で扱い方がわかるけど、長いソースの中でいきなり a = mallco(3) とかだと、その a が何型だかわからんから、途中からキャストを入れるようになったんだ。 まあ、ソースを読む人(他人)も安心してというか、確実に扱う型をその場で理解できるしね。
お礼
回答ありがとうございます。私は、最初キャストをつけなければエラーが出るものとばかり思ってました。けれど、いくつかのサイトやwikipedia, C の FAQ とかの例にキャストがなかったんです。そこでびっくりしてしまいました。 情報処理技術者試験の問題文でありC89限定ということ別に考えると、どうなんでしょう。読みやすいプログラム(キャストあり?)と書き換えやすいプログラム(キャストなし?)、両立できれば良いのでしょうがそうもいかないのでしょうね。読みやすいと感じるのと美しいと感じるのは多分そんなに違わないので、まさに現場では、人それぞれ、場それぞれ、なんでしょうね。
- sakusaker7
- ベストアンサー率62% (800/1280)
基本的にこれは Tacosan さんの書かれている通りその場の取り決めの問題であって どちらかが決定的に正しいということはないと考えます。 http://www.koders.com/ あたりでコード検索するとわかりますが、C++だから といって malloc は使わないわけじゃありません。 今わたしが使っているPCのハードディスクに展開されているソースコードをいくつ か調べてみました。 Brian W. Kernighan が公開している awk b.c: setvec = (int *) malloc(maxsetvec * sizeof(int)); lex.c: if (buf == 0 && (buf = (char *) malloc(bufsize)) == NULL) lib.c: if ( (record = (char *) malloc(n)) == NULL Python (2.5.1) Modules/_ctypes/stgdict.c:375: stgdict->ffi_type_pointer.elements = PyMem_Malloc(sizeof(ffi_type *) * (len + 1)); Modules/_ctypes/_ctypes.c:2201: obj->b_ptr = (char *)PyMem_Malloc(dict->size); Ruby はマクロでラッピングしていますがキャストつき (1.9.0) #define ALLOC_N(type,n) (type*)xmalloc2((n),sizeof(type)) #define ALLOC(type) (type*)xmalloc(sizeof(type)) Perl(5.9.5)。 handy.h:767:#define Newx(v,n,t) (v = (MEM_WRAP_CHECK_(n,t) MEM_LOG_ALLOC(n,t,(t*)safemalloc((MEM_SIZE)((n)*sizeof(t)))))) sv.c:1439: s = (char*)safemalloc(newlen); util.c:987: char *const newaddr = (char*)PerlMemShared_malloc(len + 1); 無論プロダクトによってはキャストしないことをルールにしているものもあるかも しれませんが、このような現実があります。ですから、試験問題を修正*しなければ ならない* という意見には反対します。が、実際に修正しますという話になったと してもそれはそれでいいんじゃないのというスタンスです。 あー字数オーバーになりそうだからこの辺で止め。
お礼
回答ありがとうございます。これについては勉強しても追いつかないと思いますので、一つだけ。私自身が C++ を勉強しなくても大丈夫、と思えるようになったのが、最近ですが Ruby の作者さんのインタビューを読んでからです。C++は嫌い、と言ってました。また、個性的な方なのでソースのCは他の部分でもANSI(C89)ではない古い方式なのでは(google 頼みの結果です。間違っているかも)。また、Ruby(勉強しようとは思うのですが最初の例題をコンパイルした程度)の特徴は、型がないと聞いています。キャストで型変換とは逆方向の言語なのでは、と思うのは素人の浅はかさでしょうか。また、かなり前から作り続けられてきたプログラムの古い部分を読めることは大事だとは思うのですが、「古文」が先か「現代文」が先かの話のように思えます。「基本情報の問題文に古文を出されても」というのが率直な感想です。
- Tacosan
- ベストアンサー率23% (3656/15482)
個人的にはキャストしない派. 通常 malloc の返り値はなんかの変数に代入するだろう (というか捨てる意味がわからん) し, その場合には変数の型を見れば「どの単位で扱っているか」がわかるから, キャストする*必要*はないと思う>#6. ま, この辺はその「場」の決めだと思うけど.
お礼
回答ありがとうございます。「場」の決め、は実際の現場においては本当にそうなんだろうと思います。C言語で閉じて考えると、確かにキャストなしの方が少なくとも論理的(美しいと感じる)と思えるようになってきました。
- crew21
- ベストアンサー率26% (58/222)
下の方々が詳しく書かれてるから既に理解してるかもしれんけど、 全部読む時間が無いので結果だけ書くが、メモリアロケート(malloc())してきた領域に対してキャストするのは普通だぞ。 ていうか当然。 だってそうしないと、アロケートしてきたのはいいけど、どういう単位(char,int,long,etc..)で扱っていいかわかんないでしょ。 だから malloc() は確か戻り値としては void * を返すんだよ。 で、プログラマに対して、どう扱うか(char,int,long,etc..)を指定してね、すなわちキャストしてねってことになるわけよ。 最後の方オネエ言葉になっちゃったけど、そんな感じよ。 まあそれと C89 との関連はわからんけど、現場のコードではそうするものだよ。 あと、話飛んじゃうけど、就職(転職)のための箔を付けしようとして勉強してるならアレだけど、 プログラミングとか情報処理全般のウデ上げようとしてその試験の勉強しても意味無いぞ。 つか無駄。
お礼
回答ありがとうございます。変なところにお礼を言う形になりまずが、「その試験の勉強しても意味無いぞ。 つか無駄。」は、全くその通りなのではと思い始めています。情報処理技術者試験の問題を出している方々はここで私が質問していること等は何にも考えていないのでは?と思えます。特に悪気はなくても、C++に詳しい方は日頃は malloc を使わないし、世代を考えると C89 よりも前からCを使っていると考えられるため、「CはC++の一部」と考えているのでは。海外の議論も最後には「良いプログラムとはCとC++の両方で動くプログラム」と主張する人に、「CとC++は別言語だと何回言ったらわかるんだ」という主張が始まって泥沼です。いっそ、基本情報もCではなく「CとC++の共通規格」としてくれるといいのに。
- R32C
- ベストアンサー率39% (115/290)
----------malloc.c----------------------------------------------------- 1 void * malloc(long sz) 2 { FFE00010 1B04 $malloc ENTER #4 FFE00012 0AFC MOV.L R2R0, -4H[FB] 3 return((void*)(0x77777777)); FFE00014 B28C77777777 MOV.L #77777777H, A0 FFE0001A EF EXITD 4 } --------test.c ------------------------------------------------------ 11 extern malloc(long sz); 12 13 14 void main(void) 15 { FFE0001C 1B04 _main ENTER #4 16 int *ip; 17 18 19 ip = (int*)malloc(sizeof(int)); FFE0001E FA80 MOV.L #4, R2R0 FFE00020 FBEFFFFF JSR.A $malloc FFE00010H FFE00024 0AFC MOV.L R2R0, -4H[FB] 20 21 22 } FFE00026 EF EXITD 23 以上がデメリットの例です。 あまりに間違いすぎかもしれませんが、プロトタイプ宣言の型の宣言抜けおよび キャストありにより、コンパイルが通り、見事に誤動作します。 (Wallオプションでも警告もでません) 一方キャストをはずすとエラーになり、ビルドできません。 極端な例かもしれませんが、キャストによってエラーがなくなり、気づくべきところが 気づかなくなるケースがありデメリットは多少ですがあると考えています。 (上記は、M16Cファミリの32bit版で実際にコンパイルしたもの(ASMまぜてます)です。C89ではないです。つっこみどころ満載かもしれませんが) 本題ですが、例題として int *p; p=(int *)malloc(sizeof(int)); は、私個人は、よろしくないし、(第一美しくないです)と思い、質問者の意見にどちらかというと賛同します。 問題としては、本来修正すべき内容と私は思います。 もっと考えるならそれが回答すべき問題なら何を正解にするかが変わってきます。 例) 問題、pにint長のメモリを確保する処理を__を埋めて完成しなさい。 int *p; p=_________(sizeof(int)); で (int *)malloc と malloc をどちらも正解にするかどうかです。 普通に考えるなら、後者のみ正解だと思います。
お礼
回答ありがとうございます。勉強がとても追いつかないと思い、この時点でお礼をさせていただきます。この例は、#2で話題に上っている、CのFAQ7.7での例と受け取りました。キャストしない場合は問題がなく、キャストした場合にはこのような困難があると考えると、問題文としてキャストありは良くないと私も思います。また、解答例でもキャストありを不正解にすべきと言っておられることに、最初驚きました。しかし、情報処理技術者試験を将来医療機器や原子力発電所に関わる人が受ける可能性も考えると、少しでも困難があると思える方は排除すべき、とも思い始めています。特にキャストがあるとプログラムの改変でバグが混入しやすいとした場合、1%の困難の可能性であっても避けるべきですよね。キャストありとされる方が医療機器等の絶対にバグを入れてはいけない部署で働くことになるのは確かに嫌です。数十年後にプログラムを作った人とは別の人が改変するかもしれませんし。もちろん、ほとんどの場合、キャストがあってもなくても問題ない職場なのでしょうが。 C言語がアセンブラと密接な関係にあるとはうすうすですがわかります。ですから、「アセンブラとの関係でキャストはつけるべき」と言われていたら、あっさり納得したと思います。しかし、現実は逆だったんですね。勉強になりました。
- sakusaker7
- ベストアンサー率62% (800/1280)
>jactaさんの方でも補足しましたが「私も含む初心者が混乱しないでしょうか?」は情報処理技術者試験の出題側に対してです。 わかってますよ。 あなたがその論を補強するのにWikipediaやC言語FAQを 持ち出してきたので、それはあなたの論ずるところを 補強するものにはならないよといってるだけです。 ところで > ANSI規格ではキャストすべきでないとあり、 や > キャストがあると困ったことになると書かれています。 が、具体的にどこにどう書かれているかという わたしの疑問に答えていただけてませんがどうなんでしょうか? > どちらでもよいとのご指摘ですが、 > int a=10; > int b; > b=(int)a; > が問題文にあった場合(特に初心者は)奇異に感じませんか? 失礼ですが、これと、mallocの例が同じレベルのものだと思われてますか? はっきりいって例として持ち出すのに不適切です。 > 何がメリットなのか じゃあ、あなたが勘違いするという以外に なにか明確なデメリットがあるなら教えてください。 FAQ等にあるように、C++では必須であるし 過去そのようなキャストが必要であった 環境もあるという経緯を考えれば、明確な害がないのであれば 目くじら立てて取り除かなければならないものだとは思いません。
補足
もう少し勉強してからお返事した方が良いのでしょうが、ご質問の点だけお答えします。「キャストがあると困ったことになる」は、stdlib.hを忘れている際のことを指します。オプションなしで gcc でコンパイルした際、確かにキャストありだとなにも警告しません。「-Wall を付けるべきだろう」というご指摘がありそうですが、私だけかもしれませんが、初心者は Wall の存在すら知りません。 デメリットですが、必要のないキャストは間違いの元、という意図です。また、これは今回勉強してわかったのですが、プログラムを改変したい際に、型を変更するだびにキャストも変更しなければならない、ということです。また、C++でも必要という点に拘っておられる点に、最初驚きました。なぜなら、Wikipedia の malloc の項には C++ で malloc は禁じ手とあるからです。new を使うのでしょうか。そうだとすると、あまり良いとは言えないC++のプログラムとの互換性のために、キャストが必要となります。本当にそうなんでしょうか。どちらが多数派かは、この試験においては意味がないと考えています。なぜなら、情報処理技術者試験の試験問題にキャストがある限り、参考書等はそれに従うからです。結果として、どちらが多数派かは日本ではおのずと決まってしまいます。もし次回からキャストがなくなったら、急に参考書類はキャストをなくすと想像します。
- 1
- 2
お礼
回答ありがとうございます。 私の力不足のため議論がすすまず申し訳ありません。 最後に私なりに調べた結果をまとめました。