2ちゃんねる スマホ用 ■掲示板に戻る■ 全部 1- 最新50    

■ このスレッドは過去ログ倉庫に格納されています

スレを勃てるまでもないC/C++の質問はここで 24

1 :デフォルトの名無しさん:2015/11/28(土) 13:30:34.09 ID:S1e+2GUN.net
スレを勃てるまでもない低俗なC/C++の質問はここでお願いします。

過去ログ
01 http://pc11.2ch.net/test/read.cgi/tech/1167476845/
02 http://pc11.2ch.net/test/read.cgi/tech/1178503366/
03 http://pc11.2ch.net/test/read.cgi/tech/1187521676/
04 http://pc11.2ch.net/test/read.cgi/tech/1221633708/
05 http://pc11.2ch.net/test/read.cgi/tech/1230516307/
06 http://pc11.2ch.net/test/read.cgi/tech/1231564903/
07 http://pc11.2ch.net/test/read.cgi/tech/1232983248/
08 http://pc12.2ch.net/test/read.cgi/tech/1235921779/
09 http://pc12.2ch.net/test/read.cgi/tech/1240022781/
10 http://pc12.2ch.net/test/read.cgi/tech/1242300936/
11 http://pc12.2ch.net/test/read.cgi/tech/1245059383/
12 http://pc12.2ch.net/test/read.cgi/tech/1248010352/
13 http://pc12.2ch.net/test/read.cgi/tech/1260842197/
14 http://pc12.2ch.net/test/read.cgi/tech/1269273471/
15 http://pc12.2ch.net/test/read.cgi/tech/1273368706/
16 http://hibari.2ch.net/test/read.cgi/tech/1279285647/
17 http://hibari.2ch.net/test/read.cgi/tech/1285115590/
18 http://hibari.2ch.net/test/read.cgi/tech/1291571263/
19 http://hibari.2ch.net/test/read.cgi/tech/1308106024/
20 http://toro.2ch.net/test/read.cgi/tech/1316013463/
21 http://toro.2ch.net/test/read.cgi/tech/1342285511/
22 http://peace.2ch.net/test/read.cgi/tech/1399911167/
23 http://peace.2ch.net/test/read.cgi/tech/1420379468/

2 :デフォルトの名無しさん:2015/11/28(土) 13:42:54.23 ID:S1e+2GUN.net
誰か書いてー
即死する

3 :デフォルトの名無しさん:2015/11/28(土) 13:58:59.04 ID:u5grs2xF.net
1乙

4 :デフォルトの名無しさん:2015/11/28(土) 20:31:40.61 ID:JroX99O/.net
ものすごい下らないことですが質問です。
こんな感じのクラスがあって
class A {
public:
&nbsp;&nbsp;std::unique_ptr<int[]> xxx = nullptr;
private:
&nbsp;&nbsp;void reset_xxx(size_t n) /* noexcept */ // <- このコメントを外したい
&nbsp;&nbsp;{
&nbsp;&nbsp;&nbsp;&nbsp;xxx.reset(new(std::nothrow) int[n]);
&nbsp;&nbsp;/* new が失敗したときはここでどうにかする */
&nbsp;&nbsp;}
};
(1)
reset_xxx に noexcept 指定子をつけたいのですが、
int のような基本型、あるいはその配列に対する delete は
例外を投げないことが保証されているんでしょうか。
あるいは POD ではどうでしょうか。
POD でなくても、デフォルト定義のデストラクタを持っているなら?
(2)
上記のクラスで xxx を読み取り専用として扱うとき、
std::unique_ptr<int[]> xxx = nullptr;
の代わりに
std::unique_ptr<const int[]> xxx = nullptr;
とした方がいいでしょうか。
宗教上の問題になるのでしょうか。

5 :デフォルトの名無しさん:2015/11/28(土) 20:36:01.12 ID:JroX99O/.net
わあ、nbsp のつもりがひどいことになってしまいました。
クラスを再掲します。インデントは全角スペースにしました。
class A {
public:
  std::unique_ptr<int[]> xxx = nullptr;
private:
  void reset_xxx(size_t n) /* noexcept */ // <- このコメントを外したい
  {
    xxx.reset(new(std::nothrow) int[n]);
    /* new が失敗したときはここでどうにかする */
  }
};

6 :デフォルトの名無しさん:2015/11/29(日) 20:15:17.63 ID:+8PPW4GA.net
>>4
(1)については、
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
の、3.7.4.2.3に
If a deallocation function terminates by throwing an exception, the behavior is undefined.
って書いてある。だから例外投げるデストラクタの存在は無視して良いと思う。

あとnewは例外を投げるとすればstd::bad_alloc以外は投げない事になってるのと、
その場合にはそのサイズのメモリの確保は出来ない事になってるので
素直にstd::terminate投げるなりexit呼ぶなりしても良いと思う。

(2)については、(const_cast出来るって意味で)本当に書き換え不能な領域を実行中に作るのは無理なので
書き換えしないでねって他のプログラマに表明する以上の意味は無いと思う。

7 :片山博文MZ ◆T6xkBnTXz7B0 :2015/11/29(日) 20:30:03.53 ID:RQ97x6ZU.net
「FM音源をあやつって正しく音を出したい」
OpenAL+ALUTと、ciscさんのFM音源エミュレータ
「FM Sound Generator」を使って、正しく音を出したい。

https://github.com/katahiromz/fmgengen2/blob/master/sample.cpp
https://github.com/katahiromz/fmgengen2

おかしな音が出ます。たぶんFM音源の使い方が間違っています。
修正方法を教えて下さい。ドレミの音が出るようにして下さい。よろしくお願いします。

8 :デフォルトの名無しさん:2015/11/30(月) 13:51:44.68 ID:VtHFUkMk.net
unsigned short同士の掛け算がunsigned int ではなくてintに昇格するのはどうしてですか?

9 :デフォルトの名無しさん:2015/11/30(月) 20:19:20.81 ID:luHPgjr1.net
unsigned shortが int に拡張されるからでは

10 :デフォルトの名無しさん:2015/11/30(月) 21:26:57.04 ID:VtHFUkMk.net
その仕組みはわかるんですけど、そこでどうしてunsigned intではなくてintでなければならないのかがわかってません。
short 2バイト int 4バイトだとして 65535 * 65535 の結果はINT_MAXより大きいですが、unsigned intの範囲で安全に表現できますよね。
どうして不確からしさが増すような方向への変換がデフォになってるのかという疑問もあります。

11 :デフォルトの名無しさん:2015/11/30(月) 21:42:20.20 ID:jWn5VC7w.net
unsigned short × unsigned short がどうこうではなく
計算時に unsigned short が int に拡張されるってだけでしょ
拡張された状態で乗算するから結果もintになるって

12 :デフォルトの名無しさん:2015/11/30(月) 22:19:42.99 ID:VtHFUkMk.net
unsigned shortがintに拡張されてから計算されるというのは最初からわかってるんですが、
unsigned shortの拡張される先がunsigned intではなくてintでなければいけない理由がわかっていないんです。
下の2行はunsigned intにしておけば掛け算にたいしても安全ではないか、ということです。

現実的ではないのかもしれませんがintが2byteの場合だと
unsigned short * unsigned shortの結果はunsigned int*unsigned intと一緒の結果ですよね。
それがint 4byteの場合だと結果はint*intになってINT_MAXをオーバーフローして困ったことになると思うんです。

なんでそうなってしまうかといえば、unsigned intではなくてintに変換されてから計算されるからです。
どうしてそのようになっているのですか?

13 :4:2015/11/30(月) 22:38:13.05 ID:Dn8P3OaQ.net
>> 6
ありがとうございます。
(2) については仰るとおりで、まさにそれがやりたいことだったので、
const はつけておくことにします。

(1) については…… なんていうか、ちょっと聞きたいことと違っていました。
> 例外投げるデストラクタの存在は無視して良いと思う
というのは
「どうせ例外が発生したときの挙動が undefined なんだから、
 コンパイラが速いコードを生成するよう noexcept はつけててもいい」
ということだと理解したのですが、ぼくが noexcept で表現したいのは
「この関数はいつ呼ばれても(特に関数失敗時にも)意味のある値を返す」
ということなんです(これって変な考えなんでしょうか)。
なので xxx.reset が例外を投げうるなら noexcept は外したいです。
むしろ未定義動作をする可能性がある関数である、ということを強調して
コメントにでも書いておきたいくらいです。

とはいえ常識的に考えて、ヒープが壊れていない限り int[] の delete[] が失敗することは
ないですよね……。うーん。

14 :片山博文MZ ◆T6xkBnTXz7B0 :2015/11/30(月) 23:17:12.67 ID:UQmO47jh.net
>>7
他力を借りて解決しました。
http://katahiromz.bbs.fc2.com/reply/10466094/34/

15 :デフォルトの名無しさん:2015/11/30(月) 23:56:14.64 ID:qSWjFIuy.net
>>12
じゃあさ、unsigned long * unsigned long はどうすればいいと思う?

16 :デフォルトの名無しさん:2015/12/01(火) 09:09:35.39 ID:vya/mPuO.net
>>12
unsignedにキャストする処理まで入れてないだけだろ
一般的には整数演算器の入出力はsigned int
intが何ビットかはCPUコアに依存する

17 :デフォルトの名無しさん:2015/12/01(火) 11:46:59.87 ID:E/WRWJc0.net
前スレの>14で
「プログラムが終了する際にmallocした領域をイチイチfreeする奴は馬鹿だ、という情報工学の先生がいたなー
こんなセンセーに教育された学生はうちの会社にはいらないw 」
とあるんですが、これはその先生が間違っているということですか?
そうであるなら理由を教えてくれますか?

18 :デフォルトの名無しさん:2015/12/01(火) 13:21:42.49 ID:YGJMPkGb.net
>>12
そういう仕様としか言いようがないが‥
K&Rでは符号が保存され、あなたが期待するunsigned intで計算される仕様になっている
ANSI Cはintで表現できるならintになる仕様になっている
エキスパートCプログラミングによると、ANSIの方は値を保存するという考えらしい

19 :デフォルトの名無しさん:2015/12/01(火) 14:34:40.17 ID:wfTLHpyu.net
>>17
ある意味では間違っていて、ある意味では正しい。

・mallocされたメモリがプログラム終了時にきちんと開放されるかどうかはOS依存(Cの仕様上は開放されない事になってる)
・非常に長く動くプログラムの場合、mallocしたものは必要に応じて開放しなければいつかメモリが足りなくなる
・mallocされたメモリをプログラム終了時までにfreeしない方がいいとはCの仕様書には書かれていない
・人を馬鹿にしてる
という意味では常に先生が間違っている。

・mallocされたメモリはプログラム終了時までに絶対にfreeしなければならないとはCの仕様書には書かれていない
・malloc/freeの実装によっては、malloc/freeする順序によっては非常に重くなり、プログラム終了時にOSが回収したほうが速くなることがあり得る
という意味では先生は正しい。

20 :デフォルトの名無しさん:2015/12/01(火) 18:30:22.99 ID:4XFiGbBF.net
>>17
その話しの流れが読めないので想像ですが。

mallocした領域をfreeせずにプログラムを終了させた場合、その領域がどうなるかはC言語の仕様では規定されていないと思います。
言い換えれば環境(処理系やOS)に依存した挙動になるでしょう。
「freeする奴=バカ」と教え込まれた学生が会社に入り、環境ごとの挙動を調べることなく盲目的に「終了時のfreeは不要」を信じてコーディングしたら‥
アカデミックな世界ではいざしらず、実務の世界では、裏付けもない思い込みでプログラムを組まれては、たまったものではありません。

おそらくそういう事が言いたかったのではないでしょうか?
#というか情工の先生で軽々しくそんな事を言う人はいないと思いますので、おそらく「ネタ」じゃないですかね。

21 :デフォルトの名無しさん:2015/12/01(火) 21:54:03.31 ID:lP+cizb6.net
>>20
規定されてる。規格書よんでから出直しなさい。

22 :デフォルトの名無しさん:2015/12/02(水) 17:40:34.22 ID:Cj5Jy42r.net
INT_PTRが良く分かりません。単なるint型と考えていいのでしょうか?
わざわざPTRという名前が付いているのは、ポインタのサイズと同様にそのサイズが環境に一致することを示すため??

23 :デフォルトの名無しさん:2015/12/02(水) 17:51:28.60 ID:SG5bn8pD.net
>>22
単なるint型は整数型で、整数が入る
INT_PTR型はポインタ型に等しい幅を持つ整数型で、ポインタ型をどうしても整数型にキャストしたい時に使うらしい。

以下引用

ポインタは int、LONG、ULONG、DWORD のいずれの型にもキャストしないでください。
ビットのテスト、ビットの設定とクリア、またはポインタの内容の操作のためにポインタを
キャストする必要がある場合は、UINT_PTR 型または INT_PTR 型を使用します。
これらの型は、32 ビット版の Windows と 64 ビット版の Windows の両方のポインタに合わせて
サイズが変更される整数型です (たとえば、32 ビット版の Windows の場合は ULONG 型、
64 ビット版の Windows の場合は _int64 型に変更されます)。
https://msdn.microsoft.com/ja-jp/library/aa384242.aspx

24 :デフォルトの名無しさん:2015/12/02(水) 18:07:06.08 ID:tKolsFeX.net
>>22
> ポインタのサイズと同様にそのサイズが環境に一致することを示すため
大体あってる。ポインタを安全に整数として扱うための型が INT_PTR。
64-bit 環境の Windows だと int 型が 4 バイト、ポインタが 8 バイトで
ポインタを int 型の変数に格納できない。
32-bit 環境で int 型にポインタを格納できたのはたまたま int 型とポインタ型の
サイズが一致していたから。

ついでに言うと c99 で intptr_t と uintptr_t 型が仕様として定義されている。
もしも今後 Windows 以外の環境への移植を考えるならそちらを使うようにすべき。

# どうでもいいけど、Windows SDK って何か変な型を定義してるよね
# DWORDLONG (UINT64, ULONG64, ULONGLONG 含めすべて uint64_t と同じ) とか
# HALF_PTR (intptr_t の半分のサイズ) とか LONG_PTR (INT_PTR との違いが分からん) とか

25 :デフォルトの名無しさん:2015/12/02(水) 18:33:27.47 ID:Cj5Jy42r.net
丁寧なご回答ありがとうございます。

DialogBox()APIの戻り値が、32bit時代?はint型だったと記憶しているのですが、
最近調べたら同戻り値がINT_PTR型になっていたため疑問を持ったという経緯なので、キャストしたいわけではありません。
最初INT_PTRという記述を見たとき、int型の変数へのポインタなのかな、と感じたので。でもそれだったらLPINTかなと思ったり。

>>24を見て何となく理解出来ました。
全てのアドレスを格納できる必要があるポインタは64bit環境では当然64bit、
ところがint型は64bit環境でも32bitのままだったんですね。

でも何でDialogBox()の戻り値はINT_PTRである必要があるんだろう。
32bit環境で32bit長、64bit環境で64bit長になってくれる変数が他に無かったのだろうか…

26 :24:2015/12/02(水) 18:47:49.06 ID:tKolsFeX.net
>>25
ポインタを含む任意の値を返すためだと思う。
DialogBox の戻り値は EndDialog の戻り値なわけだけど、
たとえば生成したダイアログ側から構造体を返したいとき、
戻り値が INT_PTR なら malloc とかで取ってきたアドレスをそのまま返せる。

> 32bit環境で32bit長、64bit環境で64bit長
大事なのは >>23 で言われてる通り「ポインタ型に等しい幅を持つ整数型」ということ。
いま自分が使っているシステムが主に 32/64-bit だからといって、
過去もずっとそうだったわけじゃないし将来ずっとこのままなわけでもない。
じゃあそのとき DialogBox の戻り値は何になって欲しいか、と言われれば、
「せめてポインタが格納できるサイズの型」ということになる。
それならどんな値でも返せるから。

27 :デフォルトの名無しさん:2015/12/02(水) 19:15:43.22 ID:Cj5Jy42r.net
>>26
な〜るほど、アドレスを返すこともあると考えれば、INT_PTRを使う事は無理矢理なことではなく、妥当なことに感じますね。
32bit時代にintで受けてたのが多少無理矢理だったとも言えるのかな。4バイトを受けられれば何でも良かったんでしょうけど。

# いっそ「PTR型」とか「SYS型」とかにして使う側でキャストするようにした方が誤解が無いんじゃないかと思ったり
# WinAPIでは昔から色々な型を使ってて覚えるのが面倒臭かったですね

28 :デフォルトの名無しさん:2015/12/05(土) 12:09:57.14 ID:XDnkwO5X.net
関数を作るとき、引数にポインタを渡すことで実質的な返り値にできるテクニックって普通に返り値を返すのとどう使い分けれるべきなんですか?
コードの可読性が下がる代わりに複数出力に対応できるっていう認識なんですが、わかりやすさとか保守性(人間の都合)以外に推奨される理由とかやめた方がいい理由はありますか?

int power(int a){return a*a;}

void power(int ain, int* aout){*aout=ain*ain;}
みたいなやつです

29 : ◆tAo.kQ2STk :2015/12/05(土) 16:27:33.05 ID:3X0n/q/1.net
>>28
他にも、構造体を返す代わりに構造体へのポインタを受け取っておいて一部だけ変更して返すとか
void move_up(Position* p, double distance) {p->y -= distance;}
デフォルトの値を受け取ってある条件で書き換えるが、書き換えた場合に引数として渡された元の値は不正になる場合とか
void my_realloc(void** p, size_t size) { *p = realloc(*p, size); } // 色々省いた!
幾つか使い道はあるけど。

やめたほうがいい理由として他には、純粋関数スタイルで書けなくなるってのがあるな。
add(a, b, &t);
mul(t, c, &d);
って書くのと
d = mul(add(a, b), c);
って書くのとは違うスタイルになるけど、後者を前者に直すのは簡単でもその逆は簡単じゃない。

30 :デフォルトの名無しさん:2015/12/05(土) 16:41:03.46 ID:WsL2Ug/J.net
>>28
計算結果を引数で受け取り、処理結果を戻り値で返す。

良くあるパターン。

31 :デフォルトの名無しさん:2015/12/05(土) 17:29:21.92 ID:KdBqlpoa.net
>>28
なんらかの制約があり仕方なく使わざるをえない場合のみ泣く泣く使うものであり推奨している個人や団体は存在しない

32 :デフォルトの名無しさん:2015/12/05(土) 17:44:53.67 ID:4CEShJeO.net
禁止する規約も見たことないけどな。
どちらがいい悪いじゃなくて、単一の戻り値を返す関数として書けない場合に
普通に使えばいいだろう。

33 :デフォルトの名無しさん:2015/12/05(土) 17:58:29.63 ID:KdBqlpoa.net
ひとつの戻り値に出来ない時点でおかしな事が起こってるか起こりつつある
複数の同じ型の返り値ならば本来そこで必要なものはコレクションだ
異なる型の複数の戻り値ならば本来そこで必要なのはそれを包含する別の型だ
必要な型が定義されていないという設計ミスの兆候から目を背けてはいけない
手抜きのタプルや参照渡しに逃げてはいけない

34 :デフォルトの名無しさん:2015/12/05(土) 18:44:26.87 ID:4CEShJeO.net
なんか変なこと言い出したぞ。
>>33個人の主張以外に一般に認められた規約/ガイドラインってあるかねぇ?

35 :デフォルトの名無しさん:2015/12/05(土) 18:47:22.55 ID:22zPQN1u.net
>>33
> 異なる型の複数の戻り値ならば本来そこで必要なのはそれを包含する別の型だ
> 手抜きのタプル
「それを包含する別の型」がタプルなんじゃないの

ていうか、個人的に問題になるのはエラー処理に関することが多い
long long int を返す関数で「失敗」を表すにはどうしたらいいのか、とか
で結局、戻り値(にしたかったもの)は引数で、エラーが起きたかどうかは戻り値で
返すことが多い
別に俺だけじゃなく、ぱっと思いつくとこだと zlib の compress なんかもそうだよね
deflate の結果は引数で返して、成功/失敗を戻り値で返す
snappy だと例外を投げるんだっけ

36 :デフォルトの名無しさん:2015/12/05(土) 20:59:15.88 ID:wHZuCpe8.net
返り値は全部ブールにして、値取得は引数で行うのをよく見るけど
これって普通なん?

37 :デフォルトの名無しさん:2015/12/05(土) 22:41:31.43 ID:3X0n/q/1.net
>>36
if文を使って成功したかどうか判定するんだから、そういう風に作ることも出来る。

構造体へのポインタを返すのでも同じ事が出来るけど。
if (auto p = foo()) {
printf("%d\n", p->value);
}
とか
auto p = foo();
if(!succeed(p)) {
return;
}
とか。

38 :デフォルトの名無しさん:2015/12/06(日) 03:26:24.33 ID:+ZBuFdaM.net
その構造体のメモリはいったいどこから…
スマートポインタとか使ってメモリがつがつ消費するのがイマドキの書き方なのかな

>>36
わりと普通。下手に「-1は失敗」とかやるよりシンプルで分かりやすい

39 :デフォルトの名無しさん:2015/12/06(日) 08:50:47.90 ID:cIZcNmeU.net
イマドキかどうかはともかく、
「スマートポインタを使う = メモリがつがつ消費する」
っていう >>38 の理解(そう読める)はどうなの

40 :デフォルトの名無しさん:2015/12/06(日) 13:45:34.39 ID:+ZBuFdaM.net
>>37みたいな使い方=メモリがつがつ消費する」ね
がつがつってのは容量的に沢山使うって話じゃなくて
無秩序にとか気軽にとか… うまい言葉が見つからないけど

41 :デフォルトの名無しさん:2015/12/06(日) 16:31:37.89 ID:iigA/d+A.net
boolにキャスト出来る構造体をifで受け取るのならどう?

42 :デフォルトの名無しさん:2015/12/06(日) 16:35:41.53 ID:4bjdt2kC.net
普通に構造体を返せばよいだけなのに,なぜそんなに凝ったことを推奨するのか?

43 :デフォルトの名無しさん:2015/12/06(日) 16:42:02.54 ID:w0JG1OnY.net
>>36
たまに見るね。Windowsの関数にそういうのが多い気がする。
fopenとfopen_sとか。
返り値の値域がint全体で、かつ、成功失敗を返す場合は
そういうのもありだと思う

44 :デフォルトの名無しさん:2015/12/06(日) 18:39:35.29 ID:Z7509Thm.net
>>28
戻り値がint型だからint型で受け取るのが良いけど
他の型で受け取れない(暗黙的な型変換)ってのがあるかな

あとその関数で言えば、数式の一部として利用できない
前者なら power(a)+b*2 のような式も書けるけど後者だと一回結果を受け取らないといけないよね
sqrtなんかもそう

45 :28:2015/12/07(月) 18:34:12.80 ID:PDqN2Ufp.net
ありがとうございます
色々使い方があるんですねm(_ _)m

46 :デフォルトの名無しさん:2015/12/08(火) 20:22:24.50 ID:BztczKM1.net
ヘッダ周りで混乱しています。ご教授おねがいします。
下のプログラムをそれぞれA.h, B.hのヘッダに書いて動作させるにはどうしたらいいでしょうか。


/*Aクラスの関数からBクラスのprivateメンバにアクセスする*/

class B;

class A {
int ia;
public:
void aFunc(B *b_ptr);
};

class B {
int ib;
public:
friend void A::aFunc(B *b_ptr);
};

void A::aFunc(B *b_ptr) {
b_ptr->ib;
}

47 :デフォルトの名無しさん:2015/12/08(火) 20:23:21.01 ID:BztczKM1.net
私が今書いているのが下のものです。
// A.h -----------------------------
#pragma once

#include "B.h"
class B;

class A {
int ia;
public:
void aFunc(B *b_ptr);
};

void A::aFunc(B *b_ptr) {
b_ptr->ib;
}
// -----------------------------------
// B.h -------------------------------
#pragma once

#include "A.h"
class A;

class B {
int ib;
public:
friend void A::aFunc(B *b_ptr);
};
// -------------------------------------
visual studio 2015で以下のエラーが出ています。
エラー C2248 'B::ib': private メンバー (クラス 'B' で宣言されている) にアクセスできません。 A.h 13行
エラー C2027 認識できない型 'A' が使われています。 B.h 9行

48 :デフォルトの名無しさん:2015/12/08(火) 21:33:55.11 ID:y1mdlUK+.net
以下のコードについて、Win+Mingw 上での結果と Ubuntu 上での結果が異なります

#include <iostream>
#include <fstream>
#include <system_error>
int main () {
using namespace std;
ifstream is;
is.exceptions(ifstream::failbit | ifstream::badbit);
try { is.open("xxx"); /* 存在しないファイル */ }
catch (ifstream::failure e) { cerr << "ifstream::failure" << endl; }
catch (system_error e) { cerr << "system_error" << endl; }
catch (exception e) { cerr << "exception" << endl; }
catch (...) { cerr << "other_error" << endl; }
return 0;
}

Win+Mingw
$ g++ --version
g++.exe (tdm64-1) 5.1.0
$ g++ -std=c++14 a.cc && ./a
exception

Ubuntu
$ g++ --version
g++ (Ubuntu 4.9.2-10ubuntu13) 4.9.2
$ g++ -std=c++14 a.cc && ./a.out
ifstream::failure

Windows 側で ifstream::failure や system_error を捕捉できていないのはなぜでしょうか?

49 :デフォルトの名無しさん:2015/12/08(火) 22:29:07.89 ID:2NgjJ1M0.net
>>47
// A.h -----------------------------
#pragma once

class B;
class A {
int ia;
public:
void aFunc(B *b_ptr);
};
// -----------------------------------
// B.h -------------------------------
#pragma once

#include "A.h"

class B {
int ib;
public:
friend void A::aFunc(B *b_ptr);
};
// -------------------------------------
// A.cpp
#include B.h
void A::aFunc(B *b_ptr) {
b_ptr->ib;
}

50 :47:2015/12/08(火) 23:52:34.51 ID:BztczKM1.net
>>49
ありがとうございます。

B.hではAクラスのメンバ情報が必要なのでA.hをインクルードして、
A.hではBクラスがあることが確認さえできればよいのでBクラスを前方宣言すればよいということですね。

A.hに定義を描いたのはファイルが少ない方が問題が簡単になるかと思ったからですが、
B.hをインクルードする必要がでてくるので返ってめんどうなんですね。

重ねて質問させていただきたいのですがこれが循環参照というものですか?
またA.hに定義を書いた場合エラーを回避する書き方はあるのでしょうか?

51 :デフォルトの名無しさん:2015/12/09(水) 00:26:24.16 ID:DdKTu+9h.net
>>50
ファイルが少ない方いいとか面倒とか気にするなら>>46のまま
依存関係にあるクラスなら無理して分けないほうが良いのでは?

ただ回避するだけのダメコードなら

// A.h -----------------------------
#pragma once

class B;
class A {
int ia;
public:
void aFunc(B *b_ptr);
};

#include "B.h"

void A::aFunc(B *b_ptr) {
b_ptr->ib;
}
// -----------------------------------
// B.h -------------------------------
#pragma once

class B {
int ib;
public:
friend void A::aFunc(B *b_ptr);
};
// -------------------------------------

52 :デフォルトの名無しさん:2015/12/09(水) 00:33:31.76 ID:DdKTu+9h.net
余計なお世話かもしれないが、
「これがやりたいから無理やりな回避するコードを書く」ってのは本末転倒なんじゃないかと思う
まあどうしようもないときってのもあるけど、自分ならクラス設計から見直すようにするけどね

53 :47:2015/12/09(水) 01:14:48.16 ID:MWRH+1zr.net
言い方が良くなかったようですみません。
私自身はファイル数も面倒も気にせずオーソドックスなコードをかきたいとおもっています。
ただ問題を考える際まず簡単なものから理解して複雑にしていくのがいいと思っています。
なのでここには私が考える最もシンプルなコードを書きました。
しかしその結果、私が考えた単純化(ファイル数を減らす)が逆に問題を複雑にしてしまっていた。ということに気づきましたという意味の発言でした。

最後の質問は単純な好奇心です。私はそのコードをいじってどうにかコンパイル通そうとしていたので、正解があるなら一応聞いておきたいなと。実用性のないコードをかかせてしまっせすみません。

> 依存関係にあるクラスなら無理して分けないほうが良いのでは?
今はじめてオブジェクト志向を取り入れて簡単なゲームを作っているのですが、どのようにクラスを割り振るのかまとめるのかということで四苦八苦しています。
今は基本に忠実に1つのクラスに1つのソースとヘッダで書いていますが、少し慣れたらまとめてみようと思います。

54 :デフォルトの名無しさん:2015/12/10(木) 23:47:39.86 ID:c+cFQUeV.net
ポインタについて教えてください

*hoge++ = 1;

こういう文があった場合、hogeに当初から入っているアドレスの次のアドレスに1を代入することになると思います
その場合、hogeに代入されているアドレス自体もプラス1されるのがふつうだと思いますが、環境によりプラス1されないこともあるのでしょうか?
よろしくお願いします

55 :デフォルトの名無しさん:2015/12/11(金) 00:15:27.78 ID:PPg536oa.net
当初入ってるアドレス先に1を代入して(=1)
それからアドレスをひとつ先に進める(++)んじゃないかな

環境に左右されないはずだけど、できれば
*hoge=1;
++hoge;
と二行に分けるのをオススメする

56 :デフォルトの名無しさん:2015/12/11(金) 06:47:49.34 ID:I09VPDH/.net
とりあえず括弧で優先順位つけろ

57 :デフォルトの名無しさん:2015/12/11(金) 06:57:19.50 ID:kB8+oJGq.net
括弧で解決するのかねえ。環境依存の要素はないし、極めて初歩の範疇だから
まずは入門書でも読んで入門した方がいい

58 :デフォルトの名無しさん:2015/12/11(金) 07:39:35.01 ID:EXbBnOrE.net
悩むような記述はしない
駆け出しに限ってトリッキーな記述を好む

59 :デフォルトの名無しさん:2015/12/11(金) 07:41:53.19 ID:0YKyOHUo.net
括弧といえば、三項演算子の優先順位がどうしても覚えられない
a - b ? c + d : e | f
みたいなの

60 :デフォルトの名無しさん:2015/12/11(金) 08:17:58.93 ID:MBFQhILY.net
ゲーム作ってるんですがダメージ計算式とかで稀に0除算が発生します
((a-b)*c)/((d*2)-e+f) のようにいくつかの変数が式に入っているので
計算の結果、割る値が0になっている場合がある といった具合です

0で割った場合は0になるようにしたいのですが、どうすればよいのでしょうか?
割る前にifで分岐するように書きなおすのは、面倒なので避けたいのですが…

61 :デフォルトの名無しさん:2015/12/11(金) 08:43:00.31 ID:gzGUt3Ym.net
チェックしろよ

62 :デフォルトの名無しさん:2015/12/11(金) 09:11:56.83 ID:cNzjvsZV.net
同じくチェックしろよとしか。
あとはまあ、適当な関数でも作るとか……?

63 :デフォルトの名無しさん:2015/12/11(金) 09:17:17.43 ID:h2+cx4oS.net
そういう演算規則の数値型のラッパーを作る
そして変数定義だけ書き直す

64 :デフォルトの名無しさん:2015/12/11(金) 09:17:45.85 ID:OYS2Ht5V.net
例外捕まえればチェックしないでも済む

65 :デフォルトの名無しさん:2015/12/11(金) 10:32:19.08 ID:MQP/fuYv.net
今回の要件では、除数が0なら結果も0と言うことだから例外ではフォロー仕切れんよ。
c++ならクラス作って割り算をオーバーロードかな。

66 :デフォルトの名無しさん:2015/12/11(金) 11:56:25.95 ID:OYS2Ht5V.net
例外処理ってC++の使えないアレだけじゃないんだよ

67 :デフォルトの名無しさん:2015/12/11(金) 13:14:14.85 ID:I09VPDH/.net
( ( ((d*2)-e+f) != 0 ) ? ( ((a-b)*c)/((d*2)-e+f) ) : (0) )
ってことか

68 :デフォルトの名無しさん:2015/12/11(金) 21:32:26.31 ID:OYS2Ht5V.net
C++の使えないアレでもできたわ
#include <functional>
int F(std::function< int(void) > func)
{
int v;
try {
v = func();
} catch (...) {
v = 0;
}
return v;
}
#define FF(e) F([&](){return (e); })
FF( ((a-b)*c)/((d*2)-e+f) );

69 :デフォルトの名無しさん:2015/12/12(土) 01:59:06.36 ID:Gz2IfgKr.net
素直に関数作ったらいいと思う

70 :デフォルトの名無しさん:2015/12/12(土) 05:59:21.93 ID:iSM6mGzV.net
書き直せなくなるまでゼロ除算を放置するなんて

71 :デフォルトの名無しさん:2015/12/12(土) 06:49:37.09 ID:zzgKuIEv.net
ゲームなので現実的にはありえない計算式なんだろ
0割で0にするというのも謎だけど、ゲームだからありなのかと思った

72 :デフォルトの名無しさん:2015/12/12(土) 08:22:05.54 ID:JwLrAiSP.net
分母に着目するんじゃなくて
そこに到達するまでのd, e, fのどれかにバグがあるって考えた方がいい

73 :デフォルトの名無しさん:2015/12/12(土) 11:18:45.83 ID:ZIa921ni.net
符号つきint同士の除算で、結果を常に負の∞に向かって丸めるにはどのようにすればいいでしょうか?
ただし、除数は常に0より大きい数です。

74 :デフォルトの名無しさん:2015/12/12(土) 11:53:16.77 ID:jiiw3kKP.net
「負の∞に向かって丸める」の意味がわからない

75 :73:2015/12/12(土) 12:05:54.12 ID:ZIa921ni.net
英語だと round toward minus infinity というところですか。
int同士の演算で丸めるというのが意味をなしていないのかもしれませんが、
結局は(実数としての)除算の結果を整数として得るのに−∞に近づくように、ということです。

76 :デフォルトの名無しさん:2015/12/12(土) 12:34:22.99 ID:l51bqpmT.net
計算結果が-3.1415となったら-4を得たいということ?floor関数だね

77 :デフォルトの名無しさん:2015/12/12(土) 14:27:51.11 ID:zzgKuIEv.net
被除数が負の場合、除数-1を引いてから割る

78 :デフォルトの名無しさん:2015/12/12(土) 16:35:31.33 ID:vifUVQ0p.net
浮動小数なら >>76
整数なら >>77
ちなみに >>77 の方法は「除数-1を*足して*から割る」とすると ceil 相当の動作になる

79 :デフォルトの名無しさん:2015/12/12(土) 16:41:35.71 ID:V2dsH5Kn.net
>>77
正整数同士の除算で端数は切り上げ、の応用技だね。
Nビットの情報を格納するのに必要なバイト数を求めるとき
ビット数に7を足してから8で割る感じ。
bytes = (bits + 7) / 8;


ところで、整数の除算で片方が負数の場合の結果は
「処理系定義」だって望洋さんのサイトに載ってる。

>>73 で除数は常に0より大きいと限定されてるから
被除数についての場合分け処理が必要になるかと。

80 :デフォルトの名無しさん:2015/12/12(土) 17:57:48.30 ID:vifUVQ0p.net
C って剰余の絶対値が最小になるように除算が決められてなかったっけ
それとも % 演算がそうなってるだけ?

81 :73:2015/12/12(土) 18:45:47.78 ID:ZIa921ni.net
ある程度試したところ>>77のやり方でうまくいきました。
動く仕組みも>>79でだいたい掴めました。
ふたりともありがとうございます。

82 :デフォルトの名無しさん:2015/12/12(土) 20:40:06.73 ID:zzgKuIEv.net
>>79
ウソを言わないように
少なくともc99以降は整数除算は「小数部は捨て」(すなわち0方向に丸め)と定義されている

83 :デフォルトの名無しさん:2015/12/12(土) 23:43:11.86 ID:DGmFor2Z.net
0除算に躓いていた若き日の僕に
手を差し伸べてくれたのは atan2(y,x) でした

84 :デフォルトの名無しさん:2015/12/13(日) 06:18:20.87 ID:dcJkyxKW.net
floor使えよ分かりやすいから

85 :デフォルトの名無しさん:2015/12/13(日) 06:18:49.92 ID:rQ+2OB8E.net
>>82
CでしかもC99以降なら、と処理系を限定すればその通り。

86 :デフォルトの名無しさん:2015/12/13(日) 07:36:52.20 ID:OeYxj6fv.net
>>85
限定しないならば、全ての処理系に対してって事だが。

87 :デフォルトの名無しさん:2015/12/13(日) 15:59:00.30 ID:NwtL3kT4.net
被除数が正ゼロ負に場合わけして処理するか、キャストして除算結果をfloorへ任せるか‥ まぁわかりやすさは人それぞれか

88 :デフォルトの名無しさん:2015/12/13(日) 17:57:12.22 ID:OeYxj6fv.net
負/非負だけで良い
(a - (b -1) * (a < 0)) / b
ゆとりはわかりにくいとか言い出すんだろうな。

89 :デフォルトの名無しさん:2015/12/13(日) 18:02:00.99 ID:4rlmjVEI.net
わかりにくいとまでは言わんが、if(a<0)で先に分岐したほうがすっきりしそう

90 :デフォルトの名無しさん:2015/12/13(日) 21:30:18.22 ID:H46hk94U.net
まあ、組み込みでもない限りは趣味の世界だな

91 :名無しさん@そうだ選挙に行こう:2015/12/14(月) 08:55:06.71 ID:7JmIVcUI.net
#include<stdio.h>

void rev_string(char s[]);

void rev_stringn(char s[][12], int n)
{
  int i,j,k;
  char swap[12];

  for(i=0;i<n;i++){
    while(s[i][k])
      k++;
    for(j=0;j<k;j++){
      swap[j] = s[i][j];
    }
    rev_string(swap);
    for(j=0;j<k;j++)
      s[i][j] = swap[j];
  }
}

92 :名無しさん@そうだ選挙に行こう:2015/12/14(月) 08:55:32.42 ID:7JmIVcUI.net
void rev_string(char s[])
{
  int i;
  int n = 0;
  while(s[n])
    n++;
  for(i=0;i<n/2;i++){
    char temp = s[i];
    s[i] = s[n-i-1];
    s[n-i-1] = temp;
  }
  s[n] = '\0';
  printf("%s \n",s);
}

93 :名無しさん@そうだ選挙に行こう:2015/12/14(月) 08:56:17.31 ID:7JmIVcUI.net
int main(void)
{
  int n;
  printf("配列の個数を入力せよ");
  scanf("%d",&n);

  char str[n][12];
  int i,j;

  printf("文字列を%d個入力せよ\n",n);
  for(i = 0;i<n;i++){
    printf("s[%d]:",i);
    scanf("%s",str[i]);
  }

  printf("反転した文字列は\n");

  rev_stringn(str,n);

  printf("である。\n");

  return 0;
}

このプログラムを実行するとセグメントエラーが出るのですが、なぜでしょうか
よろしくお願いします

94 :名無しさん@そうだ選挙に行こう:2015/12/14(月) 15:16:58.67 ID:lAggCEHS.net
>>91-93
見た感じ何かの課題っぽいね。
丸々教えちゃうのはタメにならないのでヒント。

一時文字列swap[]の生成部分を見直せ。

95 :名無しさん@そうだ選挙に行こう:2015/12/14(月) 15:42:18.02 ID:DSJzQQ/E.net
>>93
k 初期化
scanfで文字列を格納しようとしないで

96 :名無しさん@そうだ選挙に行こう:2015/12/14(月) 18:11:28.67 ID:1oZypuq3.net
>>94
>>95
出来ました
有難うございました
出来ると嬉しいですね

97 :名無しさん@そうだ選挙に行こう:2015/12/14(月) 18:30:13.04 ID:1oZypuq3.net
それと後学の為に聞いておきたいのですが
scanfで文字列取得してはダメなんですか?
getsで取得したほうが良いのでしょうか?

98 :名無しさん@そうだ選挙に行こう:2015/12/14(月) 18:38:14.34 ID:XU/HPkeH.net
どっちも使わないが正解かな
実用的なプログラムではxmlなど特定の形式のファイルを読み込むことが殆ど
そしてこういう形式のファイルは専用のライブラリがあるから標準の関数は使わない

99 :名無しさん@そうだ選挙に行こう:2015/12/14(月) 19:20:19.55 ID:lAggCEHS.net
>>97
例題の場合だと、文字列の入力時に11文字(12文字ではない)以上を
入力すると誤動作する。

gets()では事前に用意したバッファ容量以上の入力を拒絶できない。

scanf()なら対処可能だが割と面倒くさい。
詳しくは scanf のWikipediaに載ってる。

100 :99:2015/12/14(月) 19:46:15.05 ID:lAggCEHS.net
おおっと、「11文字以上」は間違い。
「11文字を超える」と書くべきだった。

例題の場合だと、文字列の入力時に11文字(12文字ではない)を超える
文字列を入力すると誤動作する。

総レス数 1013
307 KB
新着レスの表示

掲示板に戻る 全部 前100 次100 最新50
read.cgi ver 2014.07.20.01.SC 2014/07/20 D ★