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

C言語なら、俺に聞け! <31>

■ このスレッドは過去ログ倉庫に格納されています
0001SHOW-A息子NGNG
漏れは32才。22年間、父SHOW-Aにプログラムを叩き込まれてきた。
いろいろな言語を極めたが、一番漏れになじんだのはCだった。
Cのことなら父をも超えた。疑問な点があったら漏れに聞け。

便所とメシ食ってる時以外は暇だが、いちいちFAQに載った質問に応えるほど暇じゃない。
課題丸投げなら別スレにいけ。あと、至急父に仕事を与えてやってください。

コンパイラ、過去ログなどのリンクは>>2-5 あたり
0159デフォルトの名無しさんNGNG
>>158
スレ違い
0160デフォルトの名無しさんNGNG
void showA(struct Monna *a, char* *id, int* position, char* *name)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
こういう
文字列リテラルの参照渡しっこんな感じでいいんすかね?
つーか、やっていいのかな?
0161160NGNG
ズレた(`・ι・´)
はぁ・・・
0162デフォルトの名無しさんNGNG
>>160
つまり、
void showA(char **name)
{
 *name = "sage";
}
こういうことをやっても問題ないだろうか
ってこと?
そうなら、別に問題ない。
0163160NGNG
>162

えっと、

void showA(char **name);
void showA(chae **name){
printf("%s\n",(*name))
}

void Main(){

char *name="microsystems";
showA(name);
}

みたいな感じです。よさそうっすね。
(゚∀゚)サンクスコ !
0164160NGNG
#include<stdio.h>

void showA(char* *name,int* age);

void showA(char* *name,int* age){
printf("name:%s\nage:%d",(*name),(*age));
}

int main(){
int age=43;
char *name="microsystems";
showA(&name,&age);
return 0;
}


ちょっと上違ったけど、できました。
これって値渡しより、関数呼び出し時に、新しい変数領域が確保されないので
効率的なんすよね?
0165デフォルトの名無しさんNGNG
char* *name
とかって、普通に使われてるものなんでしょうか。
素朴な疑問なんですけども。
0166デフォルトの名無しさんNGNG
>>164
何ですか?これは?
0167デフォルトの名無しさんNGNG
163も164も、ポインタにして渡す必要はまったくない。
(ついでに 163 はうっかりミスが2ヶ所あるよ)

> これって値渡しより、関数呼び出し時に、新しい変数領域が確保されないので
> 効率的なんすよね?

渡すのが構造体/共用体ならともかく、整数では
効率が下がることはあっても、上がることは
(通常の処理系では)考えられない。

それどころか、呼び出し側の最適化を邪魔することに
なるので、ほとんどの場合、処理が遅くなってしまうはず。

Cの場合、参照渡しと言うよりも「ポインタの値渡し」なんだから、
引数用の領域(それがスタックであれレジスタであれ)が使われる
ことには変わりない。
0168160NGNG
>167

>164が修正版っす。
やっぱり意味ないのですか〜
処理の負荷は上がって、メモリ効率はよいような気が。

引数の部分で(呼び出し元の変数がコピーされて)無駄に消費
されるのではないかな、と考えたわけですが。

上のようにポインタの値渡しをすれば、
引数用の領域には呼び出し元の変数へのpointerが格納されるのかと。

違うのかなぁ^^;そこら辺はコンパイラの最適化の範疇なんでしょうか。
0169160NGNG
>165

呼び出し先で、呼び出し元の変数の値を変更(同期)したい場合
なんかによく使われるのでは。あ、コーディングスタイルの問題?
0170寝不足でイライラNGNG
>>164のコードは何でダブルポインタ使ってるのか分からん。const char* で十分でそ?
intがポインタになってるのも分からん。何なんだよ?
0171167NGNG
>>168
> 上のようにポインタの値渡しをすれば、
> 引数用の領域には呼び出し元の変数へのpointerが格納されるのかと。

これだけは合ってるよ。

だから、(元の変数の領域とは別の) 引数用の領域に
char** と int* が入るか、
char* と int が入るか
の違いでしかない。
どちらも引数用の領域を必要とすることには変わりない。

その領域のサイズは処理系に依存するが、たとえば
UnixとかWin32なら 前者でも後者でも4*2バイトだね。

> そこら辺はコンパイラの最適化の範疇なんでしょうか。
最適化というより、呼び出し規則が決まってるのが普通。
実際のところ、どんな処理系を使ってるの?
0172160NGNG
>171

Linuxでgcc3.2っす。
0173167NGNG
>>172
だったら使われる引数用の領域のサイズにも違いはないよ。
32ビット整数で表現できるのに、それをわざわざポインタに
して渡してもメリットはない。
0174160NGNG
今頃風呂上りです^^;

ここらへん見ると、
http://www.google.co.jp/search?q=cache:3suLwvNaZI0C:www.alfasystem.net/dojo/room5/LectureC/c09.htm
+%E5%BC%95%E6%95%B0%E3%80%80%E9%A0%98%E5%9F%9F%E3%80%80C%E8%A8%80%E8%AA%9E%E3%80%80%E3%83%9D%E3%82%A4%E3%83%B3%E3%82%BF%E3%81%AE%E5%80%A4%E6%B8%A1%E3%81%97&hl=ja&ie=UTF-8
メモリアクセスで負荷はあがりそうっすね。

>170
参照ならぬ、ポインタの値渡しをしようと思ってのことです。
でも、素直に値渡しでよさげという結論になってきました。
0175160NGNG
結論として、ポインタの値渡しを使う場面は、

1.配列、構造体などのサイズのでかいものを渡す時
2.呼び出し先で引数として受け取った変数を、呼び出し元と
同期させたい時

ということで宜しいのかな。まぁ、細かいとこでは他にもありそうだけど。
0176 NGNG
>>175 当たり前の事を何を偉そうに結論しておるのかと小一時間
0177160NGNG
>176

ううY(>_<、)Y 175みれば当たり前なんでハマってました。
他にも巧妙な使い方があるのかと、期待もして書いたわけですが。
0178デフォルトの名無しさんNGNG
いつからこのスレはポインタスレになったんだ?
0179デフォルトの名無しさんNGNG
>>152
関数を追加するのと関数ポインタを追加するのは全然違うじゃない。
素直にできないと言いなよ
0180デフォルトの名無しさんNGNG
>>179
言っている事が全然分からんが?

もし、関数の "実体" を構造体内に入れる事が出来たとして、
それが関数のポインタで代用(?)する場合と
実用上どういう風に「全然違う」のか是非説明してくれ。
(もしかして初期化するのが面倒だなんていいたいのか?
本当にそうならば、そんな事する前にその関数を構造体に
入れる "必要性" を教えてくれ)

もしかしてC++のメンバ関数なんかもナイーブに
class 内に "コピー" する事で実現されているなんて
思っちゃってるの? (プ
0181デフォルトの名無しさんNGNG
>>180
はいはい、くだらないことをいってるしったか君、ごくろーさま
0182デフォルトの名無しさんNGNG
>>179 >>181 釣り師ハケーン

ナンセンスな質問に無理に答えるとこうなる
0183デフォルトの名無しさんNGNG
>>180が正論。>>179が無知。

> もしかしてC++のメンバ関数なんかもナイーブに
> class 内に "コピー" する事で実現されているなんて
> 思っちゃってるの? (プ

そんなことになったら sizeofの結果が恐ろしいな。
0184179NGNG
>>180
> もしかしてC++のメンバ関数なんかもナイーブに
> class 内に "コピー" する事で実現されているなんて
> 思っちゃってるの? (プ

そんなこと一言も言っていないが?
もしかして実体をコピーしなければいれることにはならないと思っているのか?
0185184NGNG
構造体には関数は追加できない。だから関数ポインタで擬似的なことをする。
C++のクラスの場合はその実体が関数ポインタだとしても言語の仕様上関数を追加できるだろ?
0186デフォルトの名無しさんNGNG
C言語もメンバをstaticに出来れば、そんなことにはなりませんな。
0187デフォルトの名無しさんNGNG
>>180
関数へのポインタって変数だよ。分かっている?
0188デフォルトの名無しさんNGNG
>>184
>もしかして実体をコピーしなければいれることにはならないと思っているのか?

お前の言う「いれる」の意味を問いたい。問い詰めたい。小1時間問い詰めたい。
お前、ただ "struct{void f(void){}}" って書きたいだけちゃうんかと。
0189179NGNG
>>188
仕様上の話だってば。
0190179NGNG
Cの構造体に関数を追加できるなんて言ったら大恥書くぞ。
0191デフォルトの名無しさんNGNG
ところで、C++のインライン関数ってまさに実体をコピーするんじゃないの?C++はよくしらないんだけど。
スレ違いでスマン。
0192デフォルトの名無しさんNGNG
>>190
「大恥 "書く" ぞ」
「C++のクラスの場合はその実体が関数ポインタだ」

なんて言う方がもっと恥をかくと思うが。。。
0193デフォルトの名無しさんNGNG
int main __P((int, char *[]));

↑
これはいったい何?
0194デフォルトの名無しさんNGNG
>>193
#define _P

なんで括弧が二重なんだ?(^_^;)
0195デフォルトの名無しさんNGNG
言う(話す)時は文字は使いません。と言ってみるテスト。
0196デフォルトの名無しさんNGNG
「言ってみる」という罠
0197デフォルトの名無しさんNGNG
ポインタ変数の値をアドレスというと叩かれるけど、&ooの&はアドレス演算子っていいますよね?
なんでですか?
0198デフォルトの名無しさんNGNG
>>185
あんたの言ってることも間違っちゃいないさ。
でもな、そういうのを世間一般では
「単なる揚げ足取り」とか「無知」と呼ぶのさ。

Q) Cで文字列を表示するにはどうすればいいですか?

普通のA)
一例としては、stdio.hをincludeして printf を使え。

185のA)
C言語の仕様上の話では、文字列という概念はない。
よって不可能だ。
Cで文字列を扱えるなんて言ったら大恥かくぞ。
0199197NGNG
ごめんなさい。
そう決まっているんだからしかたないですよね。
0200デフォルトの名無しさんNGNG
>>198
揚げ足取りならどっちもどっち。
0201デフォルトの名無しさんNGNG
Cならなんでもできる。
0202デフォルトの名無しさんNGNG
世界お金持ちクラブの歌 歌:ヘドロ
 おカネ おカネ おカネ おカネ おカネ おカネ おカネ おカネ
 お金さえあれば 何でも手に入る
 ドレス イヤリング 真珠の首飾り
 マンション 別荘 建て売りマイホーム
 車飛行機自家用潜水艦キャビアフォアグラ松茸に数の子
 お金さえあれば 幸せになれる 我ら世界お金持ちクラブ
0203デフォルトの名無しさんNGNG
>>200
どっちもどっちって、他方は誰のことを指してるの?
185が揚げ足取ってるだけに見えるが。

>>191
全然違うよ。

>>193
古いコンパイラでもコンパイルできるように
プロトタイプ宣言を使い分ける時の方法だね。

前もって
#define __P(x) x
と宣言すれば、
int main (int, char *[]);
と展開され、

#define __P(x)
と宣言すれば、
int main ();
と展開される。
0204デフォルトの名無しさんNGNG
指定したディレクトリ内にあるファイル名を参照したいです。
どうすればいいですか?WinMeです。
0205193NGNG
>>203
すごく分かり易い解説、ありがとうございまふ。
0206デフォルトの名無しさんNGNG
>>203
たった一行を書き換えるためにわざわざマクロを使うの?
コンパイルオプションでマクロを定義して使うの?
0207206NGNG
よく考えてみたらたった一行とかそういう問題じゃないか・・・
俺なら#if使うかな。
0208デフォルトの名無しさんNGNG
>>202
師匠!

たった1分足らずの時間で
その様な素晴らしいレスを見つけ出す秘術を
是非とも僕に伝授してください。
0209194ですNGNG
>>203
なるほどねー
だから括弧が二重なんだ。
二重にしないとint main int,char *[];になっちゃうな。
0210デフォルトの名無しさんNGNG
double data;
int dummy = 10;
dummy /= 50;
data = (double)dummy

printf("%f\n",data);

としても0が表示されます。なんで?
コンパイラのバグですか?
0211デフォルトの名無しさんNGNG
>>210 ネタだと言って欲しい
0212203NGNG
>>206
たくさんの関数宣言がある時でないと意味がないね。

それらの宣言をすべて
int func __P((...));
のような形式で記述しておいて、
コンパイルする環境によってマクロだけを切り換える。

普通は、公開ソースで色々なプラットフォームに
対応したい時に使うものだと思う。

zlibなんかもこの方法を使ってるから、見てみるといいかもね。
ttp://www.gzip.org/zlib/
0213デフォルトの名無しさんNGNG
>>208 んー だって憶えてたんだもん
0214デフォルトの名無しさんNGNG
>>209
それ以前に、マクロ __P() の引数の数がおかしいと怒られるから、面倒だけど
二重括弧は必要。
0215デフォルトの名無しさんNGNG
>>210
0と表示されたらライブラリのバグ(藁
0.000000と表示されないと(藁
0216デフォルトの名無しさんNGNG
alloc系でメモリを取得取得取得開放取得開放開放取得開放取得ってやってたら
ヒープがこまぎれずたずたになっちゃう気がするけど
OSはガーベッジコレクションとかちゃんとやってくれてるのかな?
とりあえずWinとかLinuxとかでの例を教えてほしいかも。
0217デフォルトの名無しさんNGNG
int a=0x10;
if ( a&0x10 == 0x10 ) printf("a==0x10\n");

としてもa==0x10が表示されてません。なんで?
コンパイラのバグですか?
0218デフォルトの名無しさんNGNG
昔、幼稚園児だったころ友達に「わかってることを聞く奴は馬鹿だ」
と言われたんですけど、僕は馬鹿だったんですかね
0219デフォルトの名無しさんNGNG
>>217
& より == の方が優先度高いから
if ( a & (0x10 == 0x10 ) )
と同義。キミのバグ。
0220デフォルトの名無しさんNGNG
>>218
キミは馬鹿じゃない。
0221デフォルトの名無しさんNGNG
>>218
馬鹿じゃなくてむかつくだけ。
人を試すってことだろ?
0222デフォルトの名無しさんNGNG
・・・・・できません。なんで?
コンパイラのバグですか?

が今のはやりですか?
昨日の9<a<10とかさ。
0223デフォルトの名無しさんNGNG
教えてください.

int Q = 41;
Q -= 4 * 9 - 4 - 1;

なぜ結果が Q = 10 になるのでしょうか ?
私は今まで Q = Q - 4 * 9 - 4 - 1; と同じだと思っていたのですが ...
0224デフォルトの名無しさんNGNG
>>223
Q=Q-(4*9-4-1);だろ?
0225デフォルトの名無しさんNGNG
>> 222
ネタでしょ

>> 223
Q = Q - (4*9-4-1);

0226たけ☆地球の王子♪NGNG
>>223
小学校からやり直せや
それとも小学生か?(稿
0227デフォルトの名無しさんNGNG
dummy /= 50;
ここで整数除算して桁落ち(0.0〜とかではなく、0としか入らない)、
小数点以下が切り捨てられてデータが残らない。
つまりdummyに0が入ってその後に、別のところでキャストしても0は0(復元不可能)。
0228デフォルトの名無しさんNGNG
>>226
小学校じゃ習わないぞ(ワラ
0229たけ☆地球の王子♪NGNG
>>228
*から先に計算するって事は小学校で習いますです。はい。
0230デフォルトの名無しさんNGNG
>>229
問題はそこじゃない。
a-=bはbを先に計算してからaから引く。
0231デフォルトの名無しさんNGNG
>>224, >>225, >>226
ありがとうございました.
まるで気がつきませんでした.
0232223NGNG
すみません, 途中で間違って投稿してしまいました.

なぜ Q = 10 になるのでしょうか ? なんで ?
コンパイラのバグですか ?
0233デフォルトの名無しさんNGNG
(4*9-4-1)=31
0234デフォルトの名無しさんNGNG
もうちょっとマトモなネタキボーン
0235デフォルトの名無しさんNGNG
int i;
for(i=0;i<10;i++) ;

無限ループになります。なんで?
コンパイラのバグですか?
0236デフォルトの名無しさんNGNG
>> 235
それはコンパイラのバグ

そういやIntelのコンパイラで
short i,j;
for(i=0;i<10;i++)
{
for(j=0;j<10;j++)
{
printf("%d%d\n, i,j );
}
}
とやると、外側のループが1回しか実行されないバグがあったな
0237デフォルトの名無しさんNGNG
>>235
無限ループならコンパイラのバグです。
もうちょっとマトモなネタキボーン
0238デフォルトの名無しさんNGNG
>>236
Intelだめじゃん!
0239デフォルトの名無しさんNGNG
ハード屋がつくるソフトってだめね。
Sunのあれとか。
0240デフォルトの名無しさんNGNG
>>236
short で、インクリメントできないってこと?
0241236NGNG
>> 240
いや、2重ループが実行されない。
int なら平気。
0242デフォルトの名無しさんNGNG
short使う人の性格にバグが。
0243デフォルトの名無しさんNGNG
>>239
ソフト屋の作るソフトも人のことは言えないと思うが...
0244デフォルトの名無しさんNGNG
>>204
意味がよくわからんが、
とりあえずFindFirstFileでも使っとけ。

>>216
まずはCランタイムのヒープ管理ルーチンとよく相談しろ。
OS側の話はそれからだ。
0245236NGNG
>> 242
俺は使ってねーよ。
コーデック系のプログラムだと、作ってんの学者だから
訳わかんねー事やってんのよ。
変数や関数名も数式のまんまだし。
0246デフォルトの名無しさんNGNG
unsigned intをunsignedと略すのはやめた方がいいですか?
0247246NGNG
というのもlong intは略してもunsigned intは略さない人が多いみたいですから。
面倒な人はtypedefでもするんでしょうが。
0248デフォルトの名無しさんNGNG
>>246
かまわん。
俺個人的にはuintでtypedefする方が好みだが。
0249デフォルトの名無しさんNGNG
>>246
intぐらい書いたほうがいいと思う。
0250248NGNG
>>249
その理由を教えてくれ。
0251246NGNG
>>248-249
うー、、、どっちにすべきなんだろう・・・・
typedefがベストですか?uintなら誰でも分かりそうですし。
0252248NGNG
>>251
いや、俺はunsignedでもかまわんと思う。個人的な好みを言っただけ。
0253246NGNG
じゃあ今まで通りunsignedでいきます。
0254246NGNG
礼を忘れました・・・
ありがとうございました。
0255デフォルトの名無しさんNGNG
>>236
以前無限ループになってしまって原因がわからなかったのですが、これもコンパイラのバグだったんですね。
もっとちゃんとしたコンパイラ買わないとだめかな。

unsigned char counter;

for(counter = 0; counter < 300 ; counter++) {
処理
}

0256デフォルトの名無しさんNGNG
>>255
コンパイラ何つかってんの
0257デフォルトの名無しさんNGNG
もうネタはいいよ
せめて、ちょっとマシなやつにしてくれ

void f( unsigned int i )
{
if ( i < -1 ) printf( "i<-1\n" );
}
int main()
{
f( 1 );
}
とか
0258デフォルトの名無しさんNGNG
「unsigned char が300まではないだろ」
って言ったら、
「俺のコンパイラはcharが9ビットなんだよ」
って返される見え見えのオチだな。

もうちょっとマトモなネタキボーン
■ このスレッドは過去ログ倉庫に格納されています