こっちは、C言語で行こう!

このエントリーをはてなブックマークに追加
819色即是空:02/06/16 21:15 ID:V/0VIkpp

グァ゛ー、関数へのポインタのキャストがワカンネー。(頭を抱えて絶叫)



・・・最近キャラが壊れてきた。

820色即是空:02/06/16 21:59 ID:V/0VIkpp

・・・(・∀・)キマシタ!


忘れないうちにここに書いておこう。

    int (*comp)(void *, void *) = NULL;

    comp = (int (*)(void *, void *))strcmp;


こういう風に勘違いしてた。↓


    int (*comp)(void *, void *) = NULL;

    comp = (int (*strcmp)(void *, void *));


(;´△`).。oO(アァ゛ー、粘った甲斐があった。。。)

ヤハリ達成感は大切。
これでしばらくモチベーション持ちそう。
821廚C:02/06/16 23:51 ID:nXWaVSlp
しばらく、しばらく悩んでしまいました。
あ〜、キャスト…。型名だからこうなるのか…。

でも、これってどう使うんですか?NULL初期化している意味は?
822ぺログラマー1号:02/06/17 06:16 ID:Q2Iohqr2
>>821
不正なメモリ領域へのアクセスを防ぐためと
NULLで初期化しておけばその関数ポインタを使うときNULL判定で
ポインタが使われていない事がわかる。・・・かな?

あとこうするといいかも

typedef int (*pfunc)(void *, void *);

pfunc pf = (pfunc)(strcmp)

こうする方が見やすいよ。

age
823ぺログラマー1号:02/06/17 06:18 ID:Q2Iohqr2
訂正(汗

誤)pfunc pf = (pfunc)(strcmp)
正)pfunc pf = (pfunc)(strcmp);

824ぺログラマ1号:02/06/17 06:47 ID:Q2Iohqr2
関数ポインタの使い方とその例

例えばある構造体stがあってこの構造体を引数とする処理関数が幾つかあり、
メンバーnoで処理関数を変えたいとします 構造体はこんな感じ。
typedef struct {
 int no;
 int hoge;
} st;

処理関数の種類は8種類としましょうか。

void func0( st ); void func1( st ); ・・・ void func7( st );

とこんな感じで。
でこれらの関数のポインタを関数ポインタ配列にぶち込んでおきます。↓

typedf int (*pfunc)( A );
pfunc pf[8] = { func0, func1, func2, func3, func4, func5, func6, func7 };  

後は呼び出すときですが
構造体stのaというのがあったとして

pf[a.no]( a );

と、これだけです。
switchやifを使うよりも効率がいいですね(いいのかな?)
オマケにコードもスッキリします。
あとageてスマン。

825まただ・・・鬱:02/06/17 06:52 ID:Q2Iohqr2
↑のカキコ訂正

誤)typedf int (*pfunc)( A );
正)typedf int (*pfunc)( st );

鬱だ・・・
826王子様 ◆D48Lv1aI :02/06/17 07:10 ID:y1Dw4Y6H
プログラミングできるのに どうしてこの無職ダメ板に居るの?
PGとして働けるのじゃないの?

当方は情報系専門をこの春に卒業したのですが プログラミングできないため
無職3ヶ月 少し興味持って聞いてみました
827ぺログラマ1号 :02/06/17 12:06 ID:Vqh+v2dI
>>826
折れの場合は年齢がネック(今年で28鬱)、プログラミングは
人並み(以下?)だけど資格もってねぇしな。暇つぶしに基本情報でも
とってみようかと思ってるが・・・プログラマーなんて情報産業界の
土方だからなぁ・・・。

どうでもいいが君の方こそ専門学校に行ってたのに、なぜプログラミングが
できないの?

828825の訂正:02/06/17 15:55 ID:r/1J0awK
誤)typedf int (*pfunc)( A );
正)typedef int (*pfunc)( st );

欝だ・・・・・・・・・激しく欝だ。
829色即是空:02/06/17 21:57 ID:/FCRb5O7

以下の文章はあくまで「私の理解」です。
正確である保証は出来ません。



-------- ここから --------

>>821

820 は K&R 5 - 11:「関数へのポインタ」のサンプルコードからです。

プロトタイプ
        void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *));

使用例
        qsort((void **)lineptr, 0, nlines - 1, (int (*)(void *, void *))(numeric ? numcmp : strcmp));

このサンプルコードでは qsort の第4引数として比較関数へのポインタをとっています。
複数の「型が同じ比較関数」から選べるように(この場合は strcmp と numcmp)と言うことらしいです。
標準関数の qsort も第4引数に関数へのポインタをとります。

他の使いかたとしては、関数のテーブルを作ったり、構造体のメンバーに入れたりといったところですか。
実際にはまだ使ってないですけど。

関数テーブルについてはどこかにあったような気が。。。 C-FAQ だったか。。。

830色即是空:02/06/17 22:02 ID:/FCRb5O7

        int (*comp)(void *, void *) = NULL; /* 1 */
        comp = (int (*)(void *, void *))strcmp; /* 2 */


1 で宣言しているのは「ポインタ変数 comp」です。
comp はここでは関数のアドレスを入れるための「変数の名前(識別子)」です。
宣言と一緒に初期化しているに過ぎません。

        void *p = NULL; /* 3 */

と同じようなことです。


当然、 3 が

        void *p;
        p = NULL;

と出来るように、 1 も

        int (*comp)(void *, void *);
        comp = NULL;

と出来ます。


2 については、strcmp のプロトタイプは

        int strcmp(const char *, const char *);

なので、

        int (*comp)(void *, void *);

と宣言した comp とは引数の型が一致しません。
変数 strcmp を変数 comp に代入するにはキャストが必要と言うことです。
831色即是空:02/06/17 22:03 ID:/FCRb5O7

関数の名前 strcmp を「変数」と読んでいることについては以下のサンプルコードを。


#include <stdio.h>

int main(void){

/* printf のプロトタイプは int printf(const char *format, ...); */
/* printf と同じ型 (引数の型と戻り値の型が同じ) をもつ関数へのポインタ変数 myprintf の宣言。 */

         int (*myprintf)(const char *format, ...);

/* ポインタ変数を初期化。 */
         myprintf = NULL;

/* 普通に printf を使う。 */
         printf("1: Hello, World\n");

/* printf() という使いかたは実は (*printf)() の省略記法。 */
         (*printf)("2: Hello, World\n");

/* 型が同じ変数なので、代入も出来る */
         myprintf = printf;

/* そうすると当前 myprintf は printf と全く同じように使うことが出来る */
         (*myprintf)("3: Hello, World\n");
         myprintf("4: Hello, World\n");

         return 0;
}


-------- ここまで --------
832色即是空:02/06/17 22:05 ID:/FCRb5O7

何故自分がここで躓いていたのか考えてみました。
結論としては、「関数の型」と言えば「関数の戻り値の型」という先入観があったようです。
何でそんな先入観があったのかと思い出してみると、
学習初期の頃に「関数の型といえば戻り値の型のことを指す」という記述をどこかで見かけ、
なおかつ今回の「関数へのポインタの型をキャストする」まではそれで通用していたからだと思われます。

そういうことでいつのまにか頭の中で、
「関数の型」=「関数の戻り値の型」
「型キャスト」=「戻り値の型のキャスト(引数は対象外)」
という等式が勝手に成立していたものと思われます。


「記憶しない」というのも難しいですな。
出来るだけそうするように心がけていても。
833色即是空:02/06/17 22:16 ID:/FCRb5O7

>>822
便利ですね。
最近までそういう記述の意味が分からなかったんです。
「宣言は必ずしも左から読むとは限らない」というのを理解してからは読めるようにはなりました。

typedef は最近使いはじめたばっかりなので、これからです。
834廚C:02/06/17 23:50 ID:TOF+IQ50
うわ〜、えーと、うん、ありがとうございます、お二方。
関数の引数で関数ポインタを使って、処理の統合をしたことは
あります。…キャストせずに使ってたな…。それ一回だけ。
ポインタは未だに(゚д゚)ポエー、じゃなかった、ムズーです。

頭痛い。眠い。長文に対し短文で失礼します。おやすみなはい…。
835色即是空:02/06/23 18:33 ID:AtiwENjn

うむ。廚はいい人ですな。

基本的に他人がしたことに対して恐縮したりする必要はないと思います。
もちろん、私がしたことに対しても必要ありません。

ここへの書き込みは私自身の役に立ってますし、ついでに誰かの役にも立つでしょう。



(´-`).。oO(しかしこのスレを見ている人は少ない罠。。。)
836色即是空:02/06/23 18:34 ID:AtiwENjn

binsearch で期待どおりの結果が出ないので何日も悩んだあげく、
原因はデータ配列が未整列だったためと判明。


。。。マジデヘコンダ


教訓:前提をよく確認しましょう。

しかしこれだけ悩めば同じ間違いはしないだろう、とポジティブシンキングに切り替えてみる。



更に疑問が。
ポインタ同士の引き算の結果を整数で割るのはいいのか?
試したところ整数の割り算同様、半端な分は切り捨てられている模様。
結果自体は感覚的に自然で予想通りなのだけれど、
演算していい根拠がどこにあるのか分からない。
837色即是空:02/06/23 18:45 ID:AtiwENjn

・・・(・∀・)!

書き込んだ後で閃きました。
ポインタ同士の引き算の結果は整数値になるんですな。
整数だから別に割り算しても構わないと。
知ってたのに気がつかなかった。
何故かここの部分だけポインタ同士の引き算の結果はポインタになると思いこんでた模様。

ちなみにこれは K&R の 「6.4 構造体へのポインタ」の binsearch での話です。




悩んだときはそれを文章にしてみるというのはいいかも知れない。
文章にしてみると客観的に見れる。

これで先程の binsearch でヘコンダ分は帳消し。
838色即是空:02/06/23 18:58 ID:AtiwENjn



(´-`).。oO(夏が終わる頃には1000いくかなぁ。。。)
839色即是空:02/06/23 19:47 ID:AtiwENjn

ケアレスミス多発。

struct tnode{
    char *word;
    int count;
    struct tnode *left;
    struct tnode *right;
};

と、宣言しておきながら、

struct tnode *talloc(void){

    return (struct tnode *)malloc(tnode);

}

などとやってコンパイラに怒られること数時間。。。
840色即是空:02/06/23 19:51 ID:AtiwENjn

その2

2分木で。

英文を単語に分解してそれぞれを格納。
表示するときには格納した順番だと思いこんでたら、
アルファベット順だったのね。
しばらく使ってなかったら勝手に自分の脳内データ構造が変わっていた罠。

また勘違いで、3時間。



(;´△`).。oO(最近多いな。。。てか、多すぎ。。。)
841色即是空:02/06/23 19:55 ID:AtiwENjn

しかしこれだけ痛めつけられれば次は大丈夫だろう、
と思いたい、思いこみたい。


でもこういう単純なミスこそ、
自分で気が付くまで探すのが結局成長への近道なのだと自分に言い聞かせてみる。


無理矢理ポジティブシンキング。ワショーイ
842色即是空:02/06/23 20:38 ID:AtiwENjn

>>839

    return (struct tnode *)malloc(tnode);

は、こんな風に書いたつもりだった。↓

    return (struct tnode *)malloc(sizeof(tnode));


間違いすら間違えて激しく鬱。
マジデ ヘコム。


今日はもう寝よう。。。
843  :02/06/24 04:49 ID:rIZNKYnJ
475まで落ちていたのであげてみますた
844王子様 ◆D48Lv1aI :02/06/24 07:24 ID:TT2hAAf5
>>827

学科選びが間違えたのよ・・・
専門では 情報処理科 と アミューズメント科(ゲーム) 以外は プログラミングを一切教えない・・・
情報処理科選ぶべきだった・・・
845ダメダメ:02/06/24 11:37 ID:j0gd/7H1
>色即是空
おひさです。ひさびさに上がっていたので書き込んでます。
勉強がんばってるようですね。
俺もmallocの引数は以前よく型名を書いてコンパイラに怒られてました。
最近ではあまり間違わないようになってきたけどたまに間違えるw
けど、間違えてもすぐここがおかしいってわかるようになました。
間違えた経験は絶対力になってると思います。
846ダメダメ:02/06/24 12:00 ID:2lua+9SB
>>842
あれこれってstructを付け忘れたってことかな。
俺もちょっと勘違いしてたかな。
どっちにしても一回間違えれば次からは気をつけるだろうし
間違えてもすぐわかる。
847専門神 ◆Yuri7mb. :02/06/25 11:47 ID:TzE6U1F8
>>844
こんなところに居たとは。
848ぺログラマー:02/06/26 08:48 ID:VNzwshlp
847>>
折れも専門板のスレッド一覧でちらっと見かけたことがあるが・・・このお方が・・・
一体どんな学科選んだんだ?

#今月のCマガの特集のレンジコーダがわからん(鬱

849バナナじゃ時計は動かない:02/06/29 12:44 ID:jZZxzdj3
すごい遅すれですね。でも、皆さんがんばてください。
850廚C || 厨JSP:02/06/30 01:18 ID:AYJ3cUwS
さよなら、C言語。会社の研修も終わり、JAVA関連の
仕事に就くことになりました。JAVAの知識はほぼ皆無ですが。
他のもっといろんなことを勉強した上で、改めてC言語に
帰ってくると、出来ることが増えて楽しそうな気がする。
851色即是空:02/06/30 23:49 ID:JYciI5nO

>>850
ポカーン。。。(ガーンの上

。。。組織はつらいですな。


3か月の研修期間が終わって、実戦配備ですか。
もう3か月、いやまだ3か月か。
とにもかくにも凹んでる暇はないですな。
がんがってくだされ。


言語が変わってもプログラムの目的自体はたいして変わらないし、
どんな言語にも共通する部分というのがあると思うので、
知識に頼らず考えることを怠らなければ、
後で C に戻ったとしても短期間で修得できると思います。

自分の限界を自分で決めてしまわないことが大切。
852色即是空:02/06/30 23:59 ID:JYciI5nO

>>ダメダメ
どうも、お久です。
いつもお久ですと言っているような気がします。(W

このスレだけを読んでいると私が勉強家のように見えてしまう罠。(ニヤリ

実際は何とか進んでると言ったところです。
今までダメだったのは「続けられない」からだったという自己分析に基づき、
ひたすら途切れないことだけを頭に置いてます。
853色即是空:02/07/01 00:00 ID:DADegPVq

>>848
C マガ読みたい。モーレツに。
しかし今は我慢して基礎固め。
854色即是空:02/07/01 00:01 ID:DADegPVq

>>849
長寿スレと言っておくれ。
遅スレは音がイマイチ。

プログラマのくせに語感を気にするなという突込みは無しで。
855色即是空:02/07/01 00:06 ID:DADegPVq

ちょうど日付が変わりましたな。
今月中に初心者卒業を宣言できるよう頑張りますわ。
856厨JSP:02/07/01 00:14 ID:ECyePfKt
>851色即是空
ありがとうございます。がんがります。
Cの(へなちょこな)基礎があるので、JAVAの勉強も
途中まではサクサク行きそうです。

で、取りあえず、JDKとApacheと Tomcatを入れてみた。
最初に何をやったかといえば、Cygwin上で
System.out.println("Hello!");
"こんにちわ、世界"にすべきだったか。
…先は長い。
857 :02/07/01 05:37 ID:YnpV4vHe
858ひきプロ:02/07/01 15:59 ID:2GK/0/r1
すげえすげえ、駄目板にもあったのか
ヒキからきますた
859ハラッパ☆ラッパー ◆j4WJqlk. :02/07/01 18:44 ID:B6+Rg0/M
同じくヒキ板からきますた。相互リンク。

プログラミング雑談 in HIKIKO.Ver3.1.5
http://life.2ch.net/test/read.cgi/hikky/1022078381/
860厨JSP:02/07/07 01:47 ID:nf0vLsdE
ヒキ板のスレ、(ここよりは)盛り上がってますな。
私はCからちょっと離れているので、このスレに
書くのも何だし。
861色即是空:02/07/07 04:16 ID:6ZnhtGke

>>ひきプロ
>>ハラッパ☆ラッパー ◆j4WJqlk.

遅レス失礼。

もう行ったかも知れませんが、
現在この板にはプログラム系はあと3つあります。
「Delphiやろうぜ!」
http://salami.2ch.net/test/read.cgi/dame/1018335057/l50
「プログラミング集会所@ダメ板」
http://salami.2ch.net/test/read.cgi/dame/1018736040/l50
「ギャルゲーを作ろう!@ダメ板」
http://salami.2ch.net/test/read.cgi/dame/1022884270/l50

書き込む人はあんまりいませんし、
リアルタイムでの会話はほぼ成り立たないと思った方がいいです。
当然のことながら情報交換は難しいと思います。
メール交換するぐらいの気持ちだといいかも。

慣れてしまえば荒しとかもほとんどありませんし、いい感じですよ。

独り語ちるのに最適。(W


ところでヒキプロはプログラム板の方で
以前ブロックくずしを作ってた人だったりしますか?
862色即是空:02/07/07 04:18 ID:6ZnhtGke

>>860
900 ぐらいまで行ったらこのスレから使えそうな情報を抜きだして、
まとめレスするつもりです。

その後は集会所の方に移動しようと思います。

向こうに書くネタが無いんで丁度いいかなと。
863色即是空:02/07/12 23:45 ID:/vywCsNk

関数外で宣言してある関数はいちいち extern で宣言することにした。

#include <stdio.h>

int main(void){

    extern int printf(const char *, ...);

    printf("Hello, World!\n");

    return 0;
}

取りあえずコンパイラに何も言われないということは間違ってはいないのだろう。
あとで裏付けを取る必要はある。
864色即是空:02/07/12 23:46 ID:/vywCsNk

auto とかも使う。
さすがに異和感があるが、変数の範囲と寿命を意識するため当分続けることにする。
865色即是空:02/07/12 23:47 ID:/vywCsNk

識別子の最初の文字があアルファベットでなければならないのは
トークン切り出しの都合ではと思う今日この頃。
866色即是空:02/07/12 23:48 ID:/vywCsNk

例題の出来具合を日付と共に付け始めて一月半。
1回目は1月以上かかったのに2回目は2週間で終われそう。
来週3回目を1週間で終わらせて、
再来週は良く分かっていないところと附録Aをやる予定。

今月中に初心者脱出キボンヌ。



(´-`).。oO(まぁ、自分次第だな。。。)
867色即是空:02/07/12 23:49 ID:/vywCsNk

宣言、再帰、可変引数リスト、辺りが苦手。
あとは寿命と範囲を調べなければ。
ポインタも要復習。

使えるからと言って裏付けを取らないものを記憶するとあとで困る。
868色即是空

一通り終わったら GLUT でもやろう。
さすがに脳内 VRAM にも飽きて来た。