【初心者歓迎】C/C++室 Ver.102【環境依存OK】
■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん
垢版 |
2017/11/04(土) 16:33:35.07ID:NYxCuvMY
エスケープシーケンスやWin32APIなどの環境依存なものもOK
そのような質問は必ず環境を書きましょう
半角空白やタブでのインデントはスレに貼ると無くなります

コードを貼れる所
http://codepad.org/
https://ideone.com/

前スレ
【初心者歓迎】C/C++室 Ver.101【環境依存OK】
https://mevius.5ch.net/test/read.cgi/tech/1500329247/
0466デフォルトの名無しさん
垢版 |
2018/04/08(日) 08:56:58.76ID:peS6i82l
>>465 thanks yey!
0468デフォルトの名無しさん
垢版 |
2018/04/08(日) 09:14:13.86ID:peS6i82l
>>464
it is conditional on your ability, although its mean applying in the case of a usual Japanese.
0470デフォルトの名無しさん
垢版 |
2018/04/08(日) 09:44:32.26ID:nHJNjK41
main関数の中でstaticを使う意味は何でしょうか?

ロベールの本のpp.318-319にそのような例が出てきて意味不明です。
0472デフォルトの名無しさん
垢版 |
2018/04/08(日) 11:47:04.28ID:fQMOYFpe
ロベールの本を持ってないんで、適切な回答じゃないかもしれんが。

main() 関数の中でstatic変数を使う意味といえば、
単純型の初期化の処理時間を回避したいか、
セクション(変数のメモリ配置)の説明のためか、
「staticなインスタンスのコンストラクタはmain()より前に実行される」
ていう話の前フリかなぁ。
0473はちみつ餃子 ◆8X2XSCHEME
垢版 |
2018/04/08(日) 13:50:30.74ID:RvzgDq0H
>>472
ローカル変数に static 変数が付いていた場合は最初に通過したときに初期化されるルール。
(コンストラクタもそのときに走る。)
これは C のときから変わってないよ。
0474デフォルトの名無しさん
垢版 |
2018/04/08(日) 14:41:24.43ID:b4O4Usd0
普通に考えると、
単にスコープをローカルにしたいってのがまず考えられる
0475デフォルトの名無しさん
垢版 |
2018/04/08(日) 14:46:24.29ID:drN9+cfC
>>473
横からだけど訂正乙
初心者が読んで間違えて覚えるので、初心者スレでは嘘を書かないように特に気をつける必要ある
0476デフォルトの名無しさん
垢版 |
2018/04/08(日) 15:12:26.18ID:nkM5b3tX
>>474
mainの中だから意味無い

っつーかstaticは二つの意味があって全然別物
スコープと性的と混ぜるな危険
0478デフォルトの名無しさん
垢版 |
2018/04/08(日) 15:20:01.32ID:drN9+cfC
>>474
関数内でstatic変数を使うのは静的変数のスコープを関数ローカルにしたいからでは、
というごく当たり前の文意だろ普通に読むと。

どう読むと
関数内だからファイルローカルの話とか関係ない!勘違いするな!となるんだよ
自分以外は文法もセマンティックもろくに知らないという前提はやめるべき
0481472
垢版 |
2018/04/09(月) 08:00:59.66ID:4Qmw3/oH
関数スコープのstaticなクラス・インスタンスのコンストラクタは
main()以前でなく、最初にその部分が実行されたときに初期化されるんだっけか。

static なら一律にmain()の前、基本型や単純な構造体のstaticはロード時に初期化、
だと勘違いしていた。
訂正してくれてありがとう。そして間違ったことを書いてすまぬ。
0482デフォルトの名無しさん
垢版 |
2018/04/09(月) 08:28:16.55ID:arNj8dw4
初期化が固定データのメモリコピーで済むものはロード時に初期化するコンパイラが普通
0484デフォルトの名無しさん
垢版 |
2018/04/09(月) 15:10:57.47ID:cuDt6une
>>480

ありがとうございます。本とは内容が違うようです。

int main() {
static const double ARRAY1[] = {1, 2, 3, -1};
static const double ARRAY2[] = {0.5, 1.5, ,-1};
static const double ARRAY3[] = {-1};
static const double* const ARRAY[] = {ARRAY1, ARRAY2, ARRAY3};


}

というコードが該当箇所です。
0485片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2018/04/09(月) 15:13:59.63ID:4wbW7ji0
staticを付けなければスタックに確保されるかもしれない。その場合、どうしても遅くなる。
0486デフォルトの名無しさん
垢版 |
2018/04/09(月) 15:16:14.76ID:cuDt6une
>>485

でも、速さがどうとかいうことについては何も書いていないんです。
staticを付けていることについては何の説明もありません。
0487デフォルトの名無しさん
垢版 |
2018/04/09(月) 15:31:05.83ID:iBEYls0Z
>>486
>>485はきちんとした回答だと思うよ。
配列が大きくなれば顕著になる。
「その本に書かれていないから」と拒絶するのは憲法に基づいて自由だけど
0488デフォルトの名無しさん
垢版 |
2018/04/09(月) 15:38:58.45ID:7w9BViIO
定数だからstatic constにした
というだけのことでそれ以上の意味はないと思うが
0489デフォルトの名無しさん
垢版 |
2018/04/09(月) 15:39:52.73ID:Cpp6LEO8
その変数をコンパイル時点で確定しようとしている。
ローディング時間も早くなる
0491デフォルトの名無しさん
垢版 |
2018/04/09(月) 15:57:19.85ID:XexqtlKa
>>484
ROMとRAMに別れてる環境、
つまりほとんどの小規模な組み込み環境だと
static const は通常ROMに配置される
要するにRAMの節約

速度は逆にRAMの方が速いのが普通
0492デフォルトの名無しさん
垢版 |
2018/04/09(月) 16:42:59.75ID:cuDt6une
クラスの定義をヘッダファイルに書くときに、

privateなメンバまで書くのはなぜですか?

必要ないように思います。
0493デフォルトの名無しさん
垢版 |
2018/04/09(月) 16:45:14.78ID:cuDt6une
>>484

みなさん、ありがとうございました。
速度について気にしているのなら、ロベールにはそう書いてほしかったです。
例では、非常に小さな配列ですから速度について気にしていることは読み取りにくい
ように思います。

>>488
定数だから const にしたというのなら分かるのですが、なぜstaticをつけるのでしょうか?
0494デフォルトの名無しさん
垢版 |
2018/04/09(月) 16:46:43.49ID:cuDt6une
>>492

private なメンバはむしろ、クラスのメンバ関数を実装する .cpp ファイルに書いた方がいいように思います。
0498デフォルトの名無しさん
垢版 |
2018/04/09(月) 18:17:18.89ID:R2K+YmFs
>>493
あの部分では特別に速度を意識した記述ではなく普通に意識する程度の事だから一々説明されないということではないかな
速度や使用メモリを気にするのはCやC++プログラマの癖または習慣みたいなもので特にロベールみたいな昔の人は体に染み付いているだろうからね
0499デフォルトの名無しさん
垢版 |
2018/04/09(月) 18:28:43.00ID:arNj8dw4
>>493
今回はたまたまmainであり、
たまたま小さなデータだったというだけで、
より汎用性の高いコードにするのはプログラミングの基本

staticを付けるメリットは
・データ構造の初期化が1回(ROMだと0回)で済む
・スタックを浪費しない
・関数を抜けてもデータが保持される
・番地が固定

デメリットは
・関数を通らなくても初期化される
・関数外でもメモリを使う
0501デフォルトの名無しさん
垢版 |
2018/04/09(月) 18:49:30.99ID:m9zaOBXx
test2の形だと上手く動作しないのですが何故でしょうか
環境はvc6とstlport521です

void test1(const char* cstr, ...) {
char buf[1024];
va_list args;
va_start(args, cstr);
vsprintf(buf, cstr, args);
va_end(args);
printf(buf);
}
void test2(std::string str, ...) {
const char* cstr = str.c_str();
char buf[1024];
va_list args;
va_start(args, cstr);
vsprintf(buf, cstr, args);
va_end(args);
printf(buf);
}
void main() {
test1("hello1 %d\n", 123);
test2("hello2 %d\n", 123);
}
//結果
//hello1 123
//hello2 1819043176
0503デフォルトの名無しさん
垢版 |
2018/04/09(月) 19:06:25.54ID:m9zaOBXx
引数を参照とポインタでも試してみましたが結果は変わらなかったです

void test3(std::string& str, ...) {
const char* cstr = str.c_str();
・・・
void test4(std::string* str, ...) {
const char* cstr = str->c_str();
・・・
void main() {
・・・
std::string str3("hello3 %d\n");
test3(str3, 123);
std::string str4("hello4 %d\n");
test4(&str4, 123);
}
//結果
//hello1 123
//hello2 1819043176
//hello3 1819043176
//hello4 1819043176
0506デフォルトの名無しさん
垢版 |
2018/04/09(月) 19:22:49.12ID:m9zaOBXx
ああなんとなく意味が分かってきました
va_startはマクロであってcstrの部分は引数の変数名が指定されなければならないということですかね
0507デフォルトの名無しさん
垢版 |
2018/04/09(月) 19:41:37.65ID:m9zaOBXx
こういうコードにすると期待した動作をするようになりました
ありがとうございました

void test5(std::string str, ...) {
char buf[1024];
va_list args;
va_start(args, str);
vsprintf(buf, str.c_str(), args);
va_end(args);
printf(buf);
}
void main() {
・・・
test5("hello5 %d\n", 123);
}
//結果
//hello1 123
//hello2 1819043176
//hello3 1819043176
//hello4 1819043176
//hello5 123
0508デフォルトの名無しさん
垢版 |
2018/04/09(月) 19:45:39.82ID:yhCzF70B
ついでに言うと va_start の第二引数については仕様上結構な制限、
各 argument に課される制約と同じ制約がある
配列はダメ、参照はダメ、基本型が格上げされる型との互換性が必要、など
最後のはクラスオブジェクトや float はダメということ
仕様として結果が不定なだけで違反してもエラーにはならないし
意図した通りに動くことも多い

詳しくは default argument promotions va_start
で検索
0509片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2018/04/09(月) 20:00:39.54ID:4wbW7ji0
va_listとC++は、相性が合わないんだよな。呼び出し側でc_str()するとか。
0511はちみつ餃子 ◆8X2XSCHEME
垢版 |
2018/04/10(火) 00:44:35.92ID:141aKXKv
特に強い理由がなければ variadic template を使った方が安全だし簡単に書ける。

template<class... T>
void test6(std::string str, T... args) {
char buf[1024];
std::sprintf(buf, str.c_str(), args...);
std::printf(buf);
}
0516はちみつ餃子 ◆8X2XSCHEME
垢版 |
2018/04/11(水) 11:17:54.25ID:ZSzBt9iE
えー、可変長引数の例にしただけなので、そんなどうでもいいとこを言われても困るよ。
0521デフォルトの名無しさん
垢版 |
2018/04/11(水) 21:29:16.68ID:0UD5Vzkt
普通はね
クソコテがコードサイズ、互換性、実行速度など
全て犠牲にしてもテンプレートを使いたかったみたい
0522デフォルトの名無しさん
垢版 |
2018/04/11(水) 21:46:51.95ID:4xNEGOrU
va_start の第2引数の型の制限を知らなくてもor気にしなくても良いように
C++ らしく va_start 使わない例を出したんだろ…

と書いてはみたが、
そういう意図が通じるわけないか
通じる人は最初からわかってるもんな
0526デフォルトの名無しさん
垢版 |
2018/04/11(水) 22:01:42.55ID:5X4H9iqq
危険てんこ盛りなコードの危険性が低い部分をなおしてどうすんの?アホなの?

オナニーは隠れてやれ
0528はちみつ餃子 ◆8X2XSCHEME
垢版 |
2018/04/12(木) 00:24:16.88ID:csgoYI7G
>>526
危険性が高いかどうかは重要じゃなくて、話題のテーマに近いかどうかだろ。
本題に関係ないところなんてどうでもいいじゃないの。
0531デフォルトの名無しさん
垢版 |
2018/04/12(木) 10:41:06.56ID:KhnSMF/h
const double const ARRAY[] = { 3, -1 };
const double ARRAY[] = { 3, -1 };

の違いを教えてください。
0532デフォルトの名無しさん
垢版 |
2018/04/12(木) 10:48:56.23ID:ySRK5Kj5
ポインタ変数なら
・変数も指し先も書き換えられない
・変数は書き換え可能。 指し先は書き換えられない
のパターンだけど

対象が配列の場合、元々変数の書き換えができないから同じ意味じゃないかと
0534デフォルトの名無しさん
垢版 |
2018/04/12(木) 12:25:36.92ID:KhnSMF/h
>>532

ありがとうございました。

>>533

Visual Studioではコンパイルエラーになりません。
0537 ◆QZaw55cn4c
垢版 |
2018/04/12(木) 15:19:35.63ID:4odEe1Tq
とりなくこえすゆめさませ
0538デフォルトの名無しさん
垢版 |
2018/04/12(木) 21:59:02.17ID:nMaemNOx
const double const a[];

const double a[];
と同じ意味
const const double const const a[];
なんて書いてもいいし
double const a[];
と書いてもいい

const typename と typename const と同じ
しかもconstはいくつ書いてもいい
0539デフォルトの名無しさん
垢版 |
2018/04/13(金) 10:38:13.53ID:roGFrSR8
Win32のBOOL型を返す関数を複数回呼んで、
すべて成功したときのみTRUEを返したいのですが
(途中で失敗しても関数自体はすべて呼んでおく)、

BOOL Test()
{
  BOOL bResult = TRUE;
  bResult &= Api(...);
  bResult &= Api(...);
  bResult &= Api(...);
  return bResult;
}

と書いてとりあえず動くのですが、よく考えたら&=はビット演算だし、
Win32のBOOL関数は成功時にTRUEを返すとは書いていないので、
例えば関数が成功時に2を返すパターンがあったら、
すべて成功しても戻り値はFALSEになるのではと思っています。

この場合、

bResult = Api(...) && bResult;
bResult = Api(...) && bResult;
bResult = Api(...) && bResult;

みたいな書き方をするしかないのでしょうか。
0540デフォルトの名無しさん
垢版 |
2018/04/13(金) 10:57:04.94ID:UdLtdLwz
result &= !!api(...);

という風に!!を使うのも zero, non zero を false/true に正規化するイディオムだけど、
何にしても見た目は汚いと思う

文字数は増えるがif文を使って
if (!api()) result=false;
の方が可読性高いかもしれない
0541デフォルトの名無しさん
垢版 |
2018/04/13(金) 11:38:56.36ID:OgXHMhZG
>>539
成功した回数をカウントして呼び出す関数が3つなら3でTRUEにするかな
BOOL Test()
{
int count = 0;
if(Api() != FALSE) count++;
if(Api() != FALSE) count++;
if(Api() != FALSE) count++;
if(count == 3) return TRUE;
}
0542デフォルトの名無しさん
垢版 |
2018/04/13(金) 12:44:10.91ID:mVcRE5FO
結果を std::vector にでもまとめておいて、 std::all_of で全てがFALSEでないことを確認するとか。
0543デフォルトの名無しさん
垢版 |
2018/04/13(金) 12:50:27.67ID:UkpF6ptq
>>539
> bResult = Api(...) && bResult;
> bResult = Api(...) && bResult;
> bResult = Api(...) && bResult;
これでいいと思う

>>541
3個位ならいいけどたくさんになると数え間違いとかやらかしそう
0547539
垢版 |
2018/04/13(金) 15:24:49.14ID:roGFrSR8
みなさんご意見ありがとうございます。
例を簡略化しすぎてしまいましたが、処理は状況によって分かれるため、
常に同じ関数が3回というわけではありませんでした。
失礼しました。

bResult = Api(...) && bResult;

の書き方自体は、そこまで汚いわけではないのですね。
同じような書き方をしているソースも、検索してみたら出てきました。

個人的には、

bResult &&= Api(...);

のような記述ができるとありがたかったです。
0549デフォルトの名無しさん
垢版 |
2018/04/13(金) 16:33:04.14ID:cn4ajNkQ
&&= と書けないことをこの質問で知ったわ。

>>548
「返り値が0でなければ成功」の関数で変テコな返り値が来ると
組み合わせでダメになるかも。
256 * 256 == 65536 で オーヴァーフローして0、みたいな感じ。
0550デフォルトの名無しさん
垢版 |
2018/04/13(金) 16:33:39.54ID:aZorcSvM
明確なメリットが無いのに、
無駄にトリッキーなコードを書くのはおすすめしない
0551デフォルトの名無しさん
垢版 |
2018/04/13(金) 16:39:34.39ID:aZorcSvM
数が少なく重要な箇所であれば、
デバッグ用コードを追加しやすい以下で良い

if (!Api(...)){
bResult = FALSE;
}
...

数が少なく重要じゃなければ >>547 で良い

数が多ければ色々と工夫しようか
0552 ◆QZaw55cn4c
垢版 |
2018/04/13(金) 16:44:07.64ID:fORiWt/O
>>548
適当なニ数をかけたら 0 になってしまった、とかはあり得るのでしょうか?

…んー、ないな、何故ないのだろう?
0553デフォルトの名無しさん
垢版 |
2018/04/13(金) 17:53:26.34ID:ledbPVdv
基底クラスのメンバ関数に virtual をつけないことってあるんですか?
つけてもつけなくてもどちらでもいいという場合はあると思いますが、
つけちゃいけないという場合が考えにくいのですが、そういう場合は
あるのでしょうか?
0554デフォルトの名無しさん
垢版 |
2018/04/13(金) 17:55:06.07ID:ledbPVdv
逆に言うと、今のC++でvirtualをつけた場合の機能をvirtualをつけなかった場合の
デフォルトの機能にすればいいのにと思います。

どうでしょうか?
0555片山博文MZ ◆T6xkBnTXz7B0
垢版 |
2018/04/13(金) 17:56:07.81ID:meZ//aXI
>>553
仮想メソッドは、最適化がなければ関数ポインタのように確保されるので、不必要なものはメモリーの無駄になる。
0556デフォルトの名無しさん
垢版 |
2018/04/13(金) 17:58:31.25ID:ledbPVdv
>>555

virtualはつけなくてもかまわない場合には付けない方がいいということなんですね。

ありがとうございました。
0558はちみつ餃子 ◆8X2XSCHEME
垢版 |
2018/04/13(金) 21:02:41.55ID:RMqAMM1S
>>557
せやな。 普通はないと思うが、無いと言い切ることもできない。

ここまでいろんな案が出てるけど、なんだかんだで >>539 が自分で結論出してるのがベストだと思う。
書き方の話なら、マクロでもクラスでも適当なものでラップすれば見栄えはどうとでも出来ることだし。
0560デフォルトの名無しさん
垢版 |
2018/04/14(土) 00:48:59.29ID:qJeIaUAA
今回は「非ゼロ」が様々な数値である場合について考えているわけだから
0x80000 等掛けたらゼロになるケースを意識しないのはむしろ不自然
0561デフォルトの名無しさん
垢版 |
2018/04/14(土) 01:08:45.20
int64_t 使えばいいだろwww
ケチケチすんなってwwwww
0563デフォルトの名無しさん
垢版 |
2018/04/14(土) 05:40:34.13ID:DUdlBUp3
>>547
汚い書き方とまでは言わないけど、個人的にはあまりいいやり方だとも思わないかな。

俺もC, C++を覚えた当初はなるべく冗長な記述を省くことが正義であると考えていたけど、
そのうち高々数文字削ることなんかより、素直に可読性や保守性が高い記述をする方が美しいと感じるようになったよ。
■ このスレッドは過去ログ倉庫に格納されています

ニューススポーツなんでも実況