C言語

C

人気の記事:

コメント

  1. jinnee より:

    今小ネタで何故C言語は難しいと言われるのかというテーマで何か書いてます。

    主に自分用に。

    ネタ元はgcc 3.4のプリプロセッサなんですけど。すぐ忘れちゃうんですよね、

    cppの構文規則。

  2. とおる。 より:

    たしかに、cpp が C を難しくしている点もありますよね。gcc の cpp ってちょっと便利な機能がついてて、それに頼りがちになっちゃうし。

    gcc 用のコードが Code Warrior でもコンパイルできるようにするのに、苦労したような記憶がうっすらとあります。

    少し前に復刊された、コーニグの『Cプログラミングの落とし穴』を読んでみましたが、面白かったです。

    http://w3.shinkigensha.co.jp/books/4-7753-0255-8.html

  3. tateisu より:

    ・文字列データ型が提供されていない

    ・アドレスの線形性を意識する必要がある

    のが難しい理由だと思います。BASICにもJavaにもPerlにもこんな特徴はありません。

  4. jinnee より:

    Cは高度に抽象化されたアセンブラであるとも言えるわけですから。

    自由度が高い分、実装のメモリイメージを意識せざるを得ません。

    (いわゆる慣れの部分に入ると思います。言語仕様として特別難しいことをやっているわけではない)

    比較対象があるとしたら,,,cobol、pascal、PL/1 ? いや、違うなぁ…。

  5. 羽月 より:

    スコープとかなれないとわかりにくいです。

    typedef ってどこまで有効だっけ? とか。

    あと、ポインタ型が(foo *)var なのは違和感感じましたね。

    hoge* var とか (hoge*)var でいいやん、って。

    …最初のころは、scanfに渡す変数に &付け忘れて転んでたなぁ。

  6. だいはど より:

    私がC言語を習った時、いちばん難しかったのはやはりポインタですね。データ型へのポインタはまだしも、関数ポインタになるとかなり混乱してました。

    そういえばGCCってCファイルをコンパイルするときでもC++みたいに扱っちゃうんですよね。man ページ見ると “-ansi” フラッグを使っても完全なANSI仕様にはならない、と書いてあったような覚えがあります。

  7. chonan より:

    同じくポインタの理解が最初は難しいと思いますね。

    他の言語と比べるとポインタの特殊性が分かりますよね。

    ポインタに慣れると、参照テーブルの利用など、

    面白い事が次から次に思い浮かんで楽しいんですけど。

    8086ASMを覚え始めたくらいから、

    すんなりポインタを理解できたような気がします。

  8. だいはど より:

    私が勤めている会社の製品もC言語で書かれていますが、単純に switch ステートメントを使えばいいと思われるようなところにも関数ポインタ・テーブルが使ってあったりします。switch にしてくれるほうがデバッグがラクなんですがねぇ…(笑)。

  9. chonan より:

    >だいはどさん

    大変気持ち解りますw

    関数ポインタを使い始めた頃に楽しみを覚えて、

    switch文の個所に関数テーブルを使用した記憶ありましたけど。

    チーム開発の事や、コードの読み易さを考えると、

    ものによってはswitch文の方が最適なシーンはありますよね。

  10. shimarin より:

    最近のCPUだと、ループ中の分岐は下手に関数テーブルを使うよりifやswitchで書いた方が分岐予測に都合が良いので高速な場合もありますよ、と古い人に説明すると驚かれます。

  11. yasuo-s より:

    昔のCコードなんかみてると無理矢理アセンブラ的に書いてる場合もありますね。

    正直、理解しがたいので辞めてください。。。

  12. だいはど より:

    > shimarin さん

    なるほど,そうなのですか.確かに最近のコンパイラの最適化は非常に優れているらしいですね.for ループなどでも iteretaion が少ない場合は展開してしまうらしいです.一度どこかの雑誌で Intel C/C++ コンパイラと GCC のパフォーマンスの比較をやっていました.当時は Intel に軍配が上がっていましたが,今はどうでしょうね.

  13. jinnee より:

    最近のCPUのパイプライン制御と分岐予測は5、6年前にはちょっと考えられない

    位凄い仕事してますからね。とは言っても僕自身はなるべくswitch文は書かない

    様にしていますが。どうしてもソースが大きくなる傾向があるので。

    あと組み込み用の石では関数テーブル使った方がまだ有効な事も多いみたい

    ですね。やっぱり月並みですけど、使い方と目的次第で使い分けというのが

    良いんじゃないでしょうか。

  14. あつし より:

    Cで関数ポインタをばりばり使うくらいなら、いっそC++を使えば…と思うのは気のせいでしょうか? (^^;;

  15. だいはど より:

    私は実は C++ はよく知らないんですよ…。> あつしさん

    いちおうコードは不自由なく書けますが、C の関数ポインタの代わりに何を使えばよいかと言われると考えてしまいます。あと C++ は C に比べてどうしてもコードサイズが大きくなってしまうと思うのですが、それも腕次第なのでしょうか。

  16. あつし より:

    コードサイズは大きくなりますね。

    特にテンプレートをバリバリ使うとでかくなります。

    コードサイズとかC++コンパイラやC++標準ライブラリを使えないプラットフォームだとかそういう制約があるならともかく、気にしなくていいなら、もう C だけではコードがかけない体になってるかも。> 私

    いかん。C言語について語ってないような気がする。_o_

  17. Matthew より:

    関数テーブルが巨大だと線形なテーブルでは遅いので、

    関数バイナリツリーを用意したことがありました…。

    巨大といってもたいしたことなかったので、結局つかいませんでしたが(^^;

    berkleyDBを使うという手もありますね。

  18. jinnee より:

    僕もそれを考えてました>Matthewさん。

    C++を使うか、Cを使うかと言うのは開発環境に依存する話なので、おそらく

    PC系のプログラムを組む場合には相当なネックになるだろうと思います。

    #Cとアセンブラでやらざるを得ないとか

    個人的にはC++の方がオブジェクトのサイズが大きくなるような気がするんですが

    処理系依存なんでしょうか。

  19. jinnee より:

    間違った。

    PC系以外の、でした

  20. あつし より:

    > #Cとアセンブラでやらざるを得ないとか

    そういう環境だと大変ですね。

    > 個人的にはC++の方がオブジェクトのサイズが大きくなるような気がするんですが

    とは思いますね。

    真剣に比べてみたことはありませんが。

    いずれにしても、開発環境に制約がなければわざわざC++を避ける理由はないような気がします。

    (誰もそんなこと言ってないわけですが…。(^^;;)

  21. Matthew より:

    いまでは、組み込みでもc++つかいますしねぇ…。

  22. だいはど より:

    もう五年前になりますが、ドイツ系の某社との契約で Windows CE Handheld 用のアプリケーションを書いたことがあります。組込み系とは言いがたいですが、当時 C++ のコードサイズなどについて無知だった私は MFC を使うという愚挙を犯してしまいました。おかげで完成したアプリケーション+ DB のサイズが大きくなってしまい、CFカードを追加せねばなりませんでした…(汗)。

  23. jinnee より:

    確かに組み込み分野でもC++が流行っているようですが…。比較的大きいシステムに

    多い気がします。小さいものはまだCかなぁ。

  24. だいはど より:

    私もそう思います。GPS デバイスやらネットワーク・スイッチなどではまだ C が主流ではないでしょうか。携帯電話などでは Java を使うところも多いようですが…。

  25. jinnee より:

    携帯電話の「iアプリに」javaを使うことはありますが、携帯電話そのものは

    やっぱりCですね。通信系もアプリケーション系も。

    まぁもっともiアプリを開発してる知人に言わせると「あんなもん、Cと一緒ですよ」

    とのことですが。フレームワーク作ったり、OOPのコードにする事が難しい様です、

    サイズ的に。

  26. あつし より:

    > まぁもっともiアプリを開発してる知人に言わせると「あんなもん、Cと一緒ですよ」

    とのことですが。

    > フレームワーク作ったり、OOPのコードにする事が難しい様です、 サイズ的に。

    そうですね。

    iアプリ開発ではできるだけクラス数を減らさないとサイズ的にとても厳しいです。

    私は再利用可能なコードを書くのに、ppp.exe というプリプロセッサを使っています。

    Cでマクロを使っているようなもので、とてもJavaを使っての開発とは思えません。

  27. jinnee より:

    >> #Cとアセンブラでやらざるを得ないとか

    >そういう環境だと大変ですね。

    まぁそういう環境でもC++とは別のマクロ的な面白さとはひと味違う

    ミクロ的な面白さを味わえる訳ですが。

    #でも最近はアセンブラを理解しようとする人が少なくなったのは残念ではあるな

  28. あつし より:

    > ミクロ的な面白さを味わえる訳ですが。

    これ、わかる気がします。

    > #でも最近はアセンブラを理解しようとする人が少なくなったのは残念ではあるな

    確かに。うちの会社でも若い人は誰もアセンブラ使えないかも。

  29. だいはど より:

    >ミクロ的な面白さ

    なるほどっ、そういう面白さなんですね。

    何度かアセンブラやろうかと思ったんですが、難しくて挫折

    どうやってC、C++と使い分けるかが良く判らないのですが、

    計算重くなりそうな所で使うのが良いんでしょうか?

    C++とかと一緒に使いたいと思ってます。

    _asm{

    }

    こんな感じで、VC++でコンパイルできましたよね。

  30. だいはど より:

    > jinnee さん

    確かにそうですね.私もいちおう x86 のアセンブラは理解できますが(書けるかどうかは別),最近の人はもうアセンブラを習わない人も多いんでしょうね.ただOS付属のDLL内で Seg Fault など起こしてくれる場合はどうしてもアセンブラが理解できないとデバッグできないんで,たま〜に役立ったりします(笑).

    # ほんとにここはC言語のスレッドなのだろうか….

  31. shimarin より:

    >職人芸さん

    C/C++ソースの中にインラインでアセンブリコードを入れると最適化の邪魔になるため速くならないか却って遅くなる可能性が高いと思いますので、処理を速くする目的でやるのはあんまりお勧めできないです。

    (ドライバを作るとかバイナリコードを数バイトでも小さくするとか好奇心を満たすとかの目的でやるなら良いと思います)

  32. jinnee より:

    >shimarinさん

    おっ、そういうもんなんですか。

    ならば、デバック出来る程度で辞めておきます。

    マイOSを作る時にでもガンバリます。

  33. jinnee より:

    僕は逆にintel系の石は駄目です>だいはどさん

    セグメントの使い方が良く判らなかった….。

    わかるのはMC68k、MIPS R4000、H8位デスカねぇ…。ARMとSH、AVRは

    そのうち覚えたいと思ってますが。

    #まぁ業務で使わない限り覚えないだろうな

  34. だいはど より:

    > jinnee さん

    おおお〜、幅広い知識をお持ちですね。私も 68k のアセンブラは少し勉強したことがありますが、すっかり忘れてしまいました。確かに x86系より分かりやすかったような…。

  35. Matthew より:

    ARMは…ゲームボーイで遊ぶのがいいかと(w

    またはArmadilloで遊ぶというのもいいですね。

    東京ビッグサイトでARM9乗っけたArmadilloが展示されているようですが。

  36. jinnee より:

    そういや、DoCoMo 900iはARM10みたいですね。900Liはアプリケーションパートの

    OSはlinuxだとか…。

    linuxハッカーがアプリケーションパートを書き換えてくれることを切に望む。

  37. khurata より:

     もともと COBOLが身体に染みついてから Cを始めたせいで、今でも「もっさりした」コードになってしまうのが私の弱点です。他人様が書いたコードは、エディタでいちいち何行にも分解しないと読めません(涙)。

     が、もはや Cがメインの使用言語になってしまいました。アセンブリ言語、もとい機械語の知識がある人にとって、Cは強力な開発ツールだと考えてます。

     逆に、言語より下のレベル(=より機械に近い)の知識が無い人にとっては、ポインタとか配列とか、オブジェクトの抽象化が他の言語より進んでない面で、戸惑う事もあると思います。

     Cについて語る時は、やはりどうしても機械語の話は避けて通れない、というのが私の持論です。ちなみに当方、Z80、SPARCプロセッサ、IBM System/370、R8000、NTT D60系のアセンブリ言語を経験致しました。全部古いですね・・・。

  38. だいはど より:

    > khurata

    SPARC のアセンブリ言語とはすごいですね。私は 8086 系および 68000 系しか経験がありません。しかも C を先に勉強したため、アセンブリをやりながら、「ああ、こういうことだったのか」と C に対する理解を深める始末でした (笑)。メモリへの直接のアクセスなど、アセンブリを先にやるほうが確かに理解しやすそうですね。

  39. khurata より:

    >だいはどさん

     C言語が先でも、アセンブリ言語が先でも、相互に理解が深まったなら、素晴らしいと思います。そこまで進められる人は、あまり多くないと思います。

     アセンブリ言語は難しい、という先入観が広まってしまってますが、私にとってみれば、これが最も簡単です。C とか C++ とか Java とか PL/I とかは、言語毎に約束事や用語の違いがあって大変です。アセンブリ言語はそういうわずらわしさはありませんので・・・(笑)。

    > SPARC のアセンブリ言語とはすごいですね。

     以前、業務でコンピュータをいじっていた時は、見たことも聞いたこともないマシンを見せられ、いきなりその場で機械語のパッチを作らされたりする事がありました(苦笑)。目の前にある現物が全てで、マニュアルがどこにあるかも分からず、デバッガのコマンドからして手探り。

     我ながらよく作れたもんだと思いますが、それもいろんな CPUのアセンブリ言語・機械語を知っていたから出来た芸当だと思います。

     さて、C言語と機械語を連係して学ぶ上で、1つだけ、誤解してはならないと思う事があります。

     それは、Cで扱うポインタやメモリ空間などのオブジェクトは、やはり「C言語の世界で抽象化されたもの」だと言う事です。ずばっと言ってしまえば、ポインタ「イコール」メモリアドレスではない、という事です。

     ここを誤解している方は大変に多く、私にとっては残念な事でもあります。

     ポインタや文字列の話をする時に、メモリの箱の絵を描いて・・・という説明をよく見かけます。これはこれで分かりやすいですし、「説明としては」間違っていないでしょう。

     しかし、その「箱の絵」は、「C言語における箱」に過ぎず、実際のメモリであるとは限りません。

     簡単な例としては Windowsの仮想メモリがあります。1つのプロセスに 4GBのメモリ空間が割り当てられ、そのどこに対してもポインタでアクセス出来るわけですが、そのポインタは、メモリの中を指しているのか、HDの中を指しているのか?

     どちらでもありません。4GBという「仮想」空間の中を指しているだけです。

     この仮想空間は処理系により作り出された「幻」であって、実際に物理メモリの「どこ」を扱うのかは、処理系により隠蔽されているわけです。

     こういう事を分かった上で、アセンブリ言語と Cを学ぶと、また違う視点が持てるはずだと思います。

     え?・・・ここにいらっしゃる方々には「釈迦に説法」、でしたか・・・? す、すいませんでした〜(汗)

  40. よーたん より:

    少なくとも「ローカル変数や関数の引数はスタックに積まれる」こと、

    「malloc(new)で確保されたメモリはヒープに確保される」こと、

    「static変数はメモリに静的に割り当てられる」こと辺りを

    アセンブラのレベルで(大まかでもいいから)理解出来ないと

    C/C++でプログラムをやっていく上で行き詰るでしょうね。

    もっとも、並列処理とかキャッシュ処理とかやっているだろう

    最近のCPU向けのアセンブラを、手でゴリゴリ書けるように

    なる必要はあんまり感じないや…。

    >khurataさん

    昔の8bitCPUでは仮想メモリ空間なんて概念がなかった(?)ので、

    その分取っ付きがよかったんですけどね。 (^^;

  41. khurata より:

    学校で必死にがんばっています(ノ∀`*)ペチッ

    只今IF文勉強ちぅです+。:.゜ヽ(*´∀`)ノ゜.:。+゜

  42. khurata より:

     私も学生時代、8ビット CPUのマシンで IF文がさっぱり理解出来ず立ち往生していた頃がありました。で、ある日突然理解したんですよ。なんで理解出来たか、今でも分かりません。急に壁が消滅した、みたいな感じでした。そこから先は割とスイスイでした。

     おっと、C言語の話じゃなくなってしまいました・・・(汗)。

  43. 仕事で外注業者のつくったC言語のプログラムを検証するんですが、

    変数を何に使ってるかとかを読解するのにすごく手間取ります。

    他人の書いたソースを見るときのコツってありませんか?

    私はベタですが、ソースをエクセルとかにコピペして、対訳本

    みたいに日本語で「このiでループ回数をカウント」などと

    解説を書くという方法をとっています。効率悪いですが。

  44. jinnee より:

    これ使ってます。

    http://www.gnu.org/software/global/

    ご要望に添えるツールじゃないかもしれませんが。

  45. だいはど より:

    > jinnee さん

    もともとの質問者ではないんですが,これはすごく使えそうなツールですね。さっそく検証してみることにします。(関係ありませんがプロジェクト管理者が日本の方なんですね。)

  46. khurata より:

    >yoh-yohさん

     そうですね、8bit時代ならその通りでした。私は最初から「ポインタ型は、C言語の世界で抽象化された『ポインタクラス』である」という考え方で教わったので、「8bitの処理系ではそのような実装になっている」という感覚です。

    >うさみみバンディーさん

     プログラマの意図をコードから再現するのは、本当に難しいと思います。特に Cはトリッキーなコードも少なくないので、余計に難しいと思います。

     私はうさみみバンディーさんと似た方法しか思いつきません。

     ちなみに私が書くコードは、注釈がベッタリ入っているので、誰でもたやすく読解出来ると思います。なにしろ注釈がコードより多いんじゃないか?(笑)というくらいクドクドと入ってます。

     こうしないと、後から自分が見ても分からなくなっちゃうんですよ(汗)。でも、おかげで何年前のコードでもサクッと改修出来ます。

  47. jinnee より:

    あ、ほんとだ。全然気が付かなかった。

    http://tamacom.com/index-j.html

    ここですね。へー面白そうな会社だなぁ。入れてくれないかなぁ

  48. 寛生 より:

    Source Navigator http://sourceforge.net/projects/sourcenav/というのも良いかもしれません。Visual Studio 的に使えます。

  49. さのっち より:

    はじめまして。

    今学期、学校でC++とアセンブリ(68000Family? まだよくわかりません)を取ってます。Javaから始めたので、C++のポインターが未だに理解できません・・・。メモリーリークに悩まされる日々です(泣;)

  50. >さのっちさん

    メモリリーク対策にはBoehm GCを使ってJavaみたいにGCさせてしまう

    という手もありますね。

    それにしても、卒論のときに自分もメモリリークに泣かされたな。

    定期的に同じ大きさ分ずつ使用メモリが増えていったので

    原因追及は容易だったけど。

  51. shelarcy より:

    低レベルのコードを書かないなら、C++ では STL を主に使って C ベースの API でどうしてもメモリとして確保しておかなければいけないものは smart pointer にするという方法でいった方がいいような。

    あと、リソースの確保開放が気になる場所では、愚かなミステイク (http://mixi.jp/view_bbs.pl?id=52698) で Caz さんの書いている scoped lock パターン。(これをメモリの確保と開放に利用したのが smart pointer なんですけど……)

    class StCriticalSection {

    public:

      StCriticalSection() { EnterCriticalSection(); }

      ~StCriticalSection() { LeaveCriticalSection(); }

    };

    short func() {

      StCriticalSection section;

      if (…) {

        return …; // デストラクタが呼ばれる

      }

      // デストラクタが呼ばれる

    }

    if (…) {

        StCriticalSection section;

        …

      }

    学校では Accelerated C++ を教科書に使ってないんですか? C++ のコードは STL 登場以後の C++ らしく記述すれば C での悩みをほとんど回避することができます。

  52. 麦角 より:

    modern c++ programming ではメモリリークの心配はほとんど要りませんが、教育現場では、real programmer を育てるのか、programming tool user を育てるのかの都合もあって、STL をギュンギュン使う訳にもいかないかも。

  53. saito より:

    C のコードもまだまだ現役なんで、

    がんばりましょう〜 >さのっち さん

    みんな、そこを乗り越えて来た訳で、

    セレモニーみたいなもんですよ (^_^;;;

    みーんな悩んで大きくなったのだ 😀

    頑張って下さい〜。

    ポインタが分からないと、多分、メモリリークも

    退治できないような気がするので、

    まずは、ポインタの理解を深める事をオススメするかな〜。

  54. shelarcy より:

    real programmer を育てるとなると、なおさら言語特有の部分に浸ってその考え方を身につけていくというプログラミング経験があったほうがより切れ味の良いコードが書けるような。

    たとえ行きつく先が C プログラマーであろうと、ruby の考え方や Lisp(Scheme) および Haskell での考え方が身についているにこしたことはないように、言語特有の特徴をとらえることは非常に重要なことだと思います。

    そういう意味では C のポインタやインラインアセンブラも無視できませんね。

    きっちり身につけたつもりなんですが、ある問題に対処できるスキルが身についていないのでその部分は頑張らないと。

  55. jinnee より:

    学校で「C++のメモリ管理を教える」て実はとても重要な事なんじゃ

    ないかと思います。STLはまだまだ開発環境やフレームワークに依存

    しますから。(話は変わりますが、J2MEを使ったスモールシステムは

    ガベージコレクタがVMに実装されていない場合がありますのでApp

    側でメモリ管理をしなければならない場合もありますね)

    Scheme/LISPは覚えたいと思ってる言語なんですが、どうも異質な

    感じをうけますね。自分の発送を転換しなければ…と思います。

  56. よーたん より:

    アホな現場じゃ「STLはパフォーマンスが信頼できないから

    (というのは建前で他の人間が分からないから)使わないで

    ください」とか言われかねません…(苦笑)。

    というか「STLが使えればポインタの勉強しなくていい」と

    「ポインタでゴリゴリ書ければSTL不要」、どっちも

    極論という気はしますね。じゃあこういうのはどうでしょう。

    「どっちもマスターすべし」

    …これが一番極論か。 (^^;

  57. jinnee より:

    いや、それが理想だと思いますけど。

  58. さのっち より:

    皆さん、いろいろと教えて頂きありがとうございます。何とかモノに出来るよう頑張ります!STLもポインターも両方マスター出来る日が来ます様に・・・

    >shelarcyさん

    『Accelerated C++』さっそくチェックしてみます!私は現在アメリカの大学に留学中ですが、普通の大学では使っているかもしれません。

  59. だいはど より:

    > さのっちさん

    私もアメリカの大学でコンピュータ・サイエンスを専攻しました。今はシアトルの会社で C/C++ を使ってコードを書いています。言葉の壁もあって大変だと思いますが、頑張ってくださいね!

  60. さのっち より:

    あ、あと、初心者にお勧めのC++の本があったら教えていただけますか?宜しくお願いします。

  61. さのっち より:

    >だいはどさん

    えー!!

    私もシアトルです。某大学の分校にいます。社会人中心の学校なので、クラスメートは学士を取る為だけのMSの人や既に業界で働いている人ばかりです!そんな人達がクラスメイトでは焦るばかりで・・・。

    とにかく、励ましありがとうございます。

    頑張りますね!

  62. shelarcy より:

    「Accelerated C++」は初心者にダメな本ではないんですけどね。初心者に手早く C++ の真髄を知らせるために書かれた本ですし。実際、STL を使わせないというような悪癖のない企業では、新人研修用に使っていたりします。(STL の機能が本当にぶれていて苦労していたのは VC6 の頃ですし)

    私的にはそこで C++ をマスターした後、C のスタイルでもコードを書けるように C の本を読むのがお勧め。その流れでいくと、すらりと「プログラミング言語 C」に入っていけるかも。

    「プログラミング言語 C++」はその後知識をまとめる用に。ここより先は初心者用の本じゃなくなるので色んな道があると思います。Unix で C プログラミングがやりたいというのであれば、「プログラミング言語 C++」より先にそっちの道に入るという手もありますし。

    Modern C++ Design の著者と Exceptional シリーズの著者による C++ Coding Standard の本が出るらしいですけど、どういう本になるか分からないので保留。

    あと、C の範囲でない C++ のそれ以降の話題については、こっちで話すよりも C++ 言語 (http://mixi.jp/view_bbs.pl?id=6984) の方で話した方がいいと思います。

    ……C++ で話題振られると、modern な style の側にどうしても肩入れしてしまう……

  63. れい より:

    はじめまして

    自分はずっとファーム屋だったのでCでしたね、C++はほとんど見なかったのでぶっちゃけよくわかりません(^^

    ファームウェアでのCはどちらかというと高級アセンブラ的な意味合いも多いですから、結局CだけじゃだめでOSとかCPUの話になってくるんですよね、68000のバウンダリに何度苦労したことか・・・。

    ソースはなるべく簡単に書くように心がけています。コメントがなくてもわかるくらいに、が目標です(コメントもちゃんと書きますよ!)

    あと、どんな感じにコンパイルされるかをあるていど予想しながら書きましたね、これはこうなるはずだから問題ないはずとか。簡単なところだけですけどね。

    機械に入るものって24時間休みなく動かなくちゃいけないのが多いですし、ROM焼付けも多いですからバグは許されません。

    なので最近よくある携帯でのバグなんかはちょっと同情しちゃいますね。あれだけ複雑になって、しかも開発期間は短くなって・・・。見えます、徹夜続きのプログラマーが・・・。

    てなわけで、そういう分野ではCもまだまだ現役ですよ(笑)

  64. saito より:

    配置構文とかがポピュラーになれば

    普及するのかな???組み込み分野での C++ 利用。

    C++ で組み込み〜ってなんかダメそう…と思って

    その理由を考えてみたのですが、独自のメモリ管理

    領域にオブジェクトをアサインする手法が

    ポピュラーでないから、かな、と。

    これぐらいしか思いつかなかったのですが、

    なんか他に理由ってありますかね〜???

  65. れい より:

    C++での組み込みですか、自分がC++には詳しくないので何とも言えない部分があるのですが、どんなメモリ展開になるかがわからないと難しいですよね。関数はちゃんとメモリ配置決定しますし、構造体もそうなので、低レベルで直感的とも言えますが、C++のクラスって宣言した場合どんな配置になるんでしょうか・・・。

    組み込み系で動作中に落ちた場合、CPUのレジスタ状態とメモリダンプから原因探るなんて事も多いので、コンパイルで出てきたマップ使ってアドレス覗いたときになにがあるかわからないと困りますね。

    組み込みでも比較的大きいシステムは関係ないんですけどね、電話交換機とかはC++ですし、最近はJavaもあります。ルータもUnixベースだったりするので問題なく使えます。

    ただもっと小さい物になると、最近は少なくなりましたが標準関数すら使えない環境って存在しますし、メモリがほんとに限られてるシステムでのC++の利用はどうなんでしょうか。

    でも一番の原因はベテランの技術者がCしかしらないってのが大きいかも(笑)。アセンブラから来た人たちですからねぇ・・。

  66. saito より:

    インスタンスのメモリ配置って実装依存だったと思う。

    多重継承しかり、VTBL の位置しかり。

    確かに直感的じゃないですよね、C++ って。

    高級アセンブラとしての C 言語の思想を受け継いだ

    モダンな言語って、なんか無いのかな…。

  67. khurata より:

     某 DxXxXxの FXXX用交換機の交換ソフトウェアは、C++の処理系で開発されてましたが、中身はほぼ Cでした。私が経験したのは2〜3年前の話なので、今はどうなのか分かりませんが・・・。

     なぜ Cだったか、理由もよく分かりませんが、たぶん C++慣れしていない開発者が多かったから、じゃないかと思います。

  68. rep より:

    ★khurataさん

    私もその会社のサーバでやっていたことがありますよ。

    ってことで反応。

    あそこはあるアプリケーションでしか利用しない関数を共通ライブラリに入れていたり、

    char hoge[][40] = {

    “A001”, “NAMEA001”,

    “A002”, “NAMEA002”,

    “B001”, “NAMEB001”,

    };

    というようなコードを書きたがる人が多かった(-_-;)

    # BASICかよっ! なんて叫びそうになりました。

    あげく、break文を書かずに継続条件が終了するような

    値を即値で代入してループを抜けてたり。

    思い出しただけで凹んでしまいそう(;_;)

  69. khurata より:

    >あげく、break文を書かずに継続条件が終了するような

    >値を即値で代入してループを抜けてたり。

     これはこっちのスレ向きかも(苦笑)。

    http://mixi.jp/view_bbs.pl?id=338354

     条件満了によるループ脱出は、GOTOおよび類するものを全く認めない、ガチガチの SP信者が書いたのではないかと思われます。

     私の理解では、SPは GOTOを使わない事、ではなく、一定の制御構造のみでコードを組み立てる思想である、と捉えているので(だからアセンブリ言語レベルでも SPは可能だと思う)、必要ならば breakを使う事はいとわないです。

     まぁ、私もあまり自分では break使いません(苦笑)。私は breakが必要な条件があるならば、ループ条件に最初からそれを組み込みます。break使う方が見た目スッキリする事が多いと分かってはいるのですが(汗)。

  70. saito より:

    >あげく、break文を書かずに継続条件が終了するような

    >値を即値で代入してループを抜けてたり。

    BASIC の種類によっては、ループから抜ける命令を持たない

    ものもあるので、そういう BASIC では良く使うテクニック

    だったりします。

    # FOR-NEXT の途中で GOTO で抜けちゃうと、

    # スタックオーバーフローになりがちなので…。

    というわけで、そのコードを書いた人は、

    BASIC な人だったのでは 😀

  71. rep より:

    いやぁ、それがC++暦6年の方で、SP信者と言う訳でもない感じでしたね。

    構造体を利用しなかった方はまた別の方ですけど(^-^;)

    > これはこっちのスレ向きかも(苦笑)。

    ですね。実は迷っていたのですが、例の会社の名前が挙がったのでこちらになっちゃいました。

  72. khurata より:

     もしかしたら、break文が「どこまで」脱出するかをよく知らなかったがために、昔ひどい目にあった人なのかも・・・。

     私も初心者の頃、forとか while、switch、ifなどのネスト中で break使ってハマったような、おぼろげな記憶があります。だから私は(トラウマになってて)break使わないのかも知れません(汗)。

     思ったところに間違いなく脱出させるには、breakよりも終了条件を満たす方が確実と言えなくもないですが、それにしてもねぇ・・・(苦笑)。

  73. saito より:

    多重ブロックからの抜け出しに関しては、

    Java の 「break ラベル」を見たとき、

    良いアイデアだな〜と感心しました。

    そんなに多用するわけじゃないけど、

    たまーに使う事があるので>多重ブロックからの抜け出し

  74. khurata より:

    > 73 saitoさん

     Cなら、そういう時には gotoという方法もあるわけですが・・・(大汗)。皆さんは多重ブロックからの脱出は、どうされているんでしょう?

     私は多重ブロックであってもいちいち脱出条件を whileとかで書いて breakは極力使わないのですが・・・場合によって見通しが悪くなる事は認めます(汗)。

  75. 山玉 より:

    私はbreakは使わない派です。

    1.どこまで抜けるかがいまいち・・・

    2.昔BASICでスタックオーバーフローした経験が・・・

    3.プログラムの流れがいまいち読みにくい(と思う)

    が原因です。

    switch文では使いますが、forやwhileでは

    最初から条件に組み込むか変数を用意して対応しています。

    このままでは駄目かなぁ・・・

  76. shelarcy より:

    なぜ、C言語にはgotoが必要なのか?

    http://d.hatena.ne.jp/tanakh/20041002#p1

    C に Scheme 的な call/cc ください。

  77. あり より:

    多重ループの奥底からどかっと抜ける必要って、実際の場面ではかなり稀なはずなんですが、確かにどーしようもないことがあって、そういうときは素直にgotoします。本当にそれが必要ならsetjump/longjumpだってありで、それを回避することを信念として無茶な条件やフラグ変数持ち歩くよりは可読性がよいかと。ただし、最初にも書いた通り、かなり稀なケースです。

    例外条件で抜けるなら単純にtry-catchでthrowして抜けるのが素直です、C++ですが。内部ではどーせ tryでsetjumpしてthrowでlongjumpしてるんですから。

    期待条件で抜けるなら、そういう状況になったという時点で設計を見直したほうが・・・

    ましてや終了条件をセットするなんて、いつの時代?

  78. saito より:

    私の場合は、多重ブロックからの抜け出しは goto ですね。

    Exception も良いけど、ちょっと大げさかな、

    多重ループからの抜け出しに使うのは。

    使うのは、ほんとに、たま〜に、って感じですね。

    そもそも、微妙な粒度の処理じゃないと、

    なかなかこういう状況にはならないので…。

    ある程度まとまった処理ならば、関数にしちゃえば

    どこでも return で中断できるし。

  79. rep より:

    私も多重ループ脱出はgotoですね。

    > ありさん

    私の携わったのは3年半くらい前です。

    コードはモロにC言語での記述でしたよ。

    ベテランのリーダーからしてUNIX-Cを組むのに

    Quick-Cの本を常備して望んでおりました。

    # 私はQuick-Cを良く知りませんが・・・(^-^;)

  80. khurata より:

    >77: ありさん

     「いつの時代」とか言う前に、そういうループを作る事自体あまり良くないと思ってしまいます(苦笑)。脱出条件が明確なら、ループの継続条件に最初から反映させておけばよい、と私は思ってしまうので。

     私は自分では forをあまり使わないので、こう言えるのかも知れません(ループは whileで書くクセがあります)。

    >79: replicornさん

     Quick-C・・・・確か MS-DOS用の Cコンパイラ/リンカだった記憶があります。私はその頃 Turbo Cを使っていたので あまり詳しくはないのですが・・・。

     その方、よほど MS-DOSでの開発に「馴染み」があったのではないでしょうか。

  81. こじょー より:

    初書き込みです。どうぞよろしくです。

    私は集団開発系の部署(組み込み系ソフト)に属していますが、

    やはり goto はローカルなコーディングルールで禁止されています。

    個人的には goto 文を使わないと抜けられないようなループは

    初めから作らないように工夫をします。

    (集団開発なので余計にナーバスになってしまうのですが…^^;)

    もっとも、goto も使い方を誤らなければ有効なものですので、

    例外処理などには便利に使えると思っています。

    が、ルールで禁止されているのが何とも悲しいところで…

    ここらへんは個人か集団かで感覚が異なるものなので、一概には

    言えないと思いますが、やはりソースの見通しを考えると goto は

    ちょっと・・・という気がします。

    ちなみに自分はループのさせ方によって for か while かを

    使い分けています。

    ・ある回数ループさせたい → for

    ・ある条件を満たすまでループさせたい → while

  82. khurata より:

     大抵、なんでもかんでも while です・・・ OTL

  83. だいはど より:

    私はカウンター変数を使う必要があるとき以外はほとんど while です。なのでこじょーさんと似ているかもしれません。条件脱出の際はなるべく break は使わず、条件の中に組み込むようにしています。その結果あまりに条件が複雑になるようなら話は別ですが…。

    それにしても皆さん十人十色の好みがあって興味深いですね。

  84. あるごぬ より:

    do { … } while(COND); を使うと、負けたような気がします(謎。

    while (1) { … if (COND) break; } なら無問題です(謎。

  85. saito より:

    あけましておめでとうございます>みなさま

    for は、初期化ー判定ーループ本体ー状態更新、という

    while ループのシンタックスシュガーなので、

    このパターンに収まるやつは、できるだけ、

    for ループで書いちゃうなぁ…。

    加えて、初期化と状態更新の部分が

    明確になるので、上記のパターンの場合、

    for の方が、分かり易い、ってのもありますけど。

    初期化を伴わないようなものや、初期化の部分と

    ループ終了判定の距離が遠い場合なんかは

    while で回しちゃいますね〜。

    というわけで、今年もよろしくお願いします 😀

  86. kiku より:

    すべてのwhile文はforでかけるので、

    極端なはなし、while文は不要である

    認識です。do while, while doも

    同じです。

  87. khurata より:

     私は C初心者の頃に for をよく間違えて書きました。

    (a)増分と条件を逆に書いたり

    (b)条件を逆条件に書いたり

     (a)は、単にセミコロンでしか区切っていないので、どっちがどっちなのか見た目で分からなかった(慣れるしかなかった)という事です。今はさすがに大丈夫ですけど(苦笑)。

     古い BASICだと、FOR 初期値 TO 終値 STEP 増分、というように予約語で明示してあるのですが、最初に Cの for 見た時は「?」でした。

     (b)は、for の条件が、「この条件が満たされている間は繰り返す」のか、「この条件になるまで繰り返す」のかが、憶えられなかった、って事です。たぶん今でも憶えてません。実績のあるコードをコピペして使うので問題はないのですが・・・。

     このせいで、間違ったループをいくつも書いてしまい、for 恐怖症になりました。OTL

     まぁ、2つとも、単に自分の記憶力が無いだけなんですが・・・。while は、while という意味から言っても「この条件が満たされている間は繰り返す」というのが感覚的に分かるので、間違いようが無いのです。

     それと、自分は若い頃に COBOL をたたき込まれていたため、PERFORM でループする感覚が根強くあり、break を使うという思考がなかなか出来ません(汗)。

     つまり、私が while 使うのは、・・・記憶力の無さと思考の古さから、という事になりますね・・・でも Cは好きです。

  88. rep より:

    あけましておめでとうございます。

    for、whileはなんとなくですが、語彙が違うのでニュアンスで使い分けてますね。

    doに関してはforとは継続条件式が前置になるか、後置になるかが違うので単純な置き換えは微妙かもしれませんね・・・

    > khurataさん

    年跨いでしまいました。

    Quick-CってMS-DOS用なんですね。

    でも思い入れがあったとしても仕事の場ではちょっと・・・なんて思ったり(^-^;)

  89. kurosuke より:

    こんにちわ。初めまして。私はJavaオンリーなプログラマですが、

    こないだ、ちょろっとビット演算をするソースを

    読む機会がありまして、正直全然解らなかったのです。

    Javaしか知らない最近の若者プログラマーなんかは

    私みたいな人が多いと思うのですが、C言語を

    日常使用しているみなさんにして見れば、

    できて当然だったりするんでしょうか?

    やっぱ、できなきゃまずいですよね。。

    ご意見お聞かせください。

    (ビット演算に限らず、低レベルな処理全般)

  90. だいはど より:

    ○replicorn さん

    Quick-C はウィンドウズ用もありました。大学で使っておりました。(^^)

    ○kurosuke さん

    一口に C 言語で組むといってもいろいろな用途があるので,必ずしもビット演算を含む低レベル処理がさくさくと書けなければならないということはないかなと思います。使いこなせれば選択肢が広がることは間違いありませんが。

  91. はじめまして。組み込み系Cプログラマです。

    昔出ていたC言語が256倍よくわかる本という本で詳しくスタイルについてこだわりが書かれていて参考になりましたよ。

    目的の処理に合わせて適切にforやwhileを選択して書き手の意図を読み手に伝えられると読みやすいコードになると思いませんか?

    とはいえ自分もかなりそのへん怪しいのでコーディングスタイルについてうんちくが載っている本って他にもあれば教えてもらえるとうれしいんですが、どうでしょう?

  92. khurata より:

    >85: saitoさん、86: kikuさん

     確かにおっしゃる通りなんですが、どうも forは苦手意識が・・・(苦笑)。知人に指摘されて気付きましたが、自分は continueも使わないヒトです。

    >89: kurosukeさん

     私は論理演算回路とか「紙上 CPU実験」とかの勉強から入った「古いプログラマ」なので、ビット演算や論理演算は「出来て当たり前」という感覚があります。

     Javaから入った方には、この辺りは厳しいでしょうけれども、最近はこういう「古い知識」はほとんど使う機会は無いですし、プログラミングは より抽象化する方向、というのが時流だと思います。ですので、その時その時に応じて必要な事を勉強して行けば、それで充分だと思います。

     む〜、Cとは関係ない話になってしまいました(汗)、すみません。

  93. kurosuke より:

    だいやん さま

    組み込み系ですか。何か楽しそうですね。

    どんなソースを書いているのか想像もつかないです。

    私は今C/C++で組み込み、制御系の分野に転職してみたい

    なんて考えていたりします。(今の知識では無謀かもしれませんが)

    khuruta

    そうなんですよね。実際必要ないんですよね。私の会社

    はJavaプログラマしかいませんが、おそらくビット演算が

    出来る人なんていないのではなかろうかという気がします。

    私の会社で必要なスキルはSQLとHTMLとJavaScript

    ですかね。最近飽き気味。

  94. kurosuke より:

    あ、すいません。

    khuruta さま

    でした。

  95. shelarcy より:

    (情報系の学科で学んだ人は別として) C/C++ プログラマの間でもビット演算なんかは知る人ぞ知る技術になりつつあるわけで、だからこそハッカーのたのしみ (http://mixi.jp/view_item.pl?id=56661) なんて本が出てきているんじゃないでしょうか?

  96. 横槍失礼

    プログラムとは関係ないけど、ネットーワーク系(特に設計関係)に携わる機会があるなら、マスクとかの関係でビット演算が必要になるかもしれませんね

    せっかく勉強したので、無駄だといわれるとちょっと悲しくなるので弁護をw

  97. kurosuke より:

    shelarcy さま

    おお。なんか面白そうな本ですね。

    というか難しそうな本ですね。

    日記を拝見させていただきました。

    なんか凄い知識がありそうですね。尊敬します。

    関数型言語は私も興味あります。といっても今

    やっているのはelispですが。

    仕事の合間に暇見つけては書いてたりします。

  98. だいはど より:

    今さらですが,ビット演算などの処理はメモリ消費量やコードサイズを抑えるという目的ではかなり有用ではないかと思います。だいやんさんは組み込み系をやってらっしゃるということですのでその辺お詳しいのではないかと思いますが,いかがでしょう?

    わが社の製品も80年代に小型フットプリントを売り物にしていた製品が元になっているだけあり,ビット演算は当たり前のように使われています。クライアント/サーバ系の製品でネットワーク交通量を減らす目的でも一つの変数になるべく多くの情報を詰め込むため,ビット演算を使うことが多いです。実際の演算処理や数値比較はマクロにしてしまっていることが殆どですが…。

  99. ビット演算、普通に使いますよ。

    レジスタの設定とかはこれがないとできませんからね。

    メモリ節約の関係でフラグとかをビットシフトしてorしてログにぎゅうぎゅう詰め込んだりするのに活用したりもします。

    最近は組み込みでもメモリが広大になってきているのでそれほどシビアではないですけどね。

    高速化のためにシフト回数を数えたりは普通のプログラムでは・・・やらないですか?

  100. フラン より:

    embeddedな要求があるとbit演算使いまくりですな。

    ただしマクロでインラインasm文展開しまくり。

    あとメモリ境界に気をつけないとTLBミスヒットで

    がくんとスピードが落ちるので(同一目的の為に

    書かれた二つのコードで2倍の速度差が生じる)。

  101. 横から失礼いたします。組み込み系してます。

    組み込み系では普通にビット演算が使われています。物によってはコードの大半がビットをいじっているというのも珍しくはありません。但し演算というほど複雑なものではなく、ある特定のビットが1か0かを判別したり、逆に特定のビットに1ないしは0を書き込むということをよくしています。

    慣れるとそんなに難しいものではありません。**hensuu とかに比べれば…。

  102. kurosuke より:

    おお。やっぱり分野によっては

    バリバリ使ってる方がいらっしゃいますね。

    何か楽しそうだ。

    イグゼ さま

    私も悲しくなります。せっかく勉強したいと

    思っているので。

    だいやん さま

    >高速化のためにシフト回数を数えたりは普通のプログラムでは・・・やらないですか?

    すいません。シフト回数を数えるの

    意味がすでにわかりません。無知です…

    そもそも速度を意識するプログラムを書いた事がありません。

    SQLが遅いからチューニングしようくらいしかないです。

    konoa さま

    もう私の想像の及ぶ世界ではないようです。

    意味不明です。

    はまだ さま

    **hensuuはポインタのポインタですか。

    意味は解ってるつもりでも、解読しろ

    って言われたらできなさそうだ。

    このビット演算ネタですけど、

    具体的なソース出して話するのはOKですかね?

    板違いかな?

  103. こんばんは。

    ビット演算は結構好きでよく使うのですが、ペアプログラミングしてる時にガリガリ使っていたところ、横で見てる係にお手上げされたことがあります。。。

    #そんなにわかりにくいロジック組んでるわけじゃないと思っていたのに…しくしく。

    最近は、ちょとライフゲームのルーチンを、ビットを詰め込んで論理演算の嵐でやってみたりとかやってます。

    ループ以外に条件分岐しなくてよいので、たぶんそれなりに速い、はず。

  104. BaB より:

    こんにちは。

    自分はテレビゲームのプログラマですが、やっぱりビット演算よく使いますね。

    複数の変数に対して正負の判定を行うときに

    intが32ビットの環境で

    int型のa,b,c,dがあるとして、

    if((a & b & c & d) & 0x80000000){

      // 全部負数だったら

    }

    if((a | b | c | d) & 0x80000000){

      // 一つでも負数だったら

    }

    なんてのをよくやります。

    自分の業界だとサインビットの活用はわりとおいしかったりします。

  105. よーたん より:

    RGBカラーの操作には今でもビット演算が必要ですよ。

    自前でビットマップファイル(.bmp)を作成する関数を

    組んだ時にこの辺はよく使いました。

    あと、ひとつのクラスオブジェクトにたくさんの

    ブール値を含めたい場合は

    #define BIT_REGISTERED (0x01)

    #define BIT_SHOWN = (0x02)

    #define BIT_READY = (0x04);

    としておいて、inlineでsetter&getterを定義するというのは

    まだ今でもポピュラーでしょうね(既出ならごめんなさい)。

  106. 齊藤 より:

    最近のPCではビット演算に分解したほうが遅い場合もあるので速度向上の意味でビット演算することはもはや時代遅れかもしれません。シフト演算子等では条件によっては結果が未定義の場合もあるので特に注意が必要です。(符号の有無やエンディアンの影響もあったりしますし。)

    リファレンス系の書籍を見ているとCやC++には結果が未定義のものが多くて驚くことが少なくありません。いずれにしてもマクロや関数に切り出しておくのが無難なのは間違いないでしょう。数値や操作に「名前をつける」というのはどんな場合でも重要です。妙な名前を付けてしまってかえってワケが分からないというのもありがちではありますが。 :-)

  107. だいはど より:

    ○齊藤さん

    そうですね,昔は演算の高速化のためにビット演算を使ったりしたものですが,最近ではコンパイラーも進んできているので,ヘタに自前で最適化しようとしないほうがよいのかもしれません。

    符号というのはサインビットのことですよね。私がビット演算(特にシフト演算)を使うときはほぼ間違いなく unsigned 変数を使います。BaB さんの例のように signed でないと意味がない場合もあると思いますが。(^^;;

  108. 齊藤 より:

    ちょっと前にJAVA使いはビット演算が苦手というような話題が出てますが、JAVAの場合はビット演算の結果がかなり厳密に規定されているので処理系による差はでません。Cよりはかえって安心してビット演算できると思います。