【初心者歓迎】C/C++室 Ver.103【環境依存OK】
■ このスレッドは過去ログ倉庫に格納されています
エスケープシーケンスやWin32APIなどの環境依存なものもOK
そのような質問は必ず環境を書きましょう
半角空白やタブでのインデントはスレに貼ると無くなります
コードを貼れる所
http://codepad.org/
https://ideone.com/
前スレ
【初心者歓迎】C/C++室 Ver.102【環境依存OK】
http://mevius.5ch.net/test/read.cgi/tech/1509780815/ 自己解決
MFCで、sleepという関数は使えませんでした
その代り、Sleepという関数が提供されていました >>501
MFCに限らず、UIスレッドの関数内で10秒もSleepで待つのはダメ。
そのウィンドウをユーザーが操作したら「応答なし」と表示されてしまう。
OnTimerで定期的に監視し続けるなり、
独自のメッセージを送って終了を通知するなりしないと。
もちろん、その間は
×ボタンを含めてすべてのコントロールを操作不可にしたり、
ユーザーが閉じられない別ダイアログをモーダルで出したりする対応も必要。 いまどきのSleepは他プロセスを止めたりはしないぞ 本来ダメなんだけどエクセルとかも盛大にUIスレッドで長期間マクロ実行したりするからね
数秒くらいならいいんじゃないの
金とってプログラム作ってる風でもないし >>506
Sleepで待ちたくなるということは、処理自体は
別スレッドなり別プロセスなりで動いているのだと思ったが 俺はメインスレッドでそのまま何かやってると感じたな
sleep の挙動を5ちゃんで質問する人がすでにワーカスレッドを使ってるとは全く想定しなかった 本人解決したと言ってるのにいつまでもマウント取りたがってんじゃねーよ なんかえらい反感買っちゃったな
Sleep知らなくてもワーカスレッドは使ってるだろうという>>507の方が普通の感覚なのかな みなさん判りましたか
条件後出しするとこうなります tupleの要素取り出すときstd::get<>以外の方法ありますか?
tuple[index]みたいに取り出せたら良いんですけど テンプレート特殊化を使えば出来るけど、そういうのは汚いコードだね。 >>515
tuple の要素が char * だとして
std::vector<char *> vec;
int i = 0;
std::_For_each_tuple_element(t, [&h, &i](auto&& v){
printf("%d: %s\n", i++, v);
vec.push_back(v);
}); >>519
求めていたのはこれでした
ありがとうございます すごく初級の質問なんですが、
int * x =3;
auto y=*x;
としたときに、コンパイラがyの型をintと推測するのはなぜでしょうか?
ポインタのポインタになるので、最初の*でint型の変数のアドレスを示すことになるまでは分かるのですが、
その後の*でアドレスのアドレス?を指すことになるので、元のint型の値を指すのは違うように思えてしまいます。 x は 0x00000003をアドレスとして認識
y(*x) は int型アドレス0x00000003にある値を指す
アドレス(x)のアドレスを指す場合は &x になる 多分、変数yの型が省略されているから、
デフォルトのintと推定して処理しているのだろう >>522
ありがとうございます。
ということは*がついてる変数は、変数がアドレスのときはそのアドレスに収納されてる値を指し、変数がアドレスに収納されてる値のときは、そのアドレスを指すという理解でよろしいんでしょうか? >>525
違うよ。
型名の一部としての*と、式の中の演算子としての*が別物だと言うのは分かる?
1行目の方は「intをさすポインタ」という型を表すためのもの。
2行目は「xというint型の変数の値に対して、その値が指しているメモリ領域上にあるint型の値を参照する」という演算を行うというもの。 この変数はポインタです 宣言の *
ポインタで指している先の内容を得ます 式の * C++コードの部分を間違って読み込んだとか?
エンコードはEUC-JPだね Firefox だと右上メニューからエンコーディングで明示的に EUC-JP 指示で化け解消
(unicode にチェックが入ってたが、自動だとそっちに誤爆判別してた?)
Chrome での明示的なエンコーディング変更は拡張プラグインつっこまないとできないっぽい C/C++ のポインタの表現が分かり難いってのは確かにあると思う。
宣言のときも * は変数名の側にくっついているものと考えれば理解しやすいんじゃないかな。
int * x; と宣言したとき、 *x が int であるような x を宣言したことになる。 Cの頃は
int *hoge;
と書くことが多かったのに、
C++になってから
int* hoge;
と書く人が増えた。
悪い習慣だと思う。 Javaとかから入る人が増えたからかね?
その習慣はあかん。
ポインタは型じゃないから、例えば
int* a,b;
って書くとaは「int型のポインタ」で、bは「int型の変数」になる。 >>532
いや、そこらへんは C/C++ のおかしなところで、ポインタはあくまでも型だ。
その上で文法上は * は変数名の側と結合するの。
もういっそ
std::add_pointer<int> a, b;
のスタイルを普及させればいいんじゃないのかなーと思う。
C++ だとなるべくスマートポインタを使う習慣が出来つつあるから、
その記法とも一貫性があるし。 >>532
ポインタは型じゃないって言ったとき
じゃあなんて言うんだっけ
仕様でも厳密にはなんか型とは別のカテゴリとして扱われてたよな
仕様に詳しい人教えて 型変換は (型)式 と書くわけで型を単体で書く書き方はあるのに変数宣言は
型 変数[, 変数]...
じゃないからねえ
void f(void);
void (*f_ptr)(void) = f; // ふむ
void (*g_ptr)(void) = (void(*)(void)) f; // 関数ポインタ型の記法はこうか…
void (*)(void) h_ptr = f; // 型 変数で書いてみた→エラーかい!
みたいな 初期化リストで二次元配列を0で初期化したいときはどう表記したら良いですか? 初期値式リストの個数が足りない場合残りの要素は0で初期化されるので
int a[5][6] = {};
でok >>538
CやC++では、ゼロクリアされるのか。されないと思っていたが 初期化値リストをつければ足りないところは0で埋められる
付けなければ初期化されない
太古から変わらない仕様 あ、でも c だと空の初期化リストは書けないから {} じゃなく {0} にしなきゃダメか >>535
変数宣言の基本的な形式
型指定子 宣言子1, 宣言子2, …;
で言うと * は宣言子の一部ということになるが、
型指定子でないから型 (の一部) ではないというわけではない。
これは文法上の呼び名に過ぎず、
意味論的にはポインタは型の一部だよ。 視点の問題ではあるが宣言の構文上のポインタは型の種類ではなく入れ物の種類ともいえる
int *a, b;
は
int pointer a, int variable b;
を意味する省略構文であり意味論的に
variable:値をいれるもの
pointer:間接的に他の入れ物を指すもの
と区別されてると見ることもできる >>544
そういうのは単純なポインタ(foo*)の時にだけ通じる話で、配列や関数ポインタや引数込みでのそれらの再帰的な組み合わせとかも考えたら、きちんとBNFで理解して型の宣言の構文を定義通りに覚えるのが一番誤解がなくてシンプルだと思うよ。 >>543レスサンクス
自分でも調べてみた
手元のc99ドラフト版から適当に抜粋
declaration:
declaration-specifiers init-declarator-list ;
declaration-specifiers:
storage-class-specifier declaration-specifiers
type-specifier declaration-specifiers
type-qualifier declaration-specifiers
function-specifier declaration-specifiers
init-declarator-list:
init-declarator
init-declarator-list , init-declarator
init-declarator:
declarator
declarator = initializer
declarator:
pointer direct-declarator
pointer:
* type-qualifier-list
* type-qualifier-list pointer
宣言時の * は declarator なんやね構文としては >>535
詳しい人とかハードル上げられるとな。。。
プログラミング言語C売っちゃったから、厳密な仕様は記憶の彼方だが、ポインタは厳密なカテゴリ的にもポインタだったと思う。
ここからは私の解釈だが、ポインタはアドレスを入れる「変数」。
当たり前じゃんと言われればそうなんだけど、感覚的にも型というより変数って感じ。
ポインタに型があるとすればOSがアドレスを扱うビット数と同じになる。
intとかの型はポインタが指す先にどの大きさのどういう扱いのデータがあるかを知る為で、ポインタ型そのものの大きさは変わらない。
んで、普通の変数とポインタはCだと大分違うように思うけど、アセンブリ言語だと
LD GR0,TEXT ; 変数TEXTの内容を読む。
LDA GR0,TEXT ; 変数TEXTのアドレスを読む。
程度の違いしか無いわけね。
この場合、内容もアドレスもレジスタが読むけど、Cにレジスタに相当する変数を用意する為にポインタが生まれたんだと思う。 >>547
私の解釈? ポインタが生まれた理由?
なんでその内容を俺にレスしたのか意味不明 x Cにレジスタに
o CにLDA使用時のレジスタに carとcdrに付いて小一時間
こちらの方が先だべ >>538
ありがとうございます説明が足りなかったかもしれません
メンバ変数の配列をコンストラクタでリスト初期化する場合どうしたらいいですか?
Hoge::Hoge() : mPiyo(0) ←これの二次元配列版を知りたいのです >>551
同じだよ {} で初期化すればいい。
Hoge::Hoge() : mPiyo{} {
ほにゃらら
}
ってことね。 >>547
言語実装ベースの思い込みが過ぎる。
言語規格中のポインタは型だし、変数ではない値もあり得るし、ポインタの指す先の型の違いは大きさだけではない。
↓「ポインタ型」で検索して確認されたし。
http://kikakurui.com/x3/X3010-2003-01.html > void (*)(void) h_ptr = f; // 型 変数で書いてみた→エラーかい!
当然知ってると思うけど
void (*h_ptr)(void) = f;
これは * と () の優先順位が原因だ
よく * と [] で混乱してるひともいるけど
char **hoge;
char *hoge[];
char (*hoge)[123]:
char (*hoge)[]: // エラーかい! >>551
今では (C++11 以降では) 宣言時に初期化も書けるから、
struct Hoge {
int a[10][10] = {};
public:
Hoge(void);
};
って感じでも書ける。
複数のコンストラクタがあるときに、
どのコンストラクタが起動したときでも初期化はしないといけないみたいなときには、
この方式で書いた方が何度も同じことを書かなくてよいので面倒くさくなくて良いかも。 >>556
なるほど
コンストラクタにつらつら書くよりもヘッダで宣言時に初期化した方が綺麗ですね アセンブラとかから C に入門したら色々と自動化されてて
ありがたいなーってなってポインタで躓いたりしづらいけど、
レイヤが違うという意識を持ってないと変に機械の理屈に引きずられることもある。
言語の理屈だとポインタはアドレスを入れるものじゃなくて、
ポインタを値として見たものをアドレスと呼んだりもするってだけ。
結局はポインタにアドレスが入ってるんだけど、まずポインタありき。
ポインタに対する演算ってのは指す先をいくつ進めるとか、
指す先の間隔がいくつだというものであって、
アドレスを演算して実現するってのは実装上の都合。
アドレスが連続しているということさえ保証はない。
たとえば
char a[2];
とあったときに
(intptr_t)(&a[1])-(intptr_t)(&a[0])
が 1 になることは言語仕様では保証されない。
(これが 1 にならないような変な環境はまず無いと思うんだけど。)
具体的に機械でどう動いているかから見ると肌感覚として理解しやすい場合もあるのはわかるが、
言語の理屈と混同しないように、一旦それは抽象の壁の向こうに押しやる必要もある。 ラムダ式でthisを指定してそのクラスのメソッドを呼び出したところ、そのクラスのメンバ変数がすべて0になっててコンストラクタも動作してない状態になってたのですが、使い方間違ってますか >>559
インスタンスが既に破棄されているのでしょう
c++ ではオブジェクトの寿命管理は自分でやる必要があります
(参照があるから破棄されないということはない) >>559
[&*this]
こうしたっていう意味? ラムダ式にはthisを指定しました
インスタンスは生きています
ラムダ式内から直接呼ばずにグローバル変数に保持したインスタンス変数経由で同じメソッドにアクセスしたら正しい値が読み取れました auto f = [this]() {... };
てな感じにキャプチャはしてるんだよね。してないとコンパイルエラーになるし。
デバッガでみておかしいだけならデバッガがうまく動いてないだけでは?
cout << this->hoge;
とかして見てみたらどうでしょう。 >>562
>ラムダ式内から直接呼ばずにグローバル変数に保持したインスタンス変数経由で同じメソッドにアクセスしたら
warning読み飛ばしてるだけだと思うが
warningにそうしろって書いてあるはず あとグローバルにしなくても
ラムダ式を呼ぶ側の関数内のローカル変数で保持しても多分いける 複数のファイルをコンパイルするとき、ソースファイルの読み込み順番ってc++ではどのように決定されるのでしょうか? 読込み順番ってのが何を言おうとしているのかよくわからんぞ。 >>566
それぞれ別の翻訳単位として、独立に処理されるぞ。
依存関係があって先に読み込ませる必要があるファイルは、#includeで明示的に指定した順に読み込ませる必要があるよ。 先に読み込ませれば (ヘッダを include したり宣言を書いたりしなくても) 定義したものが利用可能になると思ったってことなのかな? ソースファイルの読み込み=ソースのコンパイルとして
makeなり 統合環境なりが 依存関係チェックして必要と思われた順にコンパイラを起動しコンパイルしてる >>571
>makeなり 統合環境なりが 依存関係チェックして必要と思われた順
別に make による依存度チェックが必須だとは思っていません
最悪、アプリケーションを構成する全ソースを全部コンパイルしたっていい
やっていることがよくわからないのなら、全部再コンパイルするバッチを書いてもいい、と思っています >>572
確かに、時間が無駄になるだけで、それにより動作が変わってしまう等の害を及ぼすことはないからなー
結局 >>566 が聞きたかったことは皆目見当がつかんけどもw vectorで複数のstd::stringの各要素を収納して管理してみたいのですが、
実際、vectorの特定の要素にアクセスしてstringのデータを入れようとするとエラーになってしまいます。
例えば、次のようなコードの場合です。
std::string A = "bookA";
std::string B = "bookB";
std::vector<std::string> booktitle;
booktitle[0] = A;//コンパイルエラー
vectorで複数のstd::stringのデータを収納したい場合にはどうしたらいいのでしょうか? >>574
booktitle.push_back(A); >>573
FreeBSD 2, 3, 4 (くらいかなあ) 時代には、OS カーネルを再度コンパイルすることはあたりまえだったんですけれども、最近はそういう話はすたれてしまいましたね… >>575
ありがとうございます。
例えば、vectorにpush_backで100個のstd::stringのデータを入れたけれど、38個目のデータを別のものに変更したいという場合、
38個目のstd::stringのデータを直接指定して別のものをいれるということはできないんでしょうか? >>577
38個以上格納した後なら、
booktitle[37] = A;
で書き換えられる。 >>577
c の普通の配列みたいに中身に拘らずとりあえずサイズ100の配列を用意したい場合は
v.resize(100) でいけるのでその辺りも併せて覚えておきましょう 関数の中でポインタ変数を作ったら、その関数から出る時、ポインタ変数は消えるけど、ポインタ変数の中身はどっか別にあって消えないってことで良いんですかね?
その中身を消すのがdelete関数ってことですか?ややこしいな・・・ ありがとう。すみませんもう一つ。
ポインタ変数のアドレスを格納するのに、なぜ二重ポインタが必要なのかがいまいちわかりません。
単に”番地”を格納するだけなら普通のポインタでも良いような気がしてしまいます。 それは、32ビット浮動小数点のビットパターンを32ビットintに入れておけば
float型とかいらないと言ってるようなもの アドレス値がほしいとき
引数でアドレス入れる変数のアドレスを渡すことがある >>582
情報量としては実際のところメモリアドレスなので同じだけれど型が違う
pがint へのポインタなら
*p はアドレス位置にある int を返すし、
p++ すると int のサイズ分増えるし、
p[i] はintのサイズかけるiのメモリ位置にある int になる
上記の int を char やポインタ型に入れ替えると動作が異なることがわかる。
なんの型で読み書きするのかとかサイズの計算なんて人がコードで書けばいいじゃん、
という流儀もあるだろうがcは違う
例外としてなんの型だか不明なものを扱うときには、
とりあえずvoid*で保持しておいて計算やアクセスするときに
明示的に型を指定して用いることもある アドレス渡さないと変数(今回の場合アドレスを格納する領域)に値を格納できない
コレはどんな変数でも同じ
アドレスを格納する変数もただの変数だからな >>580
>ポインタ変数の中身はどっか別にあって消えないってことで良いんですかね?
(ポインタ変数の中身はポインタだが、ポインタが指してる先と読み替えよう)
指してる先はどっか別にあってって、言語が自動で作ってくれるわけじゃないよ
ポインタが指す先もプログラマが作らなきゃならない
だから消える所に作れば(自動変数な)消えるし、消えない所に作れば(静的変数やnewな)消えない
>>582
二重ポインタ(って表現もナニだが…)も
ポインタを指してるってだけの普通のポインタだから 「戻り値ではなく、引数の書き換えで呼び出し元に新たな値を渡したい」
・関数側宣言はポインタで受けて 呼び出し側は変数に&つけてポインタを渡す (c/c++)
関数実装の際 *でデリファレンスして代入
・関数側宣言は参照で受けて 呼び出し側は変数をそのまま渡す (c++)
関数実装の際 そのまま代入 >>582
freeしたあと確実にNULL代入したいためにポインタのポインタで管理しておくことはある あと二重ポインタとかダブルポインタとかいう用語は使わない方が良い
ポインタのポインタ(たまにポインタの配列)
配列のポインタ
のどっちかにしろ void my_free(void** ptr) { free(*ptr); *ptr = NULL; }
.......
char *data = malloc(size);
.......
.......
my_free(&data);
/* これ以降 data = NULL になってるから参照するとヌルポになる */ >>590
なんで?
double pointerも十分すぎるくらい市民権得てると思うけど。 >>594
char pointer と double pointer が並んでも? 自分がそう呼ぶかどうかはともかくとして、
ダブルポインタやdouble pointer でググればわかるようにそう呼称されることも大変多いわけだから
ポインタのポインタをダブルポインタと呼ぶことが多いことを知らんでいるわけにはいかんのが現実 **ダブル ***トリプル ****クアドラプル?
うーん 使うのはポインタのポインタまでにしとかないと書いててワケわからなくなるぞ 素朴な疑問だけど、ビット演算の | と論理演算の ||
前者を「オア」と呼んで後者を「ダブルオア」と呼ぶ? ■ このスレッドは過去ログ倉庫に格納されています