トップページ⇒tech
1001コメント286KB

C言語なら俺に聞け! Part 114

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2005/09/17(土) 00:26:58
まず問題を冷静に吟味してCの話か否かをはっきりさせてから質問しましょう。
質問する前には最低限検索を。

GUIなどの標準Cではできない事の質問は使用している開発環境のスレへGo! (←ここ注目)
ソース丸投げ、宿題、書籍 は専門の別スレがあるのでそこへさようなら。

エラー(警告含む)が起きたのならばエラーメッセージを書きましょう。

C FAQ 日本語訳
http://www.kouno.jp/home/c_faq/
Cプログラマ必読 ・プログラミング言語C(通称 K&R)
http://www.amazon.co.jp/exec/obidos/ASIN/4320026926/

C言語なら俺に聞け! Part 113
http://pc8.2ch.net/test/read.cgi/tech/1125136478/

他の過去ログはここに
http://nssearch.hp.infoseek.co.jp/clang/
0232デフォルトの名無しさん2005/09/19(月) 01:28:29
用途を言え
0233デフォルトの名無しさん2005/09/19(月) 01:30:05
>>231
ケースバイケースです。以上。
0234デフォルトの名無しさん2005/09/19(月) 01:30:47
>>231
普通は
 ・確保したバッファを呼び出し元の関数に返したい場合
 ・途中でバッファのサイズを拡張する可能性がある場合
 ・サイズが128ではなくてデカ過ぎる場合
はmallocを使う。それ以外なら上で良いでしょう。
0235デフォルトの名無しさん2005/09/19(月) 01:48:56
>>232
デバッグ用にprintfっぽく使えるメッセージボックスを作ろうと思ったんですが・・・
しょっちゅう呼び出す関数は確保→開放ってやると遅くなるかと思って・・・

>>234
ありがとうございます。
0236デフォルトの名無しさん2005/09/19(月) 02:05:02
>>235
デバッグでパフォーマンスは気にしない。
0237デフォルトの名無しさん2005/09/19(月) 02:29:41
デバッグでなくても、
メッセージボックスの表示のオーバーヘッドで
全く気にならないはずだ。
0238デフォルトの名無しさん2005/09/19(月) 02:31:56
>>211
メモリを保持してないポインタはNULLにしておくべきだろ
アロケート目的に使わないならfreeしないから関係ないけど。

>、「0フィルしておけば安全」という間違った考えがバグを生みデバッグを困難にする
それはどんな状況ですか?
そういう経験はしたことないんですけど。
0239デフォルトの名無しさん2005/09/19(月) 02:59:03
×0フィルしておけば安全
○NULL フィルしておけば、NULL フィルしないよりは安全

NULL フィルしたからといってバグがなくなるわけではないが、バグ検出に役に立つ。
NULL へのアクセスは大抵の環境で実行時エラーが出る。
NULL フィルしなかった場合は、偶然どこかの正常なアドレスを指してる可能性がある。
例えば、昔ポインタとして使われたスタック領域と同じところに
そのポインタが割り当てられたときなどは、可能性としては十分あり得る。

代入が直後にある場合などは必要ないと思うかもしれないし、
実際入れなくても現時点では何も問題はないが、
後の拡張やコードの移動により問題が発生する可能性はある。
NULL フィルのオーバーヘッドが気になるような状況でもない限り、
NULL フィルしといた方が安全ってのは正しい。
0240デフォルトの名無しさん2005/09/19(月) 03:07:09
わざわざデバッグビルドで固定値を突っ込んでくれるコンパイラもあるというのに……
0241デフォルトの名無しさん2005/09/19(月) 03:12:14
0とNULLの区別がつかない人って、初心者に良くいるよね。
0242デフォルトの名無しさん2005/09/19(月) 04:01:36
>>241
詳しく
0243デフォルトの名無しさん2005/09/19(月) 04:23:47
>>241
それは紛らわしい書き方なんだが、
かといって正確に書こうとするとややこしい。

>>242
http://www.kouno.jp/home/c_faq/c5.html#0
0244デフォルトの名無しさん2005/09/19(月) 04:54:06
>>240
それはコンパイラに依存すると言うことですよね?
いちいちコンパイラの仕様を確認しなければならず、
違っていればやり方を変えなければならないと言うことですよね?

デバッグビルドとリリースビルドで動作が違ってくるって事ですよね?
デバッグビルドで取り除けるバグを、リリースビルドで見つけなければならないと言うことで、
デバッグが大変になりますよね?
0245デフォルトの名無しさん2005/09/19(月) 04:57:23
阿呆はだまってろよ
0246デフォルトの名無しさん2005/09/19(月) 05:07:28
でも、ぶっちゃけリリース版でしか再現しないバグってのがあるから困りもんだ。
0247デフォルトの名無しさん2005/09/19(月) 05:09:44
>>245
自分の主張と、間違ってると思われる発言を書けよ

自分のアホは指摘されたくないってか?
0248デフォルトの名無しさん2005/09/19(月) 05:20:59
>>240
もしかしてコンパイラに固定値突っ込ませてデバッグ後、
固定値突っ込むのをOFFにするオプションつけたデバッグビルドでもデバッグするのかな?

少しでもコードを取り除きたいならそれもいいかもね。
めんどくさ。
0249デフォルトの名無しさん2005/09/19(月) 05:22:12
>>246
ねーよwwwwwwwwwwww
0250デフォルトの名無しさん2005/09/19(月) 05:25:00
>>247が何故かものすごく必死な件に付いて
0251デフォルトの名無しさん2005/09/19(月) 05:33:59
悔しかったらCYGWINの/usr/bin/share/docと/usr/bin/share/manを
間違って上書きしちゃったどうしようdocだけ最インストできそうだけど
manはどうしようってなってる俺をどうにかしてみろよおめーら
02522512005/09/19(月) 05:36:21
ワワワワワ
激しく誤爆しちまったじゃねえか
ついでにすれ違い覚悟で聞いてみるけど
どうしたら一番効率よくもどにもどせれる?
0253デフォルトの名無しさん2005/09/19(月) 05:36:34
>>249
VC5のコンパイラのバグでlongdoubleの演算最適化ができなかった。
リリースビルドでしか再現しなかった。
MSにコード渡してチェックしてもらったけど、コーディングの問題はないと言われた。

プラグマでその部分の最適化を外して対応した。

>>250
実務未経験プログラマから見れば必死に見えるのか。
0254デフォルトの名無しさん2005/09/19(月) 05:40:57
>>251
コピー元ファイル一覧をつくり、
delコマンドのバッチファイルにし、実行する。
0255デフォルトの名無しさん2005/09/19(月) 05:49:50
あ、ユニックスだっけ?
DOSでもいいけど
ファイル一覧をパイプでdelコマンドに渡すのが一番早いかな。
でも僕は使い慣れてないからテストしてからじゃないと実行しない。
テストするならバッチに書いたほうが確実で早いと。

VZエディタからのキーボードマクロにはお世話になった。
0256デフォルトの名無しさん2005/09/19(月) 10:11:11
100げと
0257デフォルトの名無しさん2005/09/19(月) 11:16:07
>>256
ヘキサかよw
0258デフォルトの名無しさん2005/09/19(月) 11:44:07
このスレのまとめサイト作りました
ttp://aferieito.gozaru.jp/
0259デフォルトの名無しさん2005/09/19(月) 11:50:56
華麗にスルー
0260デフォルトの名無しさん2005/09/19(月) 11:56:05
アフィリエートの綴は、aferieitoじゃなくて、affiliate
0261デフォルトの名無しさん2005/09/19(月) 13:44:52
>>249
私は一回ありましたよ。
詳細は忘れてしまいましたが法線を求めた時にデバッグビルドだと0、
リリースビルドだとINFになりました。
数学関数の挙動に違いがあったとかそんな感じです。
0262デフォルトの名無しさん2005/09/19(月) 14:02:44
マクロについて質問です。
メモリリークを調べるため、
自作のアロケーターでmalloc関数群を隠そうと思います。

void *chk_malloc(size_t size, file, line) {

}
#define malloc(size) chk_malloc(size, __FILE__,__LINE__)

こんな感じです。

この場合、

int (*f)() = malloc;

の様に値として代入が発生した場合は関数マクロは効力が発揮できませんが、
この場合でもchk_mallocを代入するように細工する方法はないでしょうか。

#define malloc chk_malloc
とすると fileとlineの情報が欠落してしまいます。
0263デフォルトの名無しさん2005/09/19(月) 14:16:24
>>262
グローバル変数へパラメータを追い出してみるのはどうだろう

const char*chk_malloc_file;int chk_malloc_line;
void* chk_malloc_(size_t sz){

}
void*(*chk_malloc(const char*file,int line))(size_t){
    chk_malloc_file = file;chk_malloc_line = line;
    return chk_malloc_;
}
#define malloc chk_malloc(__FILE__,__LINE__)

まぁこの実装だと同時に2箇所以上で使うと破綻するけど
0264デフォルトの名無しさん2005/09/19(月) 14:17:13
>>263
ありがとうございます。
面白いですね。
試してみます。
0265デフォルトの名無しさん2005/09/19(月) 14:21:11
>>262
そりゃ、関数ポインタ自体に file と line 用の引数がない限り、どうしようもないわな。

#ifdef NDEBUG

typedef void* (*malloc_fp_t)(size_t size);
#define MALLOC_FP malloc
#define MALLOC_CALL(fp, size) fp(size)

#else

void* chk_malloc(size_t size, const char* file, int line);

typedef void* (*malloc_fp_t)(size_t size, const char* file, int line);
#define MALLOC_FP chk_malloc
#define MALLOC_CALL(fp, size) fp(size, __FILE__, __LINE__)

#define malloc(size) chk_malloc(size, __FILE__, __LINE)

#endif

malloc_fp_t fp = MALLOC_FP;
char* buf = MALLOC_CALL(fp, size);

こんなところだと思うが・・・。
02662632005/09/19(月) 14:21:22
よく考えると2段の関数にしなくてもこれで充分だった

const char*chk_malloc_file;int chk_malloc_line;
void* chk_malloc(size_t sz){
    return malloc(sz);
}
#define malloc (chk_malloc_file = __FILE__ , chk_malloc_line = __LINE__ , chk_malloc)
0267デフォルトの名無しさん2005/09/19(月) 14:24:24
>>263
それだと、関数ポインタを使ったとき(メモリを確保したとき)の情報じゃなくて、
関数ポインタに代入したときの情報が表示されてしまうと思うのだが。
発想の面白さは買うけど。
0268デフォルトの名無しさん2005/09/19(月) 14:28:37
>>265-267
大変勉強になります。
ありがとうございます。
0269デフォルトの名無しさん2005/09/19(月) 14:32:10
#define MALLOC_CALL(fp, size) (fp)((size))
#define MALLOC_CALL(fp, size) (fp)((size), __FILE__, __LINE__)
#define malloc(size) chk_malloc((size), __FILE__, __LINE)

こうしといた方が安全か。
0270デフォルトの名無しさん2005/09/19(月) 15:03:21
mallocなんてキチガイじみたものを使わないのが正解。
0271デフォルトの名無しさん2005/09/19(月) 15:05:57
>>270
C++ならともかく、Cでmalloc無しってどうすればいいんだよ。(calloc realloc をつかえとか言うなよ)
0272デフォルトの名無しさん2005/09/19(月) 15:09:40
>>271
API使えって句とかと。
0273デフォルトの名無しさん2005/09/19(月) 15:10:30
は?
0274デフォルトの名無しさん2005/09/19(月) 15:10:43

 ̄ ̄ ̄ ̄ ̄ ̄∨ ̄ ̄ ̄
          ______
         /:::::::::::::::::::::\
       /::::::::::::::::::::::::::::::::\
       |::::::::::::::::       |
       |::::::::::::::: ∪ \,, ,,/)
       |::( 6::ー──◎─◎|
        ノ::: (∵∴∪ ( ・ ・))
     /      ∵    3 丿    ブフィ
    /\    U   ___ノ
  /   .\      ____ノ\
        \______ノ  .\
0275デフォルトの名無しさん2005/09/19(月) 15:16:53
>>271
realloc じゃないか? 上のアレ。
0276デフォルトの名無しさん2005/09/19(月) 15:30:21
過去スレに居たな malloc() なんて必要無いって言ってたの。
スタックに予め大きく取って分ければ良いとか言ってたっけな。
そいつもかなり鬱陶しかった。
0277デフォルトの名無しさん2005/09/19(月) 15:42:56
スタックじゃなくてヒープだろw
0278デフォルトの名無しさん2005/09/19(月) 15:47:27
0で初期化が必要って状況じゃない限りmalloc使うわな
0279デフォルトの名無しさん2005/09/19(月) 16:11:57
それよりcallocの2つの引数の使い方が、謎。
0280デフォルトの名無しさん2005/09/19(月) 16:36:14
>>279
お好きなように。プロジェクト単位で使い方のルールが統一されていると読み易くて宜しいかと。
0281デフォルトの名無しさん2005/09/19(月) 16:47:54
calloc()とfread()はセンスねーなと思うな
0282デフォルトの名無しさん2005/09/19(月) 16:55:19
fread は別に構わんと思う。
エラー時に、中途半端にデータが埋められるってのがないから。
でも、calloc はよく分からん。
何か、環境依存で問題があったりするんだろうか。
0283デフォルトの名無しさん2005/09/19(月) 17:05:28
http://www.linux.or.jp/JM/html/LDP_man-pages/man3/malloc.3.html
デフォルトでは、Linux は楽観的メモリ配置戦略を用いている。
つまり、 malloc() が NULL でない値を返しても、そのメモリが
実際に利用可能であることが保証されない。これは本当にまずいバグである。


Linuxてこわいな。
0284デフォルトの名無しさん2005/09/19(月) 17:10:29
え、Linuxってそんなにも糞だったの?
0285デフォルトの名無しさん2005/09/19(月) 17:11:21
Linux >>>>>>>>>> Windows Seriese
0286デフォルトの名無しさん2005/09/19(月) 17:21:43
カーネルのバージョンが十分に最近のものであれば、
このメモリを割り当て過ぎる動作を以下のコマンドで無効にできる。

# echo 2 > /proc/sys/vm/overcommit_memory
0287デフォルトの名無しさん2005/09/19(月) 17:30:15
>>286
だから、ソフトウェアが普通に組まれてても、
コマンド発行するまで危険な動作をする可能性があるということでしょ。

素人がLinux構築するとバグだしまくりなのは、
素人が使うことを前提としたWindowsとはやはり違うということで。

ま、Linux単体で使う人もあまりいないでしょうけど、
Linuxを盲目的に信奉すると危険てことですね。
0288デフォルトの名無しさん2005/09/19(月) 18:11:52
そんなレベルの話じゃないような気がする。
はやくバグフィクスしろよ。
0289デフォルトの名無しさん2005/09/19(月) 18:38:09
それってマニュアルのバージョンが古いだけちゃうんかと
0290デフォルトの名無しさん2005/09/19(月) 19:04:10
古いとしても12年も更新されてないのか。
やる気0だなw
0291デフォルトの名無しさん2005/09/19(月) 19:11:58
今更だが上の配列の方の話で…
今まで1次元配列の方が早いだろうと思って多次元配列を1次元で書いてたんだが、>>199見る限り速度的にそんなに差はないってこと?
0292デフォルトの名無しさん2005/09/19(月) 19:14:16
>>291
あんま変なことしてると、
最適化がうまく効いてくれないかもしれないぞ。
0293デフォルトの名無しさん2005/09/19(月) 19:16:59
>>291
んなことが気になるぐらいならasmのソースでも比較すりゃいいじゃねえか
0294デフォルトの名無しさん2005/09/19(月) 19:24:27
僕の人生も最適化できたらなァ
0295デフォルトの名無しさん2005/09/19(月) 19:28:17
>>294
人生が環境依存になりますがよろしいでしょうか?
0296デフォルトの名無しさん2005/09/19(月) 19:54:15
配列へのポインターを返す関数を作りたいと思います

int   ReturnValue[5][5];と宣言して
return ReturnValue;としたいのですが,

関数宣言の仕方が分かりません<m(__)m>

int** ThisFunction();これではだめでした!
このint**がエラーのようですが,正しくはどのように宣言するのでしょうか?
0297デフォルトの名無しさん2005/09/19(月) 19:56:05
俺の人生、最適化の前の構文解析あたりでつまずく・・・
0298デフォルトの名無しさん2005/09/19(月) 20:20:53
誰か人生をデバッグしてください。
0299デフォルトの名無しさん2005/09/19(月) 20:31:11
>>296
一応型だけを見れば

int (*ThisFunction())[5];

か

typedef int ArrayType[5];
ArrayType* ThisFunction();

か

typedef int (*ReturnType)[5];
ReturnType ThisFunction();

で、int** がダメな理由は >>221 。

ただ、配列を内部変数として取ってるのに
そうやって返すことはできないぜ。
0300デフォルトの名無しさん2005/09/19(月) 20:40:52
>>299
int (*ThisFunction())[5];でできました!
ありがとうございます

全く予想付かない形でした

>>ただ、配列を内部変数として取ってるのに
>>そうやって返すことはできないぜ。
実際はクラスの中の変数を,Public関数から返します
0301デフォルトの名無しさん2005/09/19(月) 21:08:29
C++ ジャン!
まあ、C++ 関係ない話だったからいいけどさ。
0302デフォルトの名無しさん2005/09/19(月) 21:25:13
memsetを使うとchar型の配列を高速で初期化できます
ところでint型の配列を高速で初期化する方法はないのでしょうか?

int BigArray[100][100];
for(int x=0;x<100;x++){
for(int y=0;y<100;y++)
BigArray[x][y]=10;
}
↑これを高速化したいのです!
0303デフォルトの名無しさん2005/09/19(月) 21:31:04
>>302
memset使えばいいじゃないか
0304デフォルトの名無しさん2005/09/19(月) 21:39:05
memsetのほうが高速という保証はどこにも無いと思うんだが
0305デフォルトの名無しさん2005/09/19(月) 21:42:19
>>303
memset はバイト単位じゃねぇか
0306デフォルトの名無しさん2005/09/19(月) 21:43:01
>>302
for(int i = 0; i < 10000; i++) {
 BigArray[0][i] = 10;
}
で少しくらいは速くならないかな?
0307デフォルトの名無しさん2005/09/19(月) 21:44:13
>>302=305

int もバイト単位でアクセスできますが?
0308デフォルトの名無しさん2005/09/19(月) 21:48:22
>>307のレスの意味が分からない
0309デフォルトの名無しさん2005/09/19(月) 21:50:15
int BigArray[100][100] = {0};

これがはやいんじゃねーの?
0310デフォルトの名無しさん2005/09/19(月) 21:52:17
>>307 >>309
よく見ろ。0 じゃなくて 10 で埋めるんだぞ?
0311デフォルトの名無しさん2005/09/19(月) 21:59:54
memsetの定義は
void *memset(void *s, int c, size_t n);
で。
速度云々は別としてmemsetで問題ないと思う。
0312デフォルトの名無しさん2005/09/19(月) 22:00:54
>>310
w
0313デフォルトの名無しさん2005/09/19(月) 22:02:36
>>311
てことは、逆にキャラ配列で10 padding するには、0x0a0a0a0a で生めにゃならんのか?
そういう使い方したことないから、気づかんかった。
0314デフォルトの名無しさん2005/09/19(月) 22:04:42
>>311-312
何を言っとるんだw

c の型は int だけど、実際に使われるのは下位1バイトだけだぞ!
c の型が int なのは、標準関数の引数には char を使わないから(ポインタ除く)。
0315デフォルトの名無しさん2005/09/19(月) 22:08:14
>>314
memsetは0で初期化する場合はintにも使えますが,10では無理です
0316デフォルトの名無しさん2005/09/19(月) 22:10:00
>>315
だから、さっきからそう言ってるじゃないか。
0317デフォルトの名無しさん2005/09/19(月) 22:13:18
初期化部で
int BigArrayBuf[100][100];
for(int x=0;x<100;x++){
for(int y=0;y<100;y++)
BigArrayBuf[x][y]=10;
}
ってしといて、使うとこで
int BigArray[100][100];
memcpy(BigArray,BigArrayBif,sizeof(BigArray));
ってすりゃええやん
0318デフォルトの名無しさん2005/09/19(月) 22:16:57
高速化したら幸せになるのか?
0319デフォルトの名無しさん2005/09/19(月) 22:18:07
いつもの自己満足
0320デフォルトの名無しさん2005/09/19(月) 22:19:41
大量のバッファ(メモリ)にアクセスするのと、代入していくのとだと、
代入の方が速い気がするけど、実測してみないと結論は出せぬ。
0321デフォルトの名無しさん2005/09/19(月) 22:20:34
int BigArrayBuf[100][100] = {10,10,10....10};
でいいじゃん
10000個の要素はawkなりPerlなり前処理で
自動生成すればいい
0322デフォルトの名無しさん2005/09/19(月) 22:25:16
memsetで初期化とか言わないでほすぃ
初期化は宣言と同時に行うものだよ









うざがれそうだが…
0323デフォルトの名無しさん2005/09/19(月) 22:31:03
プログラム中に初期化したい時もない?
0324デフォルトの名無しさん2005/09/19(月) 22:37:57
文法における初期化とは別の話だぞ?
作業としての初期化だ。
0325デフォルトの名無しさん2005/09/19(月) 22:44:41
混乱するから混同すんなって言ってんじゃないの?w
0326SSE2依存2005/09/20(火) 02:49:10
#include <emmintrin.h>

void foo()
{
  __declspec(align(16)) int BigArray[100][100];
  int i;
  const __m128i v = { 10, 10, 10, 10 };

  for ( i = 0; i < 100 * 100; i += 4 ) {
    _mm_store_si128( (__m128i*)&(BigArray[0][i]) , v);
  }
}
0327デフォルトの名無しさん2005/09/20(火) 02:51:02
>>321
約40KBバイナリファイルサイズが増えます
0328デフォルトの名無しさん2005/09/20(火) 06:08:46
VC++6.0でやってます
scanfで数値を一文で横に入力するようにするにはどのようにプログラムすればいいでしょうか?
100 200 300 と入力する感じにしたいのです
よくわからなかったので
scanf("%d %d %d",&a,&b,&c)みたいにやってみたのですが
これだと縦に
100
200
300
と入力するようになってしまいます
やりかた教えてください

あと小数点つき123.45とか入力した場合
途中で終わってしまいます
小数点入り数値を入力しても大丈夫なやり方も教えてほしいです
0329デフォルトの名無しさん2005/09/20(火) 06:24:07
>>328
VC++スレの人だな
変換指定子が%d %d %dなら、「100 200 300」だろうと
「100[ret]200 300」でも「100[ret]200[ret]300」でも読み込めた希ガス

小数の場合は放り込む変数をfloatなりdoubleで用意して
変換指定子を%f
0330デフォルトの名無しさん2005/09/20(火) 06:50:45
>>329
ありがとうございます
とりあえず数値を入力して出力だけ出来るように今やってるんですが、現在こんな感じ
#include <stdio.h>
int main (void)
{
       float a;
int b,c,d;
scanf("%f",&a);
scanf("%d %d %d",&b,&c,&d);
printf("%f %d %d %d",a,b,c,d);
return 0;
}
入力するのはa=123.45 b=100 c=200 d=300って感じです
出力すると123.45が123.449997になってしまいます
あと[ret]入れるのは数値を入力するときでしょうか?入れてみたらすごい数値がでちゃったり
できれば[ret]なしで横に入力させるようにしたいです
連投が返事がおそく(´・ω・`)
03313002005/09/20(火) 06:56:06
あ、↑のなんか勘違いしまくってた
横に入力まではできてました
あと残る問題は123.45を入れると123.49997って出るだけです
そのまま123.45って出したい
■ このスレッドは過去ログ倉庫に格納されています