C言語なら俺に聞け 143
■ このスレッドは過去ログ倉庫に格納されています
>>167 のリンク先を読んだのだが…
printfで色々条件、最後が改行だったらputsに置き換え、は分かったけど
最後が改行でない場合はfputs( , stdout)に置き換えるわけにいかんのじゃろか? stdoutがフラッシュされるタイミングが改行だから拙いんじゃね PC で組むなら、たいした問題にならないリソースの心配よりも、
統一して見やすいように気を使うべきだろうね。 fputs(
"文字列1\n"
"文字列2\n"
"文字列3\n"
, stdout
); みなさんありがとうございます。
末尾の改行程度しかないprintfはputsに置き換えられるんですね。
ググってみたりもしたんですが、最近のPCであれば速度にほとんど違いが出ない様なことも書いてありました。
171さんの言う通り速度やリソースよりも見やすさや読みやすさの方が大事になりそうですね。
勉強になりました。 塵も積もれば何とやらで
すぐ砂時計だの輪っかだのになるのが
M$の作風 入力が入れる前に厳密にされてないとprintfは怖くて使いたくないなエラーになるし
プログラミング問題とかなら入るの制限されてるから使う時もあるけど 自動で実行ファイルが作成されてその実行ファイルが新しく実行ファイルを作ってその実行ファイルが…
みたいな無限増殖するウイルス的なやつって理論上作れるの?
作る気はないがファイル名を自動で生成して上書きするようしていったら全ファイルが空ファイルになるってのも可能なのか? >>177
GetModulePathName+CopyFileで誰でも作れる。違法。 >>177
全ファイルが空になるというのは、イカタコウイルス。可能だが違法。 やり方は直接は教えられないから、Win32APIスレで個別の処理のやり方を細かく質問するといい。 プログラミング全体に言えることだがreturnがよくわからない
戻り値とかはなんとなくわかる
戻り値を表示するわけだからprintf要らずなわけ? >>177
fork() してプロセス作るの繰り返すだけでいいのでは?ファイル作る必要あるか?
作ったとしてもそのファイルの内容は元のやつと同じなんだろ?
Windows の場合はどうするか知らない。fork() と同じような動きをするAPIがあるなら
それ使えばいい。(cygwinのライブラリ使えばいいか) >>183
君は return を何か別のものと勘違いしてはいないか? >>183
何か関数のコードをここに書いて、自分なりに説明してみ?
優しいお兄さんたちが説明のアラを指摘してくれるよ >>187
じゃホント適当なの
int main(void){
int a,b;
scanf("%d %d",&a,&b);
a=a+b;
return a;
}
適当に
基本自分はa=a+bの後の行にprintf("%d",a);って入れるけど戻り値を表示するだけならreturnで十分なの?って聞きたい >>188
main関数のreturnの値は0固定だろ。
正常に終了したかどうかを示す数値を返さないとダメなんだし >>188
それどこにも何も出力してないよ。一応 main() での return はプログラムを実行した側に
ステータスとして返されたりするがその辺はOSやmain()を呼ぶ側のコード依存だ。
で、それはプログラムの実行中で起きたエラーを伝えるためによく使われている。
0ならエラーなしで1ならエラーみたいに。つまり普通は計算結果を返すためには使わない。 >>189
0固定なの?
苦Cでmainじゃない関数で使ってたけど
よく分かんないな >>191
固定と言うか、昔からの慣習で普通は0返すように書くんだよ。UNIXでの慣習ね。Linuxでも同じ。
UNIXではシェルスクリプトで動かした時にエラーかどうかを判定するのに使うことがある。
(シェルの if 文等で直接使える。Windows のコマンドプロンプトでもほぼ同じ)。
0が返されたら正常終了で0以外がエラーね。
まあとにかく歴史的な問題でそうなっていると思って良い。そういう意味では main() からの
return だけは特殊なものだと思っていい。 >>188
return a; と書いても基本的にはaの値は表示されないよ。
returnは関数内で計算した結果を呼び出し側に返すだけ。
値を見たければprintf等を使って表示する必要がある。
呼ばれた関数内で(途中経過として)表示するか、
呼び出した側で(関数の結果として)表示するか、は目的次第だが。
main() はOS(WindowsとかLinuxとか)からコマンドとして呼び出される関数、
と考えると分かりやすいかも。
main() 関数のreturnの値はOSに返される。
返された値をどう扱うかはOS側の問題だわね。 return は表示装置に値を戻す(表示する)機能ではない >>191
「自作関数を作る」あたりのページで出てくるsum関数でしょ?
あれってただ単に今までmain関数で return 0 しかしていないから、例として同じように書いているだけだと思うよ。
「関数から数値を返す」のページまで行けば return num してるsum関数が出てくるよ。 print関数だけで表示するだけの関数とかならreturn0するけど衝突判定とかならbool型返したりするからな 自分が使っているPCなんかで、
処理を自動で行いたいなと思った時に、
それをC言語を使って実現出来るなら >>199
それ、OS固有のAPIの知識だらけで、Cがきちんと使える能力は測れない >>197
数年かけてLinuxカーネルを読破できたら コールバック関数の型宣言とか、
関数ポインタの扱いを難無く出来るか?
とかかな? p = p() で駆動するようなステートマシンで
自分のポインタを返す関数 と それを保持するポインタの宣言とか >>200
「きちんと」とか書いてない要件を作り込んでバグだらけのコードを量産する自称玄人乙 ポインタがわからないです
メモリのアドレスの最初を配列に入れて
呼び出すときそのアドレスの最初を読み込んでデータを引き出すということなんでしょうか? すいません
本当に無知なのでアドレスがよくわかりません
バカにもわかるように教えていただけると嬉しいです ポインタの説明で、何かに例えて説明しようとすると余計に混乱する宿命。 コンピュータの中には何百メガとか何ギガとかのバイト数のメモリがあって、
データ(数値や画像や文字列、プログラム自体も)はメモリに記憶されていて、
メモリには1バイトごとに連番のアドレスが割り振られている。
…程度のイメージなら現代じゃ誰でも共有してると思うんだけど。
女学生が携帯電話機を使ったり、子供がゲームをする時だって、
「メモリカードの容量が足りなくなった」とか言うでしょ。
それとも、容量としてのメモリ(どれだけ入れられるのか)は飲み込めても
アドレスという概念(どこに入ってるのか)になると飛躍が必要なのかな。 アドレスが住所の意味で、小人さんひとりひとりが住んでる場所を表してて、お手紙を出したりもらったりするのに使うんだよ?
でok? いわえる宅急便で品物の上に貼るあれよあれがないとどこに送れないか解らないっていうあれ RAMやROMにデータがどう書き込まれているのかイメージ出来ているのかな? >>211
本屋さんへ行って「C言語ポインタ完全制覇」って本を買って読もう
それが一番近道だと思う >>213
じゃあまあざっくりと集合住宅で例えるか
例えば char hoge; と宣言したとする
するとコンピュータは空いてる部屋を1つ、hogeのために割り当ててくれる
仮に部屋番号を301号室としようか
広さは四畳半のワンルーム
君はこの部屋に、'a' でも 'x' でも好きな文字を入れることができる
次に char piyo; と宣言したとする
そしたらやっぱりコンピュータは部屋を割り当ててくれる
部屋番号はhogeと別にしないと被っちゃうから401としよう
間取りは同じ、四畳半のワンルーム
君がchar型の変数を宣言する限り、広さは常に四畳半だ
更に、int foo; と宣言してみよう。
同じように部屋を割り当ててみるが、困ったことにfooは身体が大きくて四畳半に収まりきらない
これはfooがchar型ではなくint型だからだ
そこでコンピュータは隣の3部屋の壁を取っ払って、計4部屋分の広さにしてfooに割り当てる
最初に与えられた部屋番号を501とすると、fooは501,502,503,504の4部屋を占領することになる
このそれぞれの部屋番号が、いわゆるアドレスだ
つまりまずコンピュータに膨大な数の部屋が用意されてて、変数宣言や関数宣言などをするごとに適宜空いてる部屋を割り当てていく
そのときに割り当てられた部屋の部屋番号が、その変数なり関数なりのアドレスとなる
fooみたく複数のアドレスにまたがってる場合は、その先頭アドレス(今回でいうと501)がfooを指定する際のアドレスになる
変数名からその変数に割り当てられたアドレスを知るには、&を使い&hogeや&fooと書く >>213
一応考えてみた
アドレス= 住所だと考えて
どこでもドア = ポインタ変数そのもの
行きたい場所 = 参照先のアドレス
として
・自分の部屋にどこでもドアを置く = ポインタ変数を宣言する
この時のポインタ変数のアドレス(ドアの置かれてる場所)は自分の部屋
今はまだドアの向こうはどこにも繋がっていない
・どこでもドアの向こう側をしずかちゃんの風呂場にする = ポインタ変数の中身を参照先(しずかちゃんの風呂場)のアドレスに書換える
これでポインタ変数の中身(=ドアの向こう側)はしずかちゃんの風呂場と繋がる
・ドアを開けて風呂場を見る = *を付けてポインタ変数にアクセスする
・ドア自体がどこに置かれてるかを知る = &を付けてポインタ変数にアクセスする
ポインタの嬉しい点はわざわざしずかちゃん家に行かなくても自分の部屋に居ながら
どこでもドアを介して風呂場を覗く事が出来るので移動の時間が省けて時短になる ポインタを説明するときにアドレスで説明するのって、初心者による初心者向けの説明に多いけど
それはアドレスを知ってる人向けで、ここからさらにアドレスを一生懸命別の何かで
例えるのはかえって分かりにくいだけにしか思えない 喩えるんじゃなくてメモリそのものを教えたほうがいい >>211
マイコン小僧的な意味での理解が必要かもしれないなあ
ポインタ定義した時点で、コンパイラが「アドレスを入れるためのメモリ領域」なり
「CPUのレジスタ」なりを使うようにしてくれる
貴方が int* a = 300; とか書いたら、 コンパイラは300という数字をどこかに保存しておいてくれる
CPUのレジスタか、特定のメモリ領域かは処理系次第だが
で、計算やるってなったら「CPUの間接参照機能」を利用する
アセンブラ側で「間接参照機能を使え」って感じのコードを吐くのよ
そういうオペコードがある
で、間接参照機能を使った場合、CPUはメモリの内容を2バイトか4バイトか見るでしょ
CPUは「今読んだ数字はメモリの番地である」と判断して
CPU側でいてあるメモリ番地の内容を読み込む
で、読んだデータはコンパイラが吐いたアセンブラのコード次第だが
とにかくCPUには「ある数字をメモリなりレジスタから読み、次にそこに書いてた数字をアドレスと判断し、別のメモリアドレスを読む」って機能がある
それを使うのがポインタ
そんな感じ そんな間接参照なんてないです、って処理系もあろうが
Cコンパイラがアセンブラレベルで ご ま か し ま す
ってな話かと 眠い時に書くとろくでもねぇ文章になるわーすまん
とりま「CPUの間接参照」で調べてくれ、そっちのほうが早いかも知らん アドレスについては……
Q: たとえばここに 1 2 3 4 って数字があるとするでそ
二番目を起点にして、二つ指差してみて、起点は指差しの対象に含むよ
A: 指差す箇所を[]でくくると 1 [2] [3] 4 になるかと
そんな感じのテキトーさでいいと思います、これがただ例えば0x000F34824になるだけで アドレスはアドレスだろ。何にもたとえちゃいねーよ。まんまだよ。 なお、ポインタのだいたいの使い道は
・クソでかいデータを複数の関数で参照せなあかんとき(画像処理とか)に先頭アドレスだけ渡してあとよろしこって奴
・呼び出し「先」側でなんかセットアップしてもらわなあかんとき、Win32APIあるある
・関数テーブル(30だか50だか、個別に使う関数の先頭アドレスと、そこに飛ばす条件をペアにした配列があるの)
・無名関数もどきのことをやりたいとき、一部分だけ後付け処理やりたいんでそこだけjmpさせて戻る系の奴というか、sortみたいなの
のどれかやな、こんくらいの説明でいいんだろうか? イミフすぎて正直すまんかった コンピュータの内部構造をどの程度知っている人が相手なのかで説明方法を変えた方が良いように思う。 TTLロジックICでアキュムレーター組めるくらいなら…
…あ、多分説明自体不要かw 初心者は一度バイナリーエディタやメモリエディタを弄ってみることを進める・・・と無責任に言ってみる。 8bitマイコンみたいなやつだと説明は少し楽になるな。メモリ空間が64KBしかないし。
まあ昔はそれでもバンク切り替えして沢山メモリ使えるようにしていたが、考える上では楽だ。
今はメモリ空間も広大になってメモリブロック切り替えてアドレス変わるのは当たり前だったりして説明が面倒だ。 >>246
初心者相手なら論理アドレスで説明すればいいだけ
アドレス変換とかの説明はもっと後でいいだろ ポインタの前にアドレスが理解できないってどういうことよ…
アドレス=メモリ上の位置、だよ
例えば64kbのメモリを積んだ機械ならアドレスの全範囲は0x0000〜0xffffだが
そんなこと気にしなくても使えるようにしたから高級言語なのよ
int a;
int *pa;
としたとき、コンパイラはaとpaそれぞれを上記範囲の"どこか"に割り当てる
その"どこか"をaやpaという名前で呼ぶことにするよ、という宣言だから
ただし「変数は"どこか"のアドレスの別名である」ということを"利用"することはできる
pa = &a;
とすれば、paには「aの実際の場所(=アドレス)」が入り
*pa = 123;
とすれば、paが現在指しているアドレス、即ち「aの実際の場所」に123が入る お前らが箱とか部屋とか変なこと言いだすから初学者が混乱するんだろ。 ニモニック表片手にハンドアセンブルしてみろ
そうすりゃアセンブラやコンパイラがなにしてるか
馬鹿でもない限りいろいろ分かる 自分は二重ポインタってのが分からないです
アドレスの入るアドレスがあるなら
アドレスの入るアドレスの入るアドレスもあるんですか? アドレスを記録位置と言い換えてみたらどうだろうか。 メモリーを記録装置、メモリー上のバイトを記録素子、アドレスを記録位置。
どうだい。 変数の位置(アドレス)を示す変数 = ポインタ
そいつ自体も変数だからアドレスを持ってるしポインタも持てる 記録位置の入った素子の位置が入った記録素子。
これなら有りえるとすぐわかる。 ■ このスレッドは過去ログ倉庫に格納されています