X



C言語なら俺に聞け 154

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん (ワッチョイ bf63-lB9F)
垢版 |
2020/01/14(火) 19:32:30.16ID:SgRnb4BR0
!extend:checked:vvvvv:1000:512
(新スレ立ての際上記コマンドを2行書き込んでください)
C言語の話題のみ取り扱います C++の話題はC++スレへ
質問には最低限の情報(ソース/コンパイラ/OS)を付ける
数行で収まらないソースは以下を適当に使ってURLを晒す
https://paiza.io/
https://ideone.com/
http://codepad.org/

C11
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1570.pdf

C99
http://www.open-std.org/jtc1/sc22/WG14/www/docs/n1256.pdf
http://kikakurui.com/x3/X3010-2003-01.html

C FAQ 日本語訳
http://www.kouno.jp/home/c_faq/

JPCERT C コーディングスタンダード
https://www.jpcert.or.jp/sc-rules/

※前スレ
C言語なら俺に聞け 153
https://mevius.5ch.net/test/read.cgi/tech/1566050562/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
0802デフォルトの名無しさん (ワッチョイ 07b3-wl64)
垢版 |
2020/05/04(月) 19:26:17.85ID:nMCshN110
差が大きいか小さいかなんて中身によるだろ

ほとんど何もしない関数で
関数として実装されて
ループの中にあれば
差が大きいこともある

構造体の方が速い事もあるし
直接の方が速い事もある

とりあえずはきれいなコードで作っておいて
パフォーマンスが問題だとわかった時点で対策すれば良い
おそらく今回の部分は99.99%気にしなくて良い
0804デフォルトの名無しさん (ワッチョイ 07b3-wl64)
垢版 |
2020/05/04(月) 19:34:24.84ID:nMCshN110
同じコードでも周りのコードによって時間が大幅に変わる事があるので注意

例えば関数がインライン展開されてたものが
全然関係ない所からのコールが追加されただけで
関数コールに変わったりする

また、
結果を使わないただの時間測定コードだと
関数コール自体消される事も良くある
0805デフォルトの名無しさん (ワッチョイ e7ca-Rrpt)
垢版 |
2020/05/04(月) 21:14:13.28ID:7/M++IMa0
最適化しててもアセンブラソース吐かせて比べてみると勉強になると思う。
いやむしろ最適化してる時こそアセンブラソース吐かせて確認するのがいいかも。
勝手にインラインになってたり処理が省略されたりするしね。
0806デフォルトの名無しさん (スフッ Sdff-h83k)
垢版 |
2020/05/04(月) 21:45:58.62ID:GSMTfSohd
最適化なしでリリースすることはあり得ないのだから
当然測定もチューニングも最適化オプション込みででやるべきだし
O0オプションで吐いたアセンブラなんて見ても無意味
0808デフォルトの名無しさん (ワッチョイ e7ca-Rrpt)
垢版 |
2020/05/04(月) 22:11:38.30ID:7/M++IMa0
あぁ、呼出規約についての勉強のつもりだったから最適化無しを想定したけど、
ベンチマークみたいなコード書いてるんだろうからそもそも処理が残ってるかの確認とかの意味で最適化時のを見た方がいいと書いた。
0809デフォルトの名無しさん (ワッチョイ e7ca-Rrpt)
垢版 |
2020/05/04(月) 22:11:58.28ID:7/M++IMa0
あぁ、呼出規約についての勉強のつもりだったから最適化無しを想定したけど、
ベンチマークみたいなコード書いてるんだろうからそもそも処理が残ってるかの確認とかの意味で最適化時のを見た方がいいと書いた。
0814デフォルトの名無しさん (ワッチョイ 5fbd-NlPP)
垢版 |
2020/05/04(月) 22:55:41.14ID:nUxpSn1T0
初心者です。
ポインタの理解を深めるために、visual studioのデバッグで、変数の値をウォッチしています。

例えば、
FILE *src;
  fopen(〜10byteのファイルを開く〜)
fseek(fp, 0L, SEEK_END);
printf("%s は %ld byteです.\n",filename, ftell(fp));

こんな感じの命令をやった時に、*fpとかfpとか&fpの変数を観察してみたのですが、
値がピクリとも変化していないのに、ftell(fp)を使うとちゃんと10byteと表示されるのです。
fsekkの時点でfpは変化していると思いますが、どのようにウォッチすれば良いのでしょうか?
ftellはfpのなんの変数を見ているんでしょう…。。
0815814 (ワッチョイ 5fbd-NlPP)
垢版 |
2020/05/04(月) 23:00:16.50ID:nUxpSn1T0
>>814
× FILE *src;
○ FILE *fp;
だめですね。ごめんなさい。
0816◆QZaw55cn4c (NZ 0H9f-4Tsz)
垢版 |
2020/05/04(月) 23:15:21.86ID:7QD1dgDVH
>>814
FILE *fp はポインタですから、fp の指す位置は変化しません
fseek() で変化するのは、fp が指した先の領域(struct FILE 構造体)の中にあるパラメーターであって、fp 自体は変化せず同じ位置を指したままでいます。
0818デフォルトの名無しさん (ワッチョイ df47-ts7H)
垢版 |
2020/05/04(月) 23:20:08.53ID:Fiop0J3e0
>>814
FILE構造体が直接情報を持っているとは限らず、さらにポインタを多段に経由したり
OS管理のファイルハンドル・ファイルディスクリプタなどの先に情報がある可能性もある。

そもそも構造体メンバが規定されていないのでウォッチで何も見えなくても不思議は無いよ。
0820デフォルトの名無しさん (ワッチョイ 5fbd-NlPP)
垢版 |
2020/05/04(月) 23:26:28.97ID:nUxpSn1T0
>>816
ありがとうございます。fp自体は変化してなかったのですね。
FILE構造体の中に現在値を示す変数があるのだと思い、fp.posみたいなことを試してみたのですが、
よくわかりませんでした。(_Placeholderとかいうのしかなさそうでした。)

struct FILE構造体の中身の値の変化を、ウォッチ機能で観察することは可能なんでしょうか?
0821◆QZaw55cn4c (NZ 0H9f-4Tsz)
垢版 |
2020/05/04(月) 23:35:10.05ID:7QD1dgDVH
>>818
OS 側ファイルディスクリプタが FILE に記されることはあっても、
シーク位置を OS とで共有するのは難しいのではないでしょうか?
0822デフォルトの名無しさん (ワッチョイ 5fbd-NlPP)
垢版 |
2020/05/04(月) 23:35:26.33ID:nUxpSn1T0
>>818
ありがとうございます。
もっと上位(OSレベル)でやり取りされてる情報であるから、下位(自作プログラムレベル)からでは観察できないってことですか…

>>819
ありがとうございます。
FILE構造体の中に、_ptr(現在値)や_base(先頭アドレス)があると聞きました。
なので、fp._ptrとかを試しましたが、何も見れませんでしたね。

自分で定義した構造体の中の変数は観察することができるのに、なんでFILE構造体の変数は観察できないんだって、
不思議に思ってました…。
0823デフォルトの名無しさん (アウアウウー Saab-dhD/)
垢版 |
2020/05/04(月) 23:50:07.56ID:29dvD9qia
>>817
俺は以下のようなことを繰り返して段階的に複雑なケースを理解していったよ。
まずは入門書で基本的な概念を理解する。
実際にコードを書いて、様々な型の変数、配列、構造体やその要素に対して&演算子を適用してアドレス値を取り出して、対応する型のポインタに入れる。
ポインタが格納している値、ポインタが指している先に格納されている値をprintfで表示して確認する。
ポインタをインクリメント、デクリメントしたりしてポインタ自体の値の変化やポインタが指す先の値が何なのかを確認する。
一段階のポインタが理解できてきたらポインタのポインタなど多段階の間接参照を試してみる。ここでもまたポインタの演算を様々に試す。
値が予想とは異なるものだったり、型が違うとコンパイラに指摘されたりしたら、やはり絵を描いてどこがどう違っていたかを考えてみる。
何かを理解したら、更にここをこうしたらどうなるのかという疑問が色々沸いてくるのでそれらも逐一コードを書いて試していく。
慣れてくれば多次元だったりconstや関数ポインタなども含めて複雑にネストした宣言もシンプルなルールが再帰的に組み合わせただけのものというのが腑に落ちて理解できてくると思う。
0824デフォルトの名無しさん (ワッチョイ e763-ts7H)
垢版 |
2020/05/04(月) 23:51:26.90ID:GsKQPEDp0
FILE構造体でアクセスした場合は、直接ファイルを操作するというよりも
バッファリングしたデータへのアクセスと考えた方が良いかも知れません

実際のファイルはファイルディスクリプタというOSの仕組みの中で操作してます
0826デフォルトの名無しさん (ワッチョイ df52-dhD/)
垢版 |
2020/05/05(火) 00:00:45.59ID:J1ERvQ2q0
>>822
FILE構造体の内容は仕様で規定されていないから、使用するライブラリ等の実装で決められていてユーザ側が知ることはできないし知る必要もない物だよ。_ptrとかがあるという話も、とある実装ではそうなっているということ。
そもそものポインタの理解を深めるという目的なら、FILE構造体の中身はこれ以上深入りする必要はないね。
FILE構造体は初心者が真っ先に触れるものの一つだけどちょっと特殊な存在だね。
0827デフォルトの名無しさん (ワッチョイ 7f61-IRNk)
垢版 |
2020/05/05(火) 00:06:58.87ID:NEWGqmtJ0
FILE構造体の中身は標準ライブラリの実装によって違うんだから深追いしても無駄なだけ
FILE *fp;はそもそもfopenで帰ってきたものを他のファイル操作関数に渡すだけの使い方しかしないんだからポインタを理解する教材に向いてない
0829デフォルトの名無しさん (ワッチョイ e77b-kZrw)
垢版 |
2020/05/05(火) 05:40:45.15ID:ifa9JNiv0
構造体 FILE は普通はポインタの形でしか使わないから
ユーザーが見るヘッダではopaqueかも知れないしね正ちゃん。

>>817
「ポインタ変数には“変数のアドレス”が記録される」っていう
素朴な理解でしばらく進められないかな。
&a は「変数aのアドレスを得る」
*p は「ポインタ変数pが指しているアドレスから内容を取り出す」
0830デフォルトの名無しさん (ワッチョイ bf8c-Sf3c)
垢版 |
2020/05/05(火) 06:30:19.59ID:nQMNje/J0
初心者は最初にシェルスクリプトでプログラムを固めた方がいいよ。
0832デフォルトの名無しさん (ワッチョイ c7e3-4AVG)
垢版 |
2020/05/05(火) 07:45:39.83ID:q3hMRGAJ0
コメント失礼します
年収200万、一年ごとに5%上がりさらに10万円あがる20年後の給料は?と言う問題と、2時間格闘したのですが全くわかりません。
whileを使って何度やってもエラーが出ます
0835デフォルトの名無しさん (ワッチョイ c7e3-NlPP)
垢版 |
2020/05/05(火) 08:38:22.00ID:q3hMRGAJ0
>>832
(repl):3: syntax error, unexpected '=', expecting end-of-input
x*1.05=+100000
こんなのが出ます
0845デフォルトの名無しさん (ワッチョイ c7e3-NlPP)
垢版 |
2020/05/05(火) 13:25:50.40ID:q3hMRGAJ0
>>843
わざわざ丁寧にありがとうございます!
0846デフォルトの名無しさん (ワッチョイ dfa5-fzHW)
垢版 |
2020/05/05(火) 13:36:18.22ID:JDagEH9a0
FILEは紙テープ時代の仕様を引き摺ってるからね
しょうがないね
0853デフォルトの名無しさん (ワッチョイ 5fbd-NlPP)
垢版 |
2020/05/05(火) 18:12:23.92ID:ekADkGWO0
なぜ、fopenは"fp"でポインタ受け取り、fopen_sは"&fp"でポインタを受け取るのか分かりません。
定義?を見て、見極める方法はありますか?

fopen_sの定義に、引数として"FILE** pFile"を指定されているとこに、"&fp"が入るのは何故ですか?
他の命令でも*fp、fp、&fpのどれを入れるのか判断がつきません…。

<プログラム例>
FILE *fp
fp=fopen("aiueo.txt","rb");
fopen_s(&fp,"aiueo.txt","rb") …★

<fopenの定義>
errno_t fopen_s(
 FILE** pFile,
 const char *filename,
 *mode
);

語彙力が乏しいのでわかりにくくて大変申し訳ございません。
0857デフォルトの名無しさん (ワッチョイ 5fbd-NlPP)
垢版 |
2020/05/05(火) 18:42:13.15ID:ekADkGWO0
>>854-855
ありがとうございます。
以下の理解でよろしいのでしょうか?

(1)変数FILE* fpの場合
・"*fp"(FILE型?)
・"fp"(FILE*型)
・"&fp"(FILE**型)

(2)変数FILE**fpの場合
・"**fp"(FILE型?)
・"*fp"(FILE*型)
・"fp"(FILE**型)
・"&fp"(FILE***型)

変数に付ける"*"の数を増やすと、逆に型の"*"が減るのはなんか気持ち悪いんですね…
0859デフォルトの名無しさん (ワッチョイ 5fbd-NlPP)
垢版 |
2020/05/05(火) 20:26:30.94ID:ekADkGWO0
>>858
ありがとうございます。

型側と変数側で"*"を奪い合ってるイメージをすると覚えやすいかなと感じました。
int型:値そのものを入れるイメージ
int*型:値が格納されているアドレスを入れるイメージ(ポインタ)

int * p;
*p = 1; (1つしかない"*"を変数側に付けてしまったので、int型となり"*p"には値が入る。)
p=&hensu; (変数側に"*"を付けてないので、int*型となり、"p"にはアドレス番号が入る)
0860デフォルトの名無しさん (ワッチョイ df52-dhD/)
垢版 |
2020/05/05(火) 20:48:34.53ID:J1ERvQ2q0
>>859
覚え方は色々あると思うけど、俺は以下の方法がオススメ。

int i; → iがint型の値になる。iはint型の変数。
int *p; → *pがint型の値になる。
つまりpは*を付けてint型の値になる、すなわちp自信はint型を指すポインタ (=pはint*型の変数。)
0861デフォルトの名無しさん (ワッチョイ 2701-tcyL)
垢版 |
2020/05/05(火) 21:32:51.06ID:FuU+hT+R0
俺の覚え方はこうだな

&:メモリの位置(アドレス)を取り出す操作
*:メモリの位置に記録されている値を取り出す操作
型:値が格納されているメモリの幅を示す
  ※例えばint型は4バイトなのであるint型のポインターが0x0000を指していたら
   メモリの0x0000〜0x0031に格納されている値が対象となるデータ
   int型ポインターでなくchar型ポインターだとしたら
   メモリの0x0000〜0x0001に格納されている値が対象となるデータ
0863デフォルトの名無しさん (ワッチョイ 2701-tcyL)
垢版 |
2020/05/05(火) 21:43:41.89ID:FuU+hT+R0
>>861
*については2つ意味があるとして覚えているわ(この認識が合ってるのかは分からん)

変数宣言時の*の意味:宣言した変数がポインターであることを示す
それ以外の*:メモリの位置に記録されている値を取り出す操作

ポインター:メモリの位置を保存するための変数
ダブルポインター:(ポインターの)メモリの位置を保存するための変数
トリプルポインター:(ダブルポインターの)メモリの位置を保存するための変数
・・・・以下略
0864デフォルトの名無しさん (アウアウエー Sa9f-kSwD)
垢版 |
2020/05/05(火) 21:43:43.86ID:fevQ7qkha
fopen_s では、*fp を引数として参照渡ししてるからだよね、関数側で書き換えてもらうために
int i; を &i で参照で渡して、i を書き換えてもらうように、ポインタを渡して fopen_s で内容を書き換えてもらっている
0865デフォルトの名無しさん (ワッチョイ e7ca-Rrpt)
垢版 |
2020/05/05(火) 22:05:47.08ID:ZggaRwfV0
ポインタの覚え方もさることながら、型の修飾もどうだったかすぐ忘れるw
値を指し示す const ポインタなのか、const な値を指し示すポインタなのか、その両方なのか、それらの書き分けするのに毎回 google に聞いてる。
多重ポインタとか関数ポインタとか volatile なんかも組み合わされてくると、書けはしてももはや読める自信が無いw
0870デフォルトの名無しさん (ワッチョイ 6aad-48kr)
垢版 |
2020/05/06(水) 00:52:01.23ID:izcxg96Z0
>>822
FILE型についてはわざと中身を隠蔽していると思って良い。

オブジェクト指向の言語ならクラス変数が全てprivateになってるのと同じようなもの。で、そういう変数の読み書きは専用のメソッドを通して行う。
何故そうしているのかというと、外部から勝手に書き換えられたくないからだ。書き換えられると正常な動作を保証できなくなるということでもある。
0878デフォルトの名無しさん (ワッチョイ 268c-Ds/W)
垢版 |
2020/05/06(水) 08:39:08.38ID:yZWcrGyp0
>>859
C言語で2次元配列を動的に割り当てる4つの方法
もお薦め
0880デフォルトの名無しさん (アウアウエー Sae2-jgrQ)
垢版 |
2020/05/06(水) 11:10:31.35ID:q6Rk1GB6a
本来Cでは「二次元配列」と呼ばれないものまで
二次元配列の4種類!(キリっ)とか紹介するのは非常にまずいと思う
0881デフォルトの名無しさん (ドコグロ MM22-6mzC)
垢版 |
2020/05/06(水) 15:21:29.55ID:+SMDQMnPM
>>875
strcmp的とかよくわからんし、
>>779がCではなくC++を憶えないと理解できないコードがあるのか例示してくれ
と言われてもそんなものがあるなんて誰も言ってないから「ないけど、それが何か?」で終わる話なんだけどw
0882デフォルトの名無しさん (ワッチョイ ea0e-oySJ)
垢版 |
2020/05/06(水) 16:17:32.30ID:Ye566tnt0
>>881
では何故俺が792で「猫でもわかる」はCだと言ったことに対して
拡張子がcppだなどと絡んできた?

779 Win32APIを学ぶにはCとC++どっちを学ぶべき?
780 Win32APIはCだ(猫でものリンクを貼る)
786 むしろC++を知らないほうがいい、Cからやれ
795 「猫でもわかる」はCだ
796 C++のクラスを使ってない、拡張子はcppだ

この流れで「猫でもわかる」がC++だと主張してないとぬかすなら
アホは黙ってろ
0884デフォルトの名無しさん (ドコグロ MM8a-6mzC)
垢版 |
2020/05/06(水) 18:37:10.19ID:UHy6F9xlM
>>882-883
> C++のクラスとかを使ってないだけ
> そもそもサンプルコードのファイル名はsample01.cppとかだからC++としてビルドしてるし
と言う「事実」を書いてるだけだよw
C/C++の両方でビルドできるコードの存在を知らんのか?
0890デフォルトの名無しさん (ワッチョイ ea0e-oySJ)
垢版 |
2020/05/07(木) 08:31:41.78ID:Xvq6sZ7Q0
何も意図せずに「猫でもわかる」は拡張子がcppだと譫言をぬかすのは
ガキが何のボタンかわからんものを押しちまうのと同じ
自分が何をしでかしたか理解してない
0896デフォルトの名無しさん (ワッチョイ bb69-7oqX)
垢版 |
2020/05/07(木) 10:24:21.75ID:khGNNtcv0
f(x)=任意の数値 となる x を数値演算で探せ
g(x) = f(x) - 任意の数値 として g(x) = 0 となる x を数値演算で探す
※ 任意の数値が変数 x でも差しさわりはない f(x)-x = 0 となる x を探索する話に帰着

あとは >>894 の通り
ニュートン・ラプソン法なり 2分法なりで
■ このスレッドは過去ログ倉庫に格納されています