08/11/15 05:04:45
C言語の入門者向け解説スレです。
教えて欲しいのではなく宿題を丸投げしたいだけなら
↓宿題スレ↓へ行ってください。
C/C++の宿題を片付けます 117代目
スレリンク(tech板)
・C++言語はスレ違いです。
・分からない事をなるべく詳しく書いて下さい。
・ソースコードを晒すと答えやすくなるかもしれません。
# 抜粋/整形厳禁、コンパイラに渡したソースをそのまま貼ること
# サイズが大きい場合は宿題スレのアップローダ等を利用してください
・開発環境や動作環境も晒すと答えが早いかもしれません。
・質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。
前スレ
C言語なら俺に聞け(入門篇) Part 38
スレリンク(tech板)
過去スレ
URLリンク(makimo.to:8000)
2:volatileな名無しさん
08/11/15 05:06:31
>>前スレ994
たとえば、次のようなコードを書いたとしよう。
a = b = 1 + c;
これをコンパイルして実行したとして、コンピュータの中でどういうことがおきるか。
コンピュータは、まず「1」を評価する。
この「評価する」というのは、「1」を整数の1であると認識して、
その整数値1をコンピュータが持っている小さな机の上に乗せることを意味する。
次に、「c」を評価する。
今度は、変数cの中に入っている値(仮に整数の2だったとしよう)を取り出して、
その値(仮に2)をさっきの1と一緒に机の上に並べる。
そして、今度は「1 + c」を評価する。
これは、いま並べて置いた整数値1と2を足して3という数を作り、
「1 + c」という式の値として、改めて机の上に置くことを意味する。
さらに、「b = 1 + c」を評価する。
ここで「1 + c」は3であることがわかっており、それは机の上にある。
そして「=」は代入するという演算子なので、変数bに整数値3を代入(コピー)する。
ここで、机の上の値3はなくなったわけではない。
この値は、「b = 1 + c」という式の値としてまだ残っている。
最後に、「a = b = 1 + c」が評価される。
上で書いたとおり、「b = 1 + c」は3として評価されているから、
変数bに値を代入したのと同様に変数aに3を代入する。
値3は、「a = b = 1 + c」の値として再度机の上に残されるが、
「;」が現れて「この文で行う作業は終わりです」ということになるので、
ここで残った値3は捨てられ、次のコードへと作業が移る。
3:volatileな名無しさん
08/11/15 05:07:34
つづき
同様に、以下の文の意味を考えてみる。
return N[i];
まず、「N」が評価される。
これは関数に渡されたポインタ変数の値で、たぶん配列の先頭を指していて、
そのポインタの値(配列のメモリ上での場所、番地、アドレス)が取り出される。
次に「i」が評価される。
これはもちろん、そのとき変数iに入っていた値が取り出される。
そして「N[i]」が評価される。
[]演算子は、ポインタの指している場所から整数値ぶん先の領域を参照するという意味なので、
コンピュータはN(の指している配列)のi番目の要素(変数)を見つけて、
その値を取り出し、「N[i]」の値として机の上に置く。
最後に 「return N[i]」が実行される。
returnは続く式の値を返すというキーワードであるから、その式の値、
ここでは「N[i]」の値、つまり今机の上に置かれている値が、
関数を呼び出した先に返される。
おわかりいただけただろうか。
4:デフォルトの名無しさん
08/11/15 05:54:24
>>2,3
ある程度わかるようになってから
そういう文みると
あーわかりやすね
って思うのだけれど
プログラミング始めたうちは言ってることが電波杉てわからないんだよね
5:デフォルトの名無しさん
08/11/15 09:24:33
「評価する」「式の値」「副作用」というキーワードを理解していただける手っ取りはやい方法はないものでしょうか?
printf("%d\n", 1 == 1);
はどうですか?
6:デフォルトの名無しさん
08/11/15 09:28:11
コンパイルして実行したとして・・・という感じではないなあ。
実際には CPU の仕様とか最適化とかが影響してくるわけだし。
C の文法を理解する方法としてはそれで全く問題ないんだが。
7:デフォルトの名無しさん
08/11/15 09:34:29
評価する=計算する・実行する
式の値=計算結果
副作用=状態変化
8:デフォルトの名無しさん
08/11/15 12:47:58
関数型言語教えた方がはやい気がしてきたな
9:デフォルトの名無しさん
08/11/15 13:42:12
>>8
簡単に覚えられる関数型言語って何?
10:デフォルトの名無しさん
08/11/15 14:08:24
評価っていう概念は初心者には敷居が高いと思う
前スレ見るに、
return N[i];
で 配列Nのi番目という、N と i の2つの情報が返る
と思ってるように見える。
そうじゃないよと。その配列の値ひとつ(数値なら数値ひとつ)が返ると。
って説明がわかりやすいかと
11:983,994
08/11/15 14:09:14
>>984 前スレ
大学で聞いた.
>>988 前スレ
勘違いしていない.
大学で>>983 と習ったんだよ.もしかしてうちの准教授がおかしいのか?
>>990 前スレ
今GCC使ってるんだが,コンパイラによって挙動が異なるはずだから,
C90だのなんだのって話をしたんだ.
準拠してるコンパイラならどれ使っても大丈夫なのかが知りたいんだ.
もし環境依存の事実を覚えてしまうと今後面倒なことになるから.
>>993 前スレ
>>常に確実であることが保障されている。
そうだったのか.
12:983,994
08/11/15 14:17:40
>>2,3
なるほど.よくわかった.
小さな机ってのは,多分アキュムレータのことだよな?
アセンブラの方を思い出して想像してみるとよくわかった.
大学で
関数のreturnにはstaticな変数を用いろって話だったんだ.
理由は前スレ>>983で書いてる通り.
それであんな質問をしたんだが,return文は引数と同じで値渡しでOK?
さっきから皆ポインタがどうとかって言ってるけど,それはこういうことだよな?
char *func4(char *a,*b) {
static char s[50];
sprintf(s,"%s%s",a,b);
return s;
}
例なのでバッファオーバーランの話はなしで.
もし.sをstaticで宣言してなかったら,
sのアドレスは正しく返るけど,返したアドレスが指すところはいつ書き換えられてもおかしくない.
ということだよな?
return文が値渡しってのは,みんなどこで知ったんだ?
仕様書とかに書いてある?
13:デフォルトの名無しさん
08/11/15 14:20:10
あまりに当たり前すぎて仕様書に書いてあるかどうかなんて気にした事なかったな
14:983,994
08/11/15 14:21:35
>>10
つまり値渡しってことだよな?
どうも大学で変な知識を植え付けられたらしい.
困った大学だOrz
15:デフォルトの名無しさん
08/11/15 14:22:13
仕様書にはちゃんと書いてある。
俺が知ったのはKnRでだが。
まあ、ほとんどの解説本にも書いてるだろう。
16: [―{}@{}@{}-] デフォルトの名無しさん
08/11/15 14:24:33
関数に渡す引数と、関数が返す戻り値をごっちゃにするなって。
値渡しだなんだのは前者の話だろう。
なんだって後者の話で出てくるんだ。
17:デフォルトの名無しさん
08/11/15 14:28:30
マイナスの実数を扱う変数型ってなんで無いんですか?
18:デフォルトの名無しさん
08/11/15 14:31:53
float, double
19:デフォルトの名無しさん
08/11/15 14:32:06
C言語で言う構造体とC++のクラスって似たようなもん?
20:デフォルトの名無しさん
08/11/15 14:36:50
ある側面で見ると似てるね。
ずいぶん拡張された構造体として扱えば最初は楽なんじゃない
21:デフォルトの名無しさん
08/11/15 14:41:32
>>18
float は 10^-45 ~ 10^38 ってかいてあったんですが・・・
22:デフォルトの名無しさん
08/11/15 14:44:12
符号ビットもあるよ
23:デフォルトの名無しさん
08/11/15 14:45:47
>>11
>もしかしてうちの准教授がおかしいのか?
いわれることが正しければ、そういうことになりますね。か な り お か し い。
24:デフォルトの名無しさん
08/11/15 14:47:27
浮動小数点を実装するに当たって符号ビットをもうけなければならないという制限ってあるのかな。
ないなら別にそういう処理系があってもいいんだろうし、そういうふうに
書いてあったとしてもおかしくはないだろうね。
普通は符号ビットあるとおもうんだけどさ。
25:デフォルトの名無しさん
08/11/15 15:06:56
浮動小数点のビット表現の標準規格があるから
大体の処理系はそれに準拠してる。
IEEEなんたらでぐぐれ
26:デフォルトの名無しさん
08/11/15 15:09:54
>>25
IEEEなんたら の検索結果 約 17,800 件中 1 - 10 件目 (0.27 秒)
なんたらじゃわからんwww
IEEE754だな
27:デフォルトの名無しさん
08/11/15 15:12:58
>>12
>小さな机ってのは,多分アキュムレータのことだよな?
>アセンブラの方を思い出して想像してみるとよくわかった.
早合点するやつはそれ以上学べないぞ。
小さな机はレジスタとか、あるいはスタックもありうるな。
アキュームレータはねえよ
28:デフォルトの名無しさん
08/11/15 16:35:25
>>24
ISO/IEC9899:1999(E) 5.2.4.2.2 Characteristics of floating types <float.h>
によれば、浮動小数点型は負数が表現できなければならないことになっているが、
符号ビットという実装を義務づけている記述は見あたらない。脚注 16 もそう読める。
29:デフォルトの名無しさん
08/11/15 17:24:36
>>27
いや、load/store を指示可能な(外部からレジスタと同等に扱うことのできる)アーキュムレータ、というのもありまして。
30:デフォルトの名無しさん
08/11/15 17:27:07
>>16
そりゃ、関数呼び出しで参照渡しの返り値が可能な言語処理系もありますし。
31:デフォルトの名無しさん
08/11/15 17:34:23
>>28
なるほど。C99ではそうなっているということですよね。
ありがとうございました。
32:デフォルトの名無しさん
08/11/15 17:37:54
>>30
ここは C スレ
33:デフォルトの名無しさん
08/11/15 17:46:29
>>12
仮引数もそう書けと習ったのか?
返却値の話もろくに聞いていなかっただけだろ
malloc による文字列操作に至っては授業を欠席していたようだな
適性ある奴と同じ行動とってるとひでえ目にあうぞ
34:デフォルトの名無しさん
08/11/15 18:16:16
ちょっとトンチンカンな質問かもしれませんが
int n=0;
ong t;
while(n!=100){
time(&t);
printf("%f\n",t);
n=n+1;
}
とやるとtの値として100個とも全く同じ値が出てくるのですが
これはプログラムを走らせてる最中全く時間が経過してないということなんでしょうか・・・?
35:12
08/11/15 18:16:49
>>15
昨日調べようとおもって,図書館いったら誰かが借りてて見れなかったんだ.
今度本屋で立ち読みしてくるよ.
>>16 >>32
返すときも,値渡しなのかどうかって話.>>16のいうとおり,話がごっちゃになってきてるが,俺はCの返り値が参照渡しなのか,値渡しなのかがわからなかったからこういう質問をしてしまったんだ.
ここがCのスレだからCの返り値について質問してるんだ.
>>27
アセンブラの授業だと,スタックに入ってるデータをアキュムレータに入れないと足し算も出来なかったんだがなぁ.どうしてもアキュムレータに入れないといけないのかを聞いたら,出来る事は出来るが,遅いって言われた.
36:34
08/11/15 18:16:58
すみません ong は long の間違いです
37:12
08/11/15 18:18:11
>>33
授業は全部出てるしちゃんと聞いてる.
今回のreturnについては変だったから准教授にも聞いたんだ.
そしたら
double normalize(double th) {
while(th > PI) { th -= PID; }
while(th <= -PI) { th += PID; }
return th;
}
はだめで,
double normalize(double th) {
static double out;
while(th > PI) { th -= PID; }
while(th <= -PI) { th += PID; }
out=th;
return out;
}
としろって話だったんだ.
> 引数 th が関数に渡されるときに関数内部では別の変数が用意されて,その変数
> にコピーされます.この関数内の変数は当然 static ではないはずですので,
> return によって正しく返却されることは保証されないと思います.ですから,
> やはり static 変数を別に用意してください.
> なお,数式の評価値も正しく返却されるのか不安なので,私は static 変数に代
> 入してから return しています.たとえ仕様上は保証されていてもバグがあるか
> も知れないので,こうすれば安心です.
とのことだった.
仮引数の書き方はとくに指示されてはいないし,malloc による文字列操作どころかmallocはまだ名前以外出てきた事がない.
仮引数の書き方に適切なものがあるなら是非教えてくれ.
38:デフォルトの名無しさん
08/11/15 18:19:59
>>34
実行速度が速いから,1秒たつまでに終わっちゃうんだと思うよ.
100とするところを,1000000くらいにして試してみると,少しは変わるかも.
39:デフォルトの名無しさん
08/11/15 18:23:11
>>37
教授がなんか勘違いしてんだろうね。
仮引数の件
char *func4(char *a,*b) {
↓
char *func4(char *a, char *b) {
40:34
08/11/15 18:25:07
>>38
なるほどほんとだ。
ありがとうございます。
41:デフォルトの名無しさん
08/11/15 18:27:43
>>37
その準教授なり教授なりの返答はあまりにも稚拙だな。
あなたはstatic変数にしないと不安で仕方ないかもしれませんが、
私はそのようなことで不安になることもありませんし、メモリを浪費したくもありません。
とでも言っておけば?
42:デフォルトの名無しさん
08/11/15 18:31:11
追記。
仕様で保証されているものをバグだ何だと騒ぎ立てるんだったら
staticにすれば大丈夫なんていうのも保証はないし、
そもそもnormalizeにthが壊れずに渡されるかどうかも心配すべき。
ちょっとどうかしてるよ。
43:12
08/11/15 18:34:50
>>39
ですよね……
名古屋大出てるのにOrz
仮引数.
なるほど.次からちゃんと分けて書くようにするよ.
でもなんでそう書く方がよろしいんだ??
さっき,GNU libcを落としてきて,ソース漁ってみた.
printf.cのソースで,
int
__printf (const char *format, ...)
{
va_list arg;
int done;
va_start (arg, format);
done = vfprintf (stdout, format, arg);
va_end (arg);
return done;
}
ってなってたよ.次からいちいちstaticにするのはやめておくことにする.
44:デフォルトの名無しさん
08/11/15 18:42:23
printfで%lfで表示すると同じなのに、比較すると(if分で!=de)異なると
なってしまいます。片方は計算で得た5.0000、もう片方は5をdouble型に
入れたものです。
この二つをどうにかして同じ値として扱いたいんですが何かいい方法はないでしょうか?
45:デフォルトの名無しさん
08/11/15 18:44:20
日本語がおかしくてすみません
簡単に言うとif文の条件として二つの変数を比較するときだけ
小数点5桁とか4桁だけで比較したいんですがどうしたらいいでしょうか?
46:デフォルトの名無しさん
08/11/15 18:45:22
>>44
浮動小数点では単純に==で比較すると誤差で涙目になる。
適当に許容する誤差を決めて
#define EPS 1e-5
if(fabs(a-b) < EPS){//aとbが等しいなら
}
みたいにやるのを薦める
47:33
08/11/15 18:50:37
>>37
それは失礼した
しかし痛い教授にあたったものだな、ご愁傷様
試験のときも教授と同じ間違え方をしないと減点されかねないから気をつけてな
48:デフォルトの名無しさん
08/11/15 18:50:50
ありがとうござます!!
49:デフォルトの名無しさん
08/11/15 19:00:53
>>35
一つ言っておこう
授業で習うことなんて8割方嘘だ
初心者向けにかなり誤魔化しが入っとるけん、
全部鵜呑みにせんと、概要だけふーんと聞いておけばいいよ
50:デフォルトの名無しさん
08/11/15 19:10:07
なぜ伊予弁
51:34
08/11/15 19:15:30
すみませんもうひとつ質問なのですが、
たとえばゲームとかを作る時、キャラクターを動かす部分のプログラムは、
「今xに表示しているキャラ画像を、○○秒後にx+10に表示する」
みたいになると思うのですが、
そもそもこの部分の処理に○○秒以上かかっちゃっう場合はどうするんですか?
52:デフォルトの名無しさん
08/11/15 19:19:07
>>51
動きがガクガクになる。
53:デフォルトの名無しさん
08/11/15 19:19:20
教授なんて名大を出ててもそんなものか。。。
かったるくて日進月歩に合わせられないんだろうな。
法科、会計、情報系は教授もリアルタイムに日進月歩しないと駄目じゃね?
古いままだと実態に合わなく使い物にならなくなるから。
54:デフォルトの名無しさん
08/11/15 19:25:07
>>51
タイマー割り込みの手法を使って、差分を計算してキャラを動かす。
キャラが増えて負荷が高くなったら、一部を間引いて処理する工夫を入れるか
タイマー間隔を延ばして処理する工夫を入れる。
55:12
08/11/15 19:25:23
>>47
俺は授業よりも,Cの本の方を重点的にやってるから,
今回の返り値の謎に気がついたからよかったけど,他の連中に返り値がどうのとかいうと,
「返り血」と思われてしまうよww
困ったもんだ.准教授といえども,間違うってことか.
そう言えば,scanfのフォーマットで[]とか*とかもしらなかったもんな.
そんなもんなのかな?
>>49
准教授の授業3割,本4割,libcとかのGNUのソース2割,どっかのサイト1割くらいで参考にしてるから,
それは大丈夫だと思いたい.
質問の結論は返り値は値渡し.
みんなありがと.ずっと変なソース書き続けるとこだったよ.
聞いてみてよかった.
56:デフォルトの名無しさん
08/11/15 19:34:09
>>37
誰か指摘してたが、関数内で不用意に性的変数を
参照するのは避けるべき
なぜなら再入可能でなくなるから
つまりマルチスレッドで同時にその関数を使用すると不具合が起こる
要はマルチスレッドプログラミングも
したことない助教授は明らかに素人なので
気をつけろってことさ
57:デフォルトの名無しさん
08/11/15 19:36:24
人員不足で担当させられてるだけの門外漢だったりして
58:デフォルトの名無しさん
08/11/15 19:38:06
なんという痛み分けw
59:34
08/11/15 19:40:46
>>52
なるほど・・・
>>54
なんかよくわかりませんがいろいろ解決法があるのですね。
調べてみます。
60:デフォルトの名無しさん
08/11/15 19:40:48
>>55
つかさーアセンブラやってんなら返り血を
渡すコードがどうなってるか見てみるといいぜ
返す型でも変わるし
61:デフォルトの名無しさん
08/11/15 19:51:26
しかしこの返り値クンは、なんやかんやと言い訳ばかりでむかつくなw
後から伸びないタイプだわw
62:デフォルトの名無しさん
08/11/15 20:02:13
管理職タイプ
63:デフォルトの名無しさん
08/11/15 20:09:43
>>61
それはどうでしょうか。
>>55
こちらで返り血を浴びながら修練するのも一興
スレリンク(tech板)