次スレを立てる時は本文の1行目に以下を追加して下さい
!extend:on:vvvvv:1000:512
C++に関する質問やら話題やらはこちらへどうぞ。
ただし質問の前にはFAQに一通り目を通してください。
IDE (VC++など)などの使い方の質問はその開発環境のスレにお願いします。
前スレ
C++相談室 part131
http://mevius.2ch.net/test/read.cgi/tech/1501295308/
このスレもよろしくね。
【初心者歓迎】C/C++室 Ver.101【環境依存OK】
http://mevius.2ch.net/test/read.cgi/tech/1500329247/
■長いソースを貼るときはここへ。■
http://codepad.org/
https://ideone.com/
[C++ FAQ]
https://isocpp.org/wiki/faq/
http://www.bohyoh.com/CandCPP/FAQ/ (日本語)
VIPQ2_EXTDAT: default:vvvvv:1000:512:----: EXT was configured
探検
C++相談室 part132
■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん 転載ダメ (ワッチョイ faeb-wbjw)
2017/10/10(火) 00:11:34.01ID:nc/5PI4P0759デフォルトの名無しさん (ワッチョイ a104-0wpo)
2017/11/18(土) 16:50:13.11ID:R4dFDjUs0 >>757
reinterpret_castでいい予感。
reinterpret_castでいい予感。
760デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/18(土) 16:51:55.15ID:np1Yc2el0 >>755
ところでその検証、何年ぐらい時間かけていい話なの?
ところでその検証、何年ぐらい時間かけていい話なの?
761デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/18(土) 16:53:01.86ID:np1Yc2el0 >>759
未定義動作でも「いい」と言うなら、そう。
未定義動作でも「いい」と言うなら、そう。
762デフォルトの名無しさん (ワッチョイ a104-0wpo)
2017/11/18(土) 16:55:15.51ID:R4dFDjUs0 あー検証だからな。すまんかった。
763デフォルトの名無しさん (ワッチョイ f9b3-GXP8)
2017/11/18(土) 17:20:21.34ID:gZtBhbAH0 みなさま、レスありがとうございます。
>>757
memcpyでできそうです。ありがとうございます。
int main() {
double f = 0;
for (unsigned long long i = 0; i <= -1; ++i) {
void* fp = static_cast<void*>(&f);
void* ip = static_cast<void*>(&i);
std::memcpy(fp, ip, sizeof(i));
std::cout << f << std::endl;
}
system("pause");
}
>>760
そんなに時間かかるんですかね。。。
1週間ぐらいは覚悟してたんですが。
とりあえず回してみます。
>>757
memcpyでできそうです。ありがとうございます。
int main() {
double f = 0;
for (unsigned long long i = 0; i <= -1; ++i) {
void* fp = static_cast<void*>(&f);
void* ip = static_cast<void*>(&i);
std::memcpy(fp, ip, sizeof(i));
std::cout << f << std::endl;
}
system("pause");
}
>>760
そんなに時間かかるんですかね。。。
1週間ぐらいは覚悟してたんですが。
とりあえず回してみます。
764デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/18(土) 17:32:14.09ID:np1Yc2el0 >>763
https://randomascii.wordpress.com/2014/01/27/theres-only-four-billion-floatsso-test-them-all/
> ... you can test every float bit-pattern (all four billion!) in about ninety seconds. ...
32bit が 90 秒ほどで済ませられるそうな。 64bit だと単純計算で・・・ 735439.6... 年ぐらいかな。
1週間で済ませようと思ったら 38347922 並列ぐらいで走らせればよさそう。
検証する計算内容によっても変わるだろうけど、まぁがんばれ。
https://randomascii.wordpress.com/2014/01/27/theres-only-four-billion-floatsso-test-them-all/
> ... you can test every float bit-pattern (all four billion!) in about ninety seconds. ...
32bit が 90 秒ほどで済ませられるそうな。 64bit だと単純計算で・・・ 735439.6... 年ぐらいかな。
1週間で済ませようと思ったら 38347922 並列ぐらいで走らせればよさそう。
検証する計算内容によっても変わるだろうけど、まぁがんばれ。
765デフォルトの名無しさん (ワッチョイ a193-oo0Z)
2017/11/18(土) 17:35:34.11ID:hpuIg+Nf0 とりあえず範囲を絞って回してみて、
力任せの方法で受け入れられる処理時間なら単純なプログラムのまま、
時間かかりすぎるようなら先にプログラムを洗練させる、としないと。
力任せの方法で受け入れられる処理時間なら単純なプログラムのまま、
時間かかりすぎるようなら先にプログラムを洗練させる、としないと。
766デフォルトの名無しさん (ワッチョイ f9b3-GXP8)
2017/11/18(土) 17:56:05.12ID:gZtBhbAH0767デフォルトの名無しさん (ワッチョイ 0234-1gB9)
2017/11/18(土) 19:06:18.60ID:cx1PUhyJ0 isnan()でnanチェック入れたほうが良さそう
768デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/18(土) 19:44:12.36ID:euoYf0NO0769デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/18(土) 20:29:47.22ID:np1Yc2el0 >>768
type-based aliasing rule (strict aliasing rule) というものがあってな。
(詳しく調べると闇に落ちるから言語オタクでもなければ深堀りはおすすめしない。)
mempcy なら動作が定義されてるかというとそうでもないんで、
明示的に未定義といわれているかどうか(=最適化で問題を起こしやすいかどうか)の違いしかないんだけど。
type-based aliasing rule (strict aliasing rule) というものがあってな。
(詳しく調べると闇に落ちるから言語オタクでもなければ深堀りはおすすめしない。)
mempcy なら動作が定義されてるかというとそうでもないんで、
明示的に未定義といわれているかどうか(=最適化で問題を起こしやすいかどうか)の違いしかないんだけど。
770デフォルトの名無しさん (ワッチョイ 7efb-0Zlk)
2017/11/18(土) 20:40:55.67ID:b6ZSsfqz0 std::launder「そろそろ俺の出番だな」
771デフォルトの名無しさん (ワッチョイ c6e7-RjUU)
2017/11/18(土) 21:23:52.47ID:azZ7ClyG0 ここまでfrexpとldexpの話なし
772片山博文MZ ◆T6xkBnTXz7B0 (スフッ Sd22-EXIO)
2017/11/18(土) 21:57:24.41ID:QiNK1qRtd773片山博文MZ ◆T6xkBnTXz7B0 (スフッ Sd22-EXIO)
2017/11/18(土) 21:58:52.49ID:QiNK1qRtd 初回の例外というのがよくわからない。。。
774デフォルトの名無しさん (ワッチョイ 4178-kX9V)
2017/11/18(土) 22:06:57.57ID:asu2qdyg0 なんか古い書き方だから2000年ごろからの年季の入ったソースかと思ったら最近の奴なんだな
775片山博文MZ ◆T6xkBnTXz7B0 (スフッ Sd22-EXIO)
2017/11/18(土) 22:12:33.66ID:QiNK1qRtd776デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/18(土) 22:42:09.82ID:euoYf0NO0 >>769
調べたけどこれでいいのか?
https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule
これならreinterpret_cast関係ないじゃん。static_castにしたところで変わらん。
ただそれ以前に該当しないだろ。
「同一のメモリを違う型としてaliasしたときにコンパイラがそれに気づけず最適化で削除してしまう」という問題であり、
今回はそうではない。
> mempcy なら動作が定義されてるかというとそうでもないんで
ほんとか?それじゃmemcpyマトモに使えないじゃん。
void*は++で1増えるって仕様に決まったはずで、、、と思ったがこれがgcc拡張だという話があり、このことを言っているのか?
ならグダグダ言わずにCキャストで書けよもう、としか思わないが。
或いはC++的には許せないのかもしれんが static_cast<double>にしてしまうとかか?
調べたけどこれでいいのか?
https://stackoverflow.com/questions/98650/what-is-the-strict-aliasing-rule
これならreinterpret_cast関係ないじゃん。static_castにしたところで変わらん。
ただそれ以前に該当しないだろ。
「同一のメモリを違う型としてaliasしたときにコンパイラがそれに気づけず最適化で削除してしまう」という問題であり、
今回はそうではない。
> mempcy なら動作が定義されてるかというとそうでもないんで
ほんとか?それじゃmemcpyマトモに使えないじゃん。
void*は++で1増えるって仕様に決まったはずで、、、と思ったがこれがgcc拡張だという話があり、このことを言っているのか?
ならグダグダ言わずにCキャストで書けよもう、としか思わないが。
或いはC++的には許せないのかもしれんが static_cast<double>にしてしまうとかか?
777デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/18(土) 22:48:23.04ID:euoYf0NO0 すまんミスった
× static_cast<double>
○ static_cast<double*>
× static_cast<double>
○ static_cast<double*>
778デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/18(土) 23:20:13.09ID:np1Yc2el0 >>776
static_cast じゃコンパイル通らない。
"*(long long*)&f = i" は double 型のオブジェクトに long long 型の参照を通してアクセスしているので
未定義動作になる。結果は「最適化で削除してしまう」に限らず、何でもアリだよ。
これが「「同一のメモリを違う型としてalias」に該当しないという理屈も無いでしょ。
memcpy の結果が定義されてるのは、同じ型のオブジェクト間でのコピーだけだったかと。
違う型の間で memcpy した結果の値が実は定義されてるということなら実に興味深いので
ぜひ規格の該当箇所を示して欲しい。
この場合の C スタイルキャストの動作は reinterpret_cast に丸投げされるだけなので話は変わらないよ。
static_cast じゃコンパイル通らない。
"*(long long*)&f = i" は double 型のオブジェクトに long long 型の参照を通してアクセスしているので
未定義動作になる。結果は「最適化で削除してしまう」に限らず、何でもアリだよ。
これが「「同一のメモリを違う型としてalias」に該当しないという理屈も無いでしょ。
memcpy の結果が定義されてるのは、同じ型のオブジェクト間でのコピーだけだったかと。
違う型の間で memcpy した結果の値が実は定義されてるということなら実に興味深いので
ぜひ規格の該当箇所を示して欲しい。
この場合の C スタイルキャストの動作は reinterpret_cast に丸投げされるだけなので話は変わらないよ。
779デフォルトの名無しさん (ワッチョイ 1d79-Kvax)
2017/11/18(土) 23:37:48.32ID:5VdCNKN70 ここまでnextafter/nexttowardが出てきていない
780デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/18(土) 23:38:32.35ID:euoYf0NO0 >>778
> "*(long long*)&f = i" は double 型のオブジェクトに long long 型の参照を通してアクセスしているので
してないぞ。
それは「fのアドレスを(long long*)にキャスト(この時点でlong long*型)したアドレスに対しiを書き込め」
であって、つまり long long に long long を書いている。だからmovが出る。
逆に f = *(double*)&i; は double に double を書くから fmov が出る。
その後の最適化で変更されるのはまた別の話。
> static_cast じゃコンパイル通らない。
だったら最初から>>759の言うとおり、reinterpret_castでいいだろ。
> 違う型の間で memcpy した結果の値が実は定義されてる
void* と void* なんだから同じ型だろ。何言ってんだ?
お前、基本的に理解がずれてね?
> "*(long long*)&f = i" は double 型のオブジェクトに long long 型の参照を通してアクセスしているので
してないぞ。
それは「fのアドレスを(long long*)にキャスト(この時点でlong long*型)したアドレスに対しiを書き込め」
であって、つまり long long に long long を書いている。だからmovが出る。
逆に f = *(double*)&i; は double に double を書くから fmov が出る。
その後の最適化で変更されるのはまた別の話。
> static_cast じゃコンパイル通らない。
だったら最初から>>759の言うとおり、reinterpret_castでいいだろ。
> 違う型の間で memcpy した結果の値が実は定義されてる
void* と void* なんだから同じ型だろ。何言ってんだ?
お前、基本的に理解がずれてね?
781デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/18(土) 23:47:06.34ID:np1Yc2el0 >>780
なるほど、オブジェクトの型と式の型との区別がついてないんだね。
そこの理解無しで aliasing rule に関する話は無理だから、
C++ の規格を読み直すなりして区別が付くようになってからの出直しをおすすめする。
なるほど、オブジェクトの型と式の型との区別がついてないんだね。
そこの理解無しで aliasing rule に関する話は無理だから、
C++ の規格を読み直すなりして区別が付くようになってからの出直しをおすすめする。
782デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/18(土) 23:50:31.47ID:euoYf0NO0783デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/19(日) 00:03:31.90ID:xhmNfS4m0 >>782
そうなると GCC も「全く理解出来てない」ことになるねぇ。
https://wandbox.org/permlink/WMFUTpXAgs2oZuos
> prog.cc:5:17: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
> *(long long*)&f = i;
> ^
> prog.cc:6:18: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
> f = *(double*)&i;
> ^
そうなると GCC も「全く理解出来てない」ことになるねぇ。
https://wandbox.org/permlink/WMFUTpXAgs2oZuos
> prog.cc:5:17: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
> *(long long*)&f = i;
> ^
> prog.cc:6:18: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
> f = *(double*)&i;
> ^
784デフォルトの名無しさん (ワッチョイ c6e7-RjUU)
2017/11/19(日) 00:12:55.40ID:XAwzlQ9S0785デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 00:41:57.82ID:p3uF8GIb0 まあ未定義な動作がどこまで行っても未定義な動作であって(教条主義的には)悪なのは確かだが
>>784のリンク先のを読むと
>ストアによってPの値が変わる可能性を考慮しなくてはいけないからだ。
という理由で最適化できないケースがあるから考慮する代りに未定義動作ということにしますた!
というだけで、ストアによってPの値が変わらないなら特に問題を生じないように思える…
で、ストアによってPの値が変わるケースというのは
int main() {
P = (float*)&P; // このキャストによって zero_array の中で TBAA 違反となる
zero_array();
}
みたいな変態的なケースしかなさげ;
>>784のリンク先のを読むと
>ストアによってPの値が変わる可能性を考慮しなくてはいけないからだ。
という理由で最適化できないケースがあるから考慮する代りに未定義動作ということにしますた!
というだけで、ストアによってPの値が変わらないなら特に問題を生じないように思える…
で、ストアによってPの値が変わるケースというのは
int main() {
P = (float*)&P; // このキャストによって zero_array の中で TBAA 違反となる
zero_array();
}
みたいな変態的なケースしかなさげ;
786デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 00:54:18.30ID:SsMAbqSz0 >>784
答え書いてんじゃねーかよ。
> この種の未定義な振る舞いは、-fno-strict-aliasing フラグを指定することで無効にすることができ
つまり指定すれば万事解決だ。
ただその前にwarning出てても動作するとは思うが。
> この種の型の乱用はあまり一般的ではないので、標準委員会は、"妥当な" 型のキャストによる予期しない結果と引き換えに、大幅なパフォーマンス向上を選んだ。
これっていつから?LLVMに乗せた頃からっぽいが、、、日付や元URL見るかぎりC++11からか?
あとこれって、Cもか?
(Cでは俺が書いたようなキャストは常用されているから)
知っている人がいたらよろしく。
答え書いてんじゃねーかよ。
> この種の未定義な振る舞いは、-fno-strict-aliasing フラグを指定することで無効にすることができ
つまり指定すれば万事解決だ。
ただその前にwarning出てても動作するとは思うが。
> この種の型の乱用はあまり一般的ではないので、標準委員会は、"妥当な" 型のキャストによる予期しない結果と引き換えに、大幅なパフォーマンス向上を選んだ。
これっていつから?LLVMに乗せた頃からっぽいが、、、日付や元URL見るかぎりC++11からか?
あとこれって、Cもか?
(Cでは俺が書いたようなキャストは常用されているから)
知っている人がいたらよろしく。
787デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 01:21:45.70ID:p3uF8GIb0 つかmemset(buf, ch, nのbufって__restrictじゃなかったのか…
今知った……
今知った……
788デフォルトの名無しさん (ワッチョイ c6e7-RjUU)
2017/11/19(日) 01:24:03.10ID:XAwzlQ9S0 C89からずーっとそうだよ
お前が書いてるコードが動いてるのは、コンパイラがそうしないという保証を独自に与えているか(-fno-strict-aliasingはその一例)
さもなくばたまたま動いてるだけ
お前が書いてるコードが動いてるのは、コンパイラがそうしないという保証を独自に与えているか(-fno-strict-aliasingはその一例)
さもなくばたまたま動いてるだけ
789デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/19(日) 01:33:36.82ID:xhmNfS4m0 >>786
広く知れ渡ったのは gcc 2.95 で実際にそのルールに基づく最適化が行われるようになってからかな。
https://www.gnu.org/software/gcc/gcc-2.95/features.html
> - Type based alias analysis is enabled by default. ...
そこから数えてももう 20 年近く経つわけだが。
知らずにそんなキャスト常用してるなら是非悔い改めてくれ。
広く知れ渡ったのは gcc 2.95 で実際にそのルールに基づく最適化が行われるようになってからかな。
https://www.gnu.org/software/gcc/gcc-2.95/features.html
> - Type based alias analysis is enabled by default. ...
そこから数えてももう 20 年近く経つわけだが。
知らずにそんなキャスト常用してるなら是非悔い改めてくれ。
790デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 01:35:13.22ID:p3uF8GIb0 (ま、__restrictな形でしかポインタしか使わない漏れには関係ないし…
791デフォルトの名無しさん (ワッチョイ c6e7-RjUU)
2017/11/19(日) 01:37:52.26ID:XAwzlQ9S0 ちなみに-fno-strict-aliasing付けるとこんな基本的な最適化さえ出来なくなって
パフォーマンスが激悪化する可能性があるからな
それを完全に理解した上で万事解決だと言ってるならそれでもいいけどさ
int foo(double* pd){
int k = 42;
*pd = 666;
return k * 2;
}
-fno-strict-aliasingを付けた場合、戻り値を"84"に最適化することは出来ない
なぜならpdのアドレスが&kを指してるかもしれないから
(strict aliasing ruleが効いてればdouble*がintを指してたら未定義動作なのでケアする必要がなく最適化できる)
パフォーマンスが激悪化する可能性があるからな
それを完全に理解した上で万事解決だと言ってるならそれでもいいけどさ
int foo(double* pd){
int k = 42;
*pd = 666;
return k * 2;
}
-fno-strict-aliasingを付けた場合、戻り値を"84"に最適化することは出来ない
なぜならpdのアドレスが&kを指してるかもしれないから
(strict aliasing ruleが効いてればdouble*がintを指してたら未定義動作なのでケアする必要がなく最適化できる)
792デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/19(日) 01:42:54.83ID:xhmNfS4m0 >>791
引数で受け取った(有効な)ポインタが関数内のローカル変数を指すことは不可能だから、その例は最適化できるよ。
引数で受け取った(有効な)ポインタが関数内のローカル変数を指すことは不可能だから、その例は最適化できるよ。
793デフォルトの名無しさん (ワッチョイ c6e7-RjUU)
2017/11/19(日) 02:15:02.16ID:XAwzlQ9S0 有効なポインタならね
デタラメなポインタがたまたま&kを指してるかもしれない
普通はそんなのは未定義動作だからケアしないんだけどそれをケアしろって言うのが-fno-strict-aliasing
デタラメなポインタがたまたま&kを指してるかもしれない
普通はそんなのは未定義動作だからケアしないんだけどそれをケアしろって言うのが-fno-strict-aliasing
794デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 02:22:43.60ID:SsMAbqSz0 >>789
> mempcy なら動作が定義されてるかというとそうでもないんで (>>769)
これは間違いだろ。784内見る限り、
> Cは、このような型変換をmemcpyを使って実現することを要求している。
なら、memcpy使えば正しい結果が得られるはずだし、そうじゃないとコンパイラのバグになる。
つまり、>>763のコードは正しく動くはず、と読めるが。
ちなみに>>783のページで色々試してみた。(もし編集が残っているようならすまん)
全てgcc 7.2.0 で、結果は以下。
・CはC11/C11(GNU)の両方でwarinigも何もでない。
・C++はこの中の一番古いC++03/C++03(GNU)の両方でwarinigは出る。
ということはかなり昔からC++ではそうだった、ということだね。全く知らんかったわ。
ここら辺がCの連中がC++を嫌っているところなのかもしれない。
>>788
おお、サンクス、C++89からか。
俺環はVC++2008だからね。MS側が吸収してくれてるわけか。
>>789
いや俺環では問題ないしな。
つかたぶんこれC++の話で、上記試した限りCなら問題ないんだよ。
ただ俺はbetterCの人だから、まあ微妙なわけだが、、、VC++2017とかに移行するときは気をつけるよ。
さてそのリンク先
https://www.gnu.org/software/gcc/news/alias.html
も読んでみたが、つまり s->x_m[i] は s->a_m と型が違うから上書きしないはず、
だからループ内で毎回 s->a_m を取らずに前回の値をそのまま使っていい、ということらしい。(s->b_mも同様)
ただこれなら
for (unsigned long long i = 0; i <= -1; ++i) *(long long*)&f = i;
は確実に動くけどな。ここで端折られるのはfのアドレス確認 &f 部分だけだから。
ただしstackoverflowの連中は言っていることが少し違うから、もうちょっと確認が必要だが。
> mempcy なら動作が定義されてるかというとそうでもないんで (>>769)
これは間違いだろ。784内見る限り、
> Cは、このような型変換をmemcpyを使って実現することを要求している。
なら、memcpy使えば正しい結果が得られるはずだし、そうじゃないとコンパイラのバグになる。
つまり、>>763のコードは正しく動くはず、と読めるが。
ちなみに>>783のページで色々試してみた。(もし編集が残っているようならすまん)
全てgcc 7.2.0 で、結果は以下。
・CはC11/C11(GNU)の両方でwarinigも何もでない。
・C++はこの中の一番古いC++03/C++03(GNU)の両方でwarinigは出る。
ということはかなり昔からC++ではそうだった、ということだね。全く知らんかったわ。
ここら辺がCの連中がC++を嫌っているところなのかもしれない。
>>788
おお、サンクス、C++89からか。
俺環はVC++2008だからね。MS側が吸収してくれてるわけか。
>>789
いや俺環では問題ないしな。
つかたぶんこれC++の話で、上記試した限りCなら問題ないんだよ。
ただ俺はbetterCの人だから、まあ微妙なわけだが、、、VC++2017とかに移行するときは気をつけるよ。
さてそのリンク先
https://www.gnu.org/software/gcc/news/alias.html
も読んでみたが、つまり s->x_m[i] は s->a_m と型が違うから上書きしないはず、
だからループ内で毎回 s->a_m を取らずに前回の値をそのまま使っていい、ということらしい。(s->b_mも同様)
ただこれなら
for (unsigned long long i = 0; i <= -1; ++i) *(long long*)&f = i;
は確実に動くけどな。ここで端折られるのはfのアドレス確認 &f 部分だけだから。
ただしstackoverflowの連中は言っていることが少し違うから、もうちょっと確認が必要だが。
795デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/19(日) 02:26:53.00ID:xhmNfS4m0796デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 02:37:45.46ID:SsMAbqSz0 >>791
周回遅れですまんが俺には794に書いたとおり、
・型違いは全てmemcpy使え。
と読める。だから763のコードはOKだと。
>>791-793の内容は理解した。
さて再度だが、やはり以下は動くだろ。
for (unsigned long long i = 0; i <= -1; ++i) *(long long*)&f = i;
ここで問題なのは、「fがiのアドレスをさしてたら未定義動作(&f==&i等)」であって、
i をコピーしてやらない、ではない。
791-793の言い分どおりなら、これはwarningが出てるだけで全く問題なく動くはず。
ただしstackoverflowの連中はちょっと違うことを言っているが。
周回遅れですまんが俺には794に書いたとおり、
・型違いは全てmemcpy使え。
と読める。だから763のコードはOKだと。
>>791-793の内容は理解した。
さて再度だが、やはり以下は動くだろ。
for (unsigned long long i = 0; i <= -1; ++i) *(long long*)&f = i;
ここで問題なのは、「fがiのアドレスをさしてたら未定義動作(&f==&i等)」であって、
i をコピーしてやらない、ではない。
791-793の言い分どおりなら、これはwarningが出てるだけで全く問題なく動くはず。
ただしstackoverflowの連中はちょっと違うことを言っているが。
797デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/19(日) 02:42:26.05ID:xhmNfS4m0 >>794
C の aliasing rule には memcpy, memmove によって宣言型を持たない(たとえば
malloc で確保した)オブジェクトの型 (effective type) を変更できるという規定がある。
引用された「memcpyを使って実現することを要求している」はこのことだろう。
でも、 C++ にはこれに相当する規定が無い。
C の aliasing rule には memcpy, memmove によって宣言型を持たない(たとえば
malloc で確保した)オブジェクトの型 (effective type) を変更できるという規定がある。
引用された「memcpyを使って実現することを要求している」はこのことだろう。
でも、 C++ にはこれに相当する規定が無い。
798デフォルトの名無しさん (ワッチョイ 0233-2Rtq)
2017/11/19(日) 02:53:12.72ID:xhmNfS4m0 >>796
残念、まだ理解できてないよ。
答えは >778 にある。
> "*(long long*)&f = i" は double 型のオブジェクトに long long 型の参照を通してアクセスしているので
> 未定義動作になる。結果は「最適化で削除してしまう」に限らず、何でもアリだよ。
これ以上は規格見てからしゃべってくれ。
残念、まだ理解できてないよ。
答えは >778 にある。
> "*(long long*)&f = i" は double 型のオブジェクトに long long 型の参照を通してアクセスしているので
> 未定義動作になる。結果は「最適化で削除してしまう」に限らず、何でもアリだよ。
これ以上は規格見てからしゃべってくれ。
799デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 03:03:03.03ID:SsMAbqSz0800デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 06:07:15.51ID:p3uF8GIb0 未定義動作マジコエー;;(>>784のリンク先の次のページ
ttp://blog-ja.intransient.info/2011/05/c-23.html
ttp://blog-ja.intransient.info/2011/05/c-23.html
801デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 06:25:20.22ID:p3uF8GIb0 プロセス屋さんががんばってCPUを3年ごとに倍早くしてくれるのだから
我々ソフト屋は口を開けて待っているだけにして
最適化なんてやめてしまえば良いのに
我々が忙しく働くということは、それだけバグを産むということなのだ…!
我々ソフト屋は口を開けて待っているだけにして
最適化なんてやめてしまえば良いのに
我々が忙しく働くということは、それだけバグを産むということなのだ…!
802デフォルトの名無しさん (オッペケ Srd1-0Zlk)
2017/11/19(日) 07:18:18.83ID:mXpVaiBzr803デフォルトの名無しさん (ワッチョイ 82a4-Eq1o)
2017/11/19(日) 07:18:20.90ID:Rb2sIcHm0 CPUだけ速くなってもDRAMの速度が昔のままだ
.7CRなんて法則を持ち出すまでもなく
現実にCPU速度が飽和したと感じたことなどないはずだが
.7CRなんて法則を持ち出すまでもなく
現実にCPU速度が飽和したと感じたことなどないはずだが
804デフォルトの名無しさん (オッペケ Srd1-0Zlk)
2017/11/19(日) 07:23:52.01ID:mXpVaiBzr805デフォルトの名無しさん (ワッチョイ f9b3-GXP8)
2017/11/19(日) 08:50:45.23ID:OzmZfN1I0 >>768
読んでも分からないときは?
読んでも分からないときは?
806デフォルトの名無しさん (ワッチョイ 82a4-Eq1o)
2017/11/19(日) 10:12:41.15ID:Rb2sIcHm0807デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 13:02:38.85ID:SsMAbqSz0 >>795改造は-fno-strict-aliasing有り無しによらず動くコードが出た。詳細は以下。
https://godbolt.org/g/QaSwTn
-O3 -fno-strict-aliasing -std=c++14 -pedantic -Wall -Wextra で mov QWORD PTR [rsp+8], rbx (27,29行目)が出る。
-fno-strict-aliasing を切っても同じ mov 命令が出る。
だからこれはwarningが出ているだけで動くコードが出る。
このときのコードは以下。
void test() {
double f = 0;
for (long long i = 0; i <= 10; ++i) {
*(long long*)&f = i; // (A)
std::cout << f << std::endl; // (B)
}
}
https://godbolt.org/g/QaSwTn
-O3 -fno-strict-aliasing -std=c++14 -pedantic -Wall -Wextra で mov QWORD PTR [rsp+8], rbx (27,29行目)が出る。
-fno-strict-aliasing を切っても同じ mov 命令が出る。
だからこれはwarningが出ているだけで動くコードが出る。
このときのコードは以下。
void test() {
double f = 0;
for (long long i = 0; i <= 10; ++i) {
*(long long*)&f = i; // (A)
std::cout << f << std::endl; // (B)
}
}
808デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 13:04:16.49ID:SsMAbqSz0 >>798
なお上記のGCC結果、或いは以下GCCのドキュメントは読んだ。
(ついでに後出の仕様書もチラ見したが、やはり今のところ君の理解がずれてるという見解だ。)
https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Optimize-Options.html#index-fstrict_002daliasing-750
ここでは以下コードがアウトだと言っている。
union a_union {
int i;
double d;
};
int f() {
double d = 3.0; // (C)
return ((union a_union *) &d)->i; // (D)
}
アウトな理由だが、上記と794内URLによると、「『型違いのaliasはない』と仮定して最適化」する為であり、
つまり(C)はd名でdoubleに書き(D)はi名でint読み出しだから(C)と(D)は関係ない、
よって(C)はデッドコードでいきなり(D)の読み出ししてよし、ということらしい。
ただこれだとやはり上記(A)(B)は動く。(A)も(B)もfの読み書きであり、aliasして無いからだ。
この規定は「型違いの『aliasは』ないものとみなす」であり、aliasしてなければ関係ない。
今のところ見る限り、他の例も必ずalias(別名でアクセス)している。
なお正しくはunionを使え、ということらしい。>>763
まあ確かにunionはこれ用ではあるが、単発ならCキャストする奴が多いとは思う。
そもそもunionは撲滅対象だと思っていたのだが、これは意外だ。
(或いは仕様上 char*, unsigned char* については許可《どう見ても妥協だが》しているので、void*ではなくchar*にすればいい)
なお上記のGCC結果、或いは以下GCCのドキュメントは読んだ。
(ついでに後出の仕様書もチラ見したが、やはり今のところ君の理解がずれてるという見解だ。)
https://gcc.gnu.org/onlinedocs/gcc-4.4.3/gcc/Optimize-Options.html#index-fstrict_002daliasing-750
ここでは以下コードがアウトだと言っている。
union a_union {
int i;
double d;
};
int f() {
double d = 3.0; // (C)
return ((union a_union *) &d)->i; // (D)
}
アウトな理由だが、上記と794内URLによると、「『型違いのaliasはない』と仮定して最適化」する為であり、
つまり(C)はd名でdoubleに書き(D)はi名でint読み出しだから(C)と(D)は関係ない、
よって(C)はデッドコードでいきなり(D)の読み出ししてよし、ということらしい。
ただこれだとやはり上記(A)(B)は動く。(A)も(B)もfの読み書きであり、aliasして無いからだ。
この規定は「型違いの『aliasは』ないものとみなす」であり、aliasしてなければ関係ない。
今のところ見る限り、他の例も必ずalias(別名でアクセス)している。
なお正しくはunionを使え、ということらしい。>>763
まあ確かにunionはこれ用ではあるが、単発ならCキャストする奴が多いとは思う。
そもそもunionは撲滅対象だと思っていたのだが、これは意外だ。
(或いは仕様上 char*, unsigned char* については許可《どう見ても妥協だが》しているので、void*ではなくchar*にすればいい)
809デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 13:06:08.29ID:SsMAbqSz0 仕様書は以下でいいか?読み慣れてないからだいぶ推測が入るが、
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
俺の結論は以下かな。
・gccのは -fstrict-aliasing で、あくまで alias についてだが、仕様書内は alias なんて関係ない。
・fstrict-aliasing 出来る理由が3.10.10によるのなら、reinterpret_castの存在価値はなく、仕様書内に矛盾がある。
・おそらく reinterpret_cast 撲滅で union に書き換えろ、という方向か?
aliasってのは多分折衷案で、union 以外は全部アウトにしたいっぽい。
詳細は以下。
5.2.10 Reinterpret castでは特に妙なところはなし、型キャストは為される。
aliasについては3.10.10だが、reinterpret_castしてれば the dynamic type 扱いでアクセスに問題なし、と見る。
3.10.10.の注 54) The intent of this list is to specify those circumstances in which an object may or may not be aliased.
なんだから、やはりこれは alias されているかどうか?であって、アクセスできるかどうかではない。
ただしここを根拠に undefined behavior だから最適化してよし、としてるのはかなり強引で、
(というかここでalias云々がかなり唐突で、そもそもaliasの話をここではしていない)
(D)がreinterpret_cast扱いだというのなら仕様内に矛盾があることになる。
そしてこの解釈(=reinterpret_castされたものは the dynamic type ではなく undefied behaviorだからどうなってもよし)が通るのなら、
reinterpret_castの存在価値がなくなってしまうし、
aliasとかせこいことを言わず、reinterpret_cast相当のところは全部undefined扱いで削除していいことになる。
というか、多分コンパイラ側はこの主張で、これに対してユーザ側が反対し、
結果、 alias とかいう折衷案でごまかしているように読める。(既に書いたがaliasが唐突過ぎ)
確かに正しくはunionを使うべきであり、この流れだと将来的には reinterpret_cast は廃止で union しろってことになるのか?
しかし逆に言えば、C++89以来これで大して変わらないのなら、早々急に変わることもないか。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf
俺の結論は以下かな。
・gccのは -fstrict-aliasing で、あくまで alias についてだが、仕様書内は alias なんて関係ない。
・fstrict-aliasing 出来る理由が3.10.10によるのなら、reinterpret_castの存在価値はなく、仕様書内に矛盾がある。
・おそらく reinterpret_cast 撲滅で union に書き換えろ、という方向か?
aliasってのは多分折衷案で、union 以外は全部アウトにしたいっぽい。
詳細は以下。
5.2.10 Reinterpret castでは特に妙なところはなし、型キャストは為される。
aliasについては3.10.10だが、reinterpret_castしてれば the dynamic type 扱いでアクセスに問題なし、と見る。
3.10.10.の注 54) The intent of this list is to specify those circumstances in which an object may or may not be aliased.
なんだから、やはりこれは alias されているかどうか?であって、アクセスできるかどうかではない。
ただしここを根拠に undefined behavior だから最適化してよし、としてるのはかなり強引で、
(というかここでalias云々がかなり唐突で、そもそもaliasの話をここではしていない)
(D)がreinterpret_cast扱いだというのなら仕様内に矛盾があることになる。
そしてこの解釈(=reinterpret_castされたものは the dynamic type ではなく undefied behaviorだからどうなってもよし)が通るのなら、
reinterpret_castの存在価値がなくなってしまうし、
aliasとかせこいことを言わず、reinterpret_cast相当のところは全部undefined扱いで削除していいことになる。
というか、多分コンパイラ側はこの主張で、これに対してユーザ側が反対し、
結果、 alias とかいう折衷案でごまかしているように読める。(既に書いたがaliasが唐突過ぎ)
確かに正しくはunionを使うべきであり、この流れだと将来的には reinterpret_cast は廃止で union しろってことになるのか?
しかし逆に言えば、C++89以来これで大して変わらないのなら、早々急に変わることもないか。
810デフォルトの名無しさん (ワッチョイ e1b3-GXP8)
2017/11/19(日) 14:06:40.01ID:PnhOPMpK0 >>787
ポインタの引数が1つしかないのに__restrictつける意味ないからでしょ
ポインタの引数が1つしかないのに__restrictつける意味ないからでしょ
811デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 14:19:11.46ID:p3uF8GIb0 コンパイラがうまくType-Based Alias Analysis出来るケースをいくら列挙したところで
Type-Based Alias Analysisできないケースが簡単に生じることは否定できない事実じゃんヤバイじゃん?
unionの使用が解決策というのも語弊があって、unionのメンバのアドレスを取ってから関数foo()に渡す手順だと
foo()のコンパイル時には渡ってきた2つのポインタが、型が違うけど(ループ変数などの条件次第で)同じ領域を指す(ことがある)
かどうか(ループを実際に実行してみねば)判断つかないじゃん?→コンパイラは怖くてループをmemcpy()やmemset()に置き換えられない
つまりunionこそ別の翻訳単位に属する関数に下手な渡り方をするとaliasingのすくつと化す気配が微レ存
元を断つにはやっぱID:xhmNfS4m0やGCC様がおっしゃるように、
そもそも型の混同要因(つまりポインタのキャスト)を絶つか、最適化が効いてほしい関数でプログラマが明示的に__restrictするしか、
※ 個人の感想です
Type-Based Alias Analysisできないケースが簡単に生じることは否定できない事実じゃんヤバイじゃん?
unionの使用が解決策というのも語弊があって、unionのメンバのアドレスを取ってから関数foo()に渡す手順だと
foo()のコンパイル時には渡ってきた2つのポインタが、型が違うけど(ループ変数などの条件次第で)同じ領域を指す(ことがある)
かどうか(ループを実際に実行してみねば)判断つかないじゃん?→コンパイラは怖くてループをmemcpy()やmemset()に置き換えられない
つまりunionこそ別の翻訳単位に属する関数に下手な渡り方をするとaliasingのすくつと化す気配が微レ存
元を断つにはやっぱID:xhmNfS4m0やGCC様がおっしゃるように、
そもそも型の混同要因(つまりポインタのキャスト)を絶つか、最適化が効いてほしい関数でプログラマが明示的に__restrictするしか、
※ 個人の感想です
812デフォルトの名無しさん (ワッチョイ 0233-Wr28)
2017/11/19(日) 14:25:36.63ID:67VHGIrY0 >>808
> ただこれだとやはり上記(A)(B)は動く。(A)も(B)もfの読み書きであり、aliasして無いからだ。
どうも "alias" の有無を名前に基づいて考えてるみたいだけど、
C++ (ほか多くのプログラミング言語)の文脈ではソースコード中で使われる実際の名前は関係ないんだよ。
"*(long long*)&f = i;" は "auto p = (long long*)&f; *p = i;" と等価であり、
これらのうち名前をつけた後者だけがエイリアスの問題があるということはなく、
どちらも f が表すオブジェクトに対してエイリアスがある状態と言う。
(最適化器の気持ちになって考えればわかりやすいんじゃないかと思うんだけど・・・。)
3.10.10 の注が "alias" に言及しているのも、このルールが "aliasing rule" と
呼ばれるのもそういうこと。
> なお正しくはunionを使え、ということらしい。>>763
> まあ確かにunionはこれ用ではあるが、単発ならCキャストする奴が多いとは思う。
union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。
gcc は( -fstrict-aliasing の説明にもあるとおり)特別ルールを設けてある程度の保証を与えている状態。
https://gcc.gnu.org/bugs/#casting_and_optimization
> To fix the code above, you can use a union instead of a cast (note that this is a GCC extension which might not work with other compilers):
> ただこれだとやはり上記(A)(B)は動く。(A)も(B)もfの読み書きであり、aliasして無いからだ。
どうも "alias" の有無を名前に基づいて考えてるみたいだけど、
C++ (ほか多くのプログラミング言語)の文脈ではソースコード中で使われる実際の名前は関係ないんだよ。
"*(long long*)&f = i;" は "auto p = (long long*)&f; *p = i;" と等価であり、
これらのうち名前をつけた後者だけがエイリアスの問題があるということはなく、
どちらも f が表すオブジェクトに対してエイリアスがある状態と言う。
(最適化器の気持ちになって考えればわかりやすいんじゃないかと思うんだけど・・・。)
3.10.10 の注が "alias" に言及しているのも、このルールが "aliasing rule" と
呼ばれるのもそういうこと。
> なお正しくはunionを使え、ということらしい。>>763
> まあ確かにunionはこれ用ではあるが、単発ならCキャストする奴が多いとは思う。
union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。
gcc は( -fstrict-aliasing の説明にもあるとおり)特別ルールを設けてある程度の保証を与えている状態。
https://gcc.gnu.org/bugs/#casting_and_optimization
> To fix the code above, you can use a union instead of a cast (note that this is a GCC extension which might not work with other compilers):
813デフォルトの名無しさん (ワッチョイ 0233-Wr28)
2017/11/19(日) 14:26:49.64ID:67VHGIrY0 >>809
> ・fstrict-aliasing 出来る理由が3.10.10によるのなら、reinterpret_castの存在価値はなく、仕様書内に矛盾がある。
元の型に戻せば元通り使えることが保証されているので、変更できない既存ライブラリの型に情報を無理やりねじ込んだりするのには使える。
3.10 の例外により unsigned char* などによるオブジェクト表現への直接アクセスにも使える。
> aliasについては3.10.10だが、reinterpret_castしてれば the dynamic type 扱いでアクセスに問題なし、と見る。
まだオブジェクトの型 (dynamic type) と式の型との区別がついてないようだねぇ。
> ・fstrict-aliasing 出来る理由が3.10.10によるのなら、reinterpret_castの存在価値はなく、仕様書内に矛盾がある。
元の型に戻せば元通り使えることが保証されているので、変更できない既存ライブラリの型に情報を無理やりねじ込んだりするのには使える。
3.10 の例外により unsigned char* などによるオブジェクト表現への直接アクセスにも使える。
> aliasについては3.10.10だが、reinterpret_castしてれば the dynamic type 扱いでアクセスに問題なし、と見る。
まだオブジェクトの型 (dynamic type) と式の型との区別がついてないようだねぇ。
814デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 14:38:42.54ID:p3uF8GIb0 >>810
memset()にわたるbufが__restrictでないポインタでないということは、関数の中で
memset(p, 0, 1000);
...
memset(p, 0, 1000);
と2回呼んだとき、pが非__restrictだったりグローバル変数だったりするとバカ正直に2回memset()されてしまう…
また、memset()は該当しないが
一般論としてポインタの引数が1つしかなくとも大域変数経由で(一見別のエリアを指すように見える)ポインタを受け取るケースがあるので
1引数関数でも__restrictが要るケースがあるんじゃわ;
memset()にわたるbufが__restrictでないポインタでないということは、関数の中で
memset(p, 0, 1000);
...
memset(p, 0, 1000);
と2回呼んだとき、pが非__restrictだったりグローバル変数だったりするとバカ正直に2回memset()されてしまう…
また、memset()は該当しないが
一般論としてポインタの引数が1つしかなくとも大域変数経由で(一見別のエリアを指すように見える)ポインタを受け取るケースがあるので
1引数関数でも__restrictが要るケースがあるんじゃわ;
815デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 14:43:08.58ID:SsMAbqSz0 >>811
808のコードで言うとね、
union a_union {
int i;
double d;
};
int f() {
double d = 3.0; // (C)
return ((union a_union *) &d)->i; // (D)
}
がアウトで、
int f(a_union* u) {
u->d = 3.0; // (E)
return u->i; // (F)
}
にしろってことだよ多分。これは>>812内URL内容とも一致する。
>>812
と、ここまではいいとして、これもGCC拡張であり、
> union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。
これはマジなの?C++のunionのところを読めばいいのか?
> 最適化器の気持ちになって考えればわかりやすいんじゃないかと思うんだけど・・・
これの可能性も考えたんだが、これまで全ての例で必ず別名をつけられてる。
LLVMはあまり知らないが、LLVMにおいてはレジスタへの再代入は禁止のはずだから、
同じレジスタがずっと使われてて最適化器からも「同じだ」と見える可能性もあるよ。
808のコードで言うとね、
union a_union {
int i;
double d;
};
int f() {
double d = 3.0; // (C)
return ((union a_union *) &d)->i; // (D)
}
がアウトで、
int f(a_union* u) {
u->d = 3.0; // (E)
return u->i; // (F)
}
にしろってことだよ多分。これは>>812内URL内容とも一致する。
>>812
と、ここまではいいとして、これもGCC拡張であり、
> union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。
これはマジなの?C++のunionのところを読めばいいのか?
> 最適化器の気持ちになって考えればわかりやすいんじゃないかと思うんだけど・・・
これの可能性も考えたんだが、これまで全ての例で必ず別名をつけられてる。
LLVMはあまり知らないが、LLVMにおいてはレジスタへの再代入は禁止のはずだから、
同じレジスタがずっと使われてて最適化器からも「同じだ」と見える可能性もあるよ。
816デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 14:46:54.14ID:p3uF8GIb0 ごめ>>814の前半は思い過ごしかorz
別にmemset()側に__restrictは要りませんな…
別にmemset()側に__restrictは要りませんな…
817デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 14:52:43.00ID:SsMAbqSz0 >>813
3.10.10.4 a type that is the signed or unsigned type corresponding to the dynamic type of the object,
って言ってんだから基礎型も the dynamic type に含まれてると思うぞ。
> 変更できない既存ライブラリの型に情報を無理やりねじ込んだりするのには使える。
使えない。
reinterpret_castの結果がlvalueとして正当ではない、だからundefinedで何やってもおk、
というのが最適化していい根拠なんだろ。だったらreinterpret_castしたその値を使う時点で駄目だろ。
lvalueとして正当に使えると言うのなら、undefinedじゃないんだから最適化で削除しては駄目だ。
ただまあ、ここら辺を俺と君でやりあっても意味が無い。
おそらく20年前にガチで同じことが彼らによって既に為されているはず。
俺がコンパイラを作るわけでも無し、俺は現状確認だけでいいよ。
3.10.10.4 a type that is the signed or unsigned type corresponding to the dynamic type of the object,
って言ってんだから基礎型も the dynamic type に含まれてると思うぞ。
> 変更できない既存ライブラリの型に情報を無理やりねじ込んだりするのには使える。
使えない。
reinterpret_castの結果がlvalueとして正当ではない、だからundefinedで何やってもおk、
というのが最適化していい根拠なんだろ。だったらreinterpret_castしたその値を使う時点で駄目だろ。
lvalueとして正当に使えると言うのなら、undefinedじゃないんだから最適化で削除しては駄目だ。
ただまあ、ここら辺を俺と君でやりあっても意味が無い。
おそらく20年前にガチで同じことが彼らによって既に為されているはず。
俺がコンパイラを作るわけでも無し、俺は現状確認だけでいいよ。
818デフォルトの名無しさん (ワッチョイ e1b3-GXP8)
2017/11/19(日) 14:57:33.47ID:PnhOPMpK0 >>814>>816
>一般論としてポインタの引数が1つしかなくとも大域変数経由で
あ、そういうことか・・・
まぁmemset使ってそういう症状出るとしたら、呼び出し側のpでつければいいよね
自分は__restrictそんなに使い倒してないけど、C++の標準に入らないのかな
>一般論としてポインタの引数が1つしかなくとも大域変数経由で
あ、そういうことか・・・
まぁmemset使ってそういう症状出るとしたら、呼び出し側のpでつければいいよね
自分は__restrictそんなに使い倒してないけど、C++の標準に入らないのかな
819デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 15:03:35.17ID:xhmNfS4m0 >>817
これだけ言われてまだ dynamic type が何なのか読んでないとしか思えない発言が来るか。
https://timsong-cpp.github.io/cppwp/n4659/intro.defs#defns.dynamic.type
> reinterpret_castの結果がlvalueとして正当ではない、だからundefinedで何やってもおk、
> というのが最適化していい根拠なんだろ。だったらreinterpret_castしたその値を使う時点で駄目だろ。
ポインタの reinterpret_cast で型違いの結果を得ることは未定義動作にならないし、
それに * を適用して lvalue を得ることも未定義動作にはならない。
得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。
これだけ言われてまだ dynamic type が何なのか読んでないとしか思えない発言が来るか。
https://timsong-cpp.github.io/cppwp/n4659/intro.defs#defns.dynamic.type
> reinterpret_castの結果がlvalueとして正当ではない、だからundefinedで何やってもおk、
> というのが最適化していい根拠なんだろ。だったらreinterpret_castしたその値を使う時点で駄目だろ。
ポインタの reinterpret_cast で型違いの結果を得ることは未定義動作にならないし、
それに * を適用して lvalue を得ることも未定義動作にはならない。
得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。
820デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 15:04:02.65ID:p3uF8GIb0 >reinterpret_castの結果がlvalueとして正当ではない
えっ合法なんじゃ…
int x = 10;
char* p = reinterpret_cast<char*>(&x);
*p = 2; // *pがlvalueであるところの式
x = (int)*p; // 元の型へのキャストバック
printf("x=%d\n", x); // 2
多分最適化されると
printf("x=%d\n", 2);
になる
えっ合法なんじゃ…
int x = 10;
char* p = reinterpret_cast<char*>(&x);
*p = 2; // *pがlvalueであるところの式
x = (int)*p; // 元の型へのキャストバック
printf("x=%d\n", x); // 2
多分最適化されると
printf("x=%d\n", 2);
になる
821デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 15:19:05.40ID:SsMAbqSz0 >>812
> union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。
一応unionのところ(9.5)読んだ。これは書いてなかった。
ただしGCCが「独自拡張だ」って言ってんだからどこかにはあるのだとは思うが。
章番号分かればよろしく。まさか、書いて無いから未定義って奴か?
なお9.5.5ではanonymous union ってのが定義されてて、どうもこれでやれってことっぽい。
例は以下。
void f() {
union { int a; const char* p; };
a = 1;
p = "Jennifer";
}
> union で最後に書いたメンバと別のメンバを読み出すのも C++ では未定義動作だよ。
一応unionのところ(9.5)読んだ。これは書いてなかった。
ただしGCCが「独自拡張だ」って言ってんだからどこかにはあるのだとは思うが。
章番号分かればよろしく。まさか、書いて無いから未定義って奴か?
なお9.5.5ではanonymous union ってのが定義されてて、どうもこれでやれってことっぽい。
例は以下。
void f() {
union { int a; const char* p; };
a = 1;
p = "Jennifer";
}
822デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 15:22:01.05ID:p3uF8GIb0 dynamic_typeはdynamic_cast<>とかtypeidの実装がvtableを悪用した黒魔術なので使わなーい
それはそうとして、Type-Based Alias Analysisの障害となるaliasingだけことさら問題視するLLVMの人らのスタンスはフェアではないキモス
同じ型でもaliasingは起こそうと思えばいくらでも起こせるし、コンパイラはプログラマーが意図的にaliasingさせるケースが有り得るのではと
猜疑心にとらわれて十分な最適化ができないのは同じ
やっぱC++は関数型プログラミング言語にシフトすべき頃合い
それはそうとして、Type-Based Alias Analysisの障害となるaliasingだけことさら問題視するLLVMの人らのスタンスはフェアではないキモス
同じ型でもaliasingは起こそうと思えばいくらでも起こせるし、コンパイラはプログラマーが意図的にaliasingさせるケースが有り得るのではと
猜疑心にとらわれて十分な最適化ができないのは同じ
やっぱC++は関数型プログラミング言語にシフトすべき頃合い
823デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 15:27:33.98ID:SsMAbqSz0 >>819
3.10.10には the dynamic type と cv-qualified version of the dynamic type しかないのだが、
では double や long long は何型なのだ?
> 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。
ではその aliasing rule を読もう。何章だ?
なんとなく aliasing rule はコンパイラ側の仕様で、C++の仕様では無いと思うのだが。
3.10.10には the dynamic type と cv-qualified version of the dynamic type しかないのだが、
では double や long long は何型なのだ?
> 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。
ではその aliasing rule を読もう。何章だ?
なんとなく aliasing rule はコンパイラ側の仕様で、C++の仕様では無いと思うのだが。
824デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 15:35:56.40ID:xhmNfS4m0 >>823
なんでせっかくリンク貼られた定義を無視するの?(・・・英語まともに読めないならそう言ってね。)
dynamic type は式を評価した結果の属性であって型の分類ではない。
aliasing rule は basic.lval にあるルール "If a program attempts to access ... the behavior is undefined" を指す。
https://timsong-cpp.github.io/cppwp/n4659/basic.lval#8
なんでせっかくリンク貼られた定義を無視するの?(・・・英語まともに読めないならそう言ってね。)
dynamic type は式を評価した結果の属性であって型の分類ではない。
aliasing rule は basic.lval にあるルール "If a program attempts to access ... the behavior is undefined" を指す。
https://timsong-cpp.github.io/cppwp/n4659/basic.lval#8
825デフォルトの名無しさん (ワッチョイ c58a-iF25)
2017/11/19(日) 15:36:33.89ID:BMNBgd4s0 規格キチガイとの会話は不毛
ツルッツルピカピカ
ツルッツルピカピカ
826デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 15:39:23.48ID:SsMAbqSz0 >>822
違うぞ。
794内リンク読む限り、確かにこの最適化はフェアだし、使われていい。
というか、それ以前はポインタが一つでもあったら全く最適化が出来なくなっており、
確かにそれは問題視されてた。
だから標準化委員会がそっちを選んだ、というのは分かる話だ。
違う型でエイリアスすることはほぼないし。
問題は意図的にやりたいことが偶にあって、そのときにどう回避するかだよ。
763がこれに該当する。
違うぞ。
794内リンク読む限り、確かにこの最適化はフェアだし、使われていい。
というか、それ以前はポインタが一つでもあったら全く最適化が出来なくなっており、
確かにそれは問題視されてた。
だから標準化委員会がそっちを選んだ、というのは分かる話だ。
違う型でエイリアスすることはほぼないし。
問題は意図的にやりたいことが偶にあって、そのときにどう回避するかだよ。
763がこれに該当する。
827デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 15:51:01.10ID:xhmNfS4m0 >>826
現行の規格で保証される範囲でまともな方法を見出そうとしてるなら、苦労に見合う実りは得られないからやめとけと言っておく。
標準化委員会のおおかたもそんな認識だから bit_cast なんていう提案が好意的に進められている。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0476r1.html
現行の規格で保証される範囲でまともな方法を見出そうとしてるなら、苦労に見合う実りは得られないからやめとけと言っておく。
標準化委員会のおおかたもそんな認識だから bit_cast なんていう提案が好意的に進められている。
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0476r1.html
828デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 15:53:50.85ID:SsMAbqSz0 >>824
では最初から分かるようにそう言え。
こちらは仕様書を読むのが仕事ではないので、そもそも用語も知らない。見て分からなければそれまでの話だ。
つか、lvalue, rvalue もひどいが、 xvalue とかもでてきて、いよいよC++はどうしようもなくなりつつあるなと実感したよ。
Linusが嫌うわけだよこれは。
ただまあこれは本題でもない。 aliasing rule の確認の方が重要だ。
してそのリンク先、3.10.10と同じだ。
> 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。(>>819)
これはどこからそう取れるんだ?
reinterpret_castをした結果が正当なlvalueなら、それをデリファレンスした結果も正当なlvalueだろ。
この章にはどこにも”aliasしてる場合”なんて記述はない。
だらからここを根拠にするのがそもそもおかしいんだよ。
君が期待することがここに書いてあるとしたら、例えば以下になるべきなんだよ。
the dynamic type of the object IF THE OBJET IS NOT ALIASED,
とかね。でも実際はそうじゃない。
では最初から分かるようにそう言え。
こちらは仕様書を読むのが仕事ではないので、そもそも用語も知らない。見て分からなければそれまでの話だ。
つか、lvalue, rvalue もひどいが、 xvalue とかもでてきて、いよいよC++はどうしようもなくなりつつあるなと実感したよ。
Linusが嫌うわけだよこれは。
ただまあこれは本題でもない。 aliasing rule の確認の方が重要だ。
してそのリンク先、3.10.10と同じだ。
> 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある。(>>819)
これはどこからそう取れるんだ?
reinterpret_castをした結果が正当なlvalueなら、それをデリファレンスした結果も正当なlvalueだろ。
この章にはどこにも”aliasしてる場合”なんて記述はない。
だらからここを根拠にするのがそもそもおかしいんだよ。
君が期待することがここに書いてあるとしたら、例えば以下になるべきなんだよ。
the dynamic type of the object IF THE OBJET IS NOT ALIASED,
とかね。でも実際はそうじゃない。
829デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 16:10:52.86ID:SsMAbqSz0 >>827
つか、完全に暴走してるなこれは。
これならmemcpyと同じだし、
わざわざ別に作らずともmemcpyを正式に認めてCと同じ並びにしたほうがいい。
それ以前に reinterpret_cast が使われている関数内は自動的に -fno-strict-aliasing すればいいだけなんだが。
(関数単位でこの最適化を切る。ほぼ全てこれでいけるはず)
ただまあ、これが真面目に議論されているのなら、仕様書の文面や俺の感想はともかく、
君の言う通り、今のC++の仕様では対処する方法がない、ということなのだろうね。
つか、完全に暴走してるなこれは。
これならmemcpyと同じだし、
わざわざ別に作らずともmemcpyを正式に認めてCと同じ並びにしたほうがいい。
それ以前に reinterpret_cast が使われている関数内は自動的に -fno-strict-aliasing すればいいだけなんだが。
(関数単位でこの最適化を切る。ほぼ全てこれでいけるはず)
ただまあ、これが真面目に議論されているのなら、仕様書の文面や俺の感想はともかく、
君の言う通り、今のC++の仕様では対処する方法がない、ということなのだろうね。
830デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 16:11:41.87ID:xhmNfS4m0 >>828
"If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined"
これが lvalue (それ自体は未定義ではない)を通した「アクセス」を未定義とするルールとして読めないのだとしたら、もうどう説明しても無理だろう。
用語を知らないといいながら共通の定義を求めるのではなく開き直って勝手な解釈に基づく話を進められるようではまともな会話にもならない。
説明は諦める。
規格や先人の解説を読みなおすなりして誤りに気づいてもらえれば幸いだ。
https://www.google.com/search?q=aliasing+rule
"If a program attempts to access the stored value of an object through a glvalue of other than one of the following types the behavior is undefined"
これが lvalue (それ自体は未定義ではない)を通した「アクセス」を未定義とするルールとして読めないのだとしたら、もうどう説明しても無理だろう。
用語を知らないといいながら共通の定義を求めるのではなく開き直って勝手な解釈に基づく話を進められるようではまともな会話にもならない。
説明は諦める。
規格や先人の解説を読みなおすなりして誤りに気づいてもらえれば幸いだ。
https://www.google.com/search?q=aliasing+rule
831デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 16:30:16.51ID:SsMAbqSz0 >>830
ちげーよ。
俺は、reinterpret_castの結果が正当なlvalueなら、それはド頭の
the dynamic type of the object
に該当するから、
*(long long*)&f = i
はありだろ、と読んでるんだよ。そこは君も同じだろ。
> ポインタの reinterpret_cast で型違いの結果を得ることは未定義動作にならないし (>>819)
つまり (long long*)&f で long long* 型になるのはおk ←君の見解ね、俺も同意だが。
> それに * を適用して lvalue を得ることも未定義動作にはならない。
得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動 (>>819)
つまり、*(long long*)&f もおk ←これも君の見解ね、俺も同意で。
> 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある
ここが違う。
3.10.10には alias が云々って何も書いてないだろ。
しかも *(long long*)&f = i; は両方とも long long なんだから、「型違い」のaliasではないんだよ。
だからGCC等の -fstrict-aliasing には該当しない。
というのが文面からとれる意味だ。あくまで「文面」な。
ただまあ、実際にはそうじゃないんだろ。
ちげーよ。
俺は、reinterpret_castの結果が正当なlvalueなら、それはド頭の
the dynamic type of the object
に該当するから、
*(long long*)&f = i
はありだろ、と読んでるんだよ。そこは君も同じだろ。
> ポインタの reinterpret_cast で型違いの結果を得ることは未定義動作にならないし (>>819)
つまり (long long*)&f で long long* 型になるのはおk ←君の見解ね、俺も同意だが。
> それに * を適用して lvalue を得ることも未定義動作にはならない。
得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動 (>>819)
つまり、*(long long*)&f もおk ←これも君の見解ね、俺も同意で。
> 得られた lvalue を通したアクセスが aliasing rule に基づいて未定義動作となる可能性がある
ここが違う。
3.10.10には alias が云々って何も書いてないだろ。
しかも *(long long*)&f = i; は両方とも long long なんだから、「型違い」のaliasではないんだよ。
だからGCC等の -fstrict-aliasing には該当しない。
というのが文面からとれる意味だ。あくまで「文面」な。
ただまあ、実際にはそうじゃないんだろ。
832デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 16:33:08.86ID:SsMAbqSz0 ああすまん、ちょっと慌ててて余分なコピペされてるわ。
上記1回目の「得られた lvalue を通したアクセスが…」は余分で。
上記1回目の「得られた lvalue を通したアクセスが…」は余分で。
833デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 16:34:35.29ID:xhmNfS4m0 >>830
> 俺は、reinterpret_castの結果が正当なlvalueなら、それはド頭の
> the dynamic type of the object
> に該当するから、
> *(long long*)&f = i
> はありだろ、と読んでるんだよ。そこは君も同じだろ。
違うねぇ。
オブジェクトの型 dynamic type は式の型とは違うし、式の型の影響を受けるものじゃないんだよ。
何度も区別しろと言ったつもりだったんだけど。
> 俺は、reinterpret_castの結果が正当なlvalueなら、それはド頭の
> the dynamic type of the object
> に該当するから、
> *(long long*)&f = i
> はありだろ、と読んでるんだよ。そこは君も同じだろ。
違うねぇ。
オブジェクトの型 dynamic type は式の型とは違うし、式の型の影響を受けるものじゃないんだよ。
何度も区別しろと言ったつもりだったんだけど。
834デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 16:35:57.16ID:xhmNfS4m0 ごめん、アンカーミスった。 >833 は >831 宛てね。
835デフォルトの名無しさん (ワッチョイ 82ae-Eq1o)
2017/11/19(日) 16:43:31.03ID:7jEiMXMd0836デフォルトの名無しさん (オッペケ Srd1-0Zlk)
2017/11/19(日) 16:46:31.93ID:Q6cWJ/Rgr > *(long long*)&f で long long* 型になるのはおk
んなこたーない
doubleオブジェクトの領域にlong longでアクセスすることが未定義動作
んなこたーない
doubleオブジェクトの領域にlong longでアクセスすることが未定義動作
837デフォルトの名無しさん (ワッチョイ c6e7-RjUU)
2017/11/19(日) 17:22:20.65ID:XAwzlQ9S0 double f = 0;
と変数fを構築した時点で、「値0.0のdoubleオブジェクト」が作られてメモリに置かれるんだよ(規格で言うstored valueな)
それはスタック回収やdeleteで破壊されるまでずーーっとdoubleのままで、変わることはないの
外側でポインタや参照をどれだけいじくり回したって決して変わらないの
家の横に「←ここは馬小屋です」って看板を立てたって、その家は家のままだし、勝手に馬を入れて飼うのは未定義動作なんだよ
そろそろ理解したらどうなの
と変数fを構築した時点で、「値0.0のdoubleオブジェクト」が作られてメモリに置かれるんだよ(規格で言うstored valueな)
それはスタック回収やdeleteで破壊されるまでずーーっとdoubleのままで、変わることはないの
外側でポインタや参照をどれだけいじくり回したって決して変わらないの
家の横に「←ここは馬小屋です」って看板を立てたって、その家は家のままだし、勝手に馬を入れて飼うのは未定義動作なんだよ
そろそろ理解したらどうなの
838デフォルトの名無しさん (ワッチョイ c58a-iF25)
2017/11/19(日) 17:56:59.79ID:BMNBgd4s0 >>835
内容ある発言と言われても別にこんなのは規格をひっくり返して議論するようなことでないし
たぶん俺なら(little endianだとして)
union Double {
double v;
struct {
uint64_t f:52; // fraction
uint64_t e:11; // exponent
uint64_t s:1; // sign
};
};
とかにするかな、それで何の問題も起こらない
内容ある発言と言われても別にこんなのは規格をひっくり返して議論するようなことでないし
たぶん俺なら(little endianだとして)
union Double {
double v;
struct {
uint64_t f:52; // fraction
uint64_t e:11; // exponent
uint64_t s:1; // sign
};
};
とかにするかな、それで何の問題も起こらない
839デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 18:00:09.08ID:SsMAbqSz0 >>837
多分それが違うぞ。それはどこに書いてある?
少なくとも多くのCプログラマはそう思って無い。だから平気でキャストする。
そして830内ULRも読んだが、これも明示的なエイリアスがあるケースだ。
お前らが過度にびびって拡大解釈してるだけだろ。
多分それが違うぞ。それはどこに書いてある?
少なくとも多くのCプログラマはそう思って無い。だから平気でキャストする。
そして830内ULRも読んだが、これも明示的なエイリアスがあるケースだ。
お前らが過度にびびって拡大解釈してるだけだろ。
840デフォルトの名無しさん (ワッチョイ 82ae-Eq1o)
2017/11/19(日) 18:11:47.43ID:7jEiMXMd0 あー、こいつcast-as-lvalueに完全に洗脳されている手合いかw
841デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 18:14:47.74ID:xhmNfS4m0 >>839
https://timsong-cpp.github.io/cppwp/n4659/intro.object#1
> ... The properties of an object are determined when the object is created. ... An object has a type. ...
今度からは少なくとも自分でどこをどう探したかぐらい示そうな。
https://timsong-cpp.github.io/cppwp/n4659/intro.object#1
> ... The properties of an object are determined when the object is created. ... An object has a type. ...
今度からは少なくとも自分でどこをどう探したかぐらい示そうな。
842デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 18:31:26.29ID:SsMAbqSz0 >>841
嘘つけ。キャストした場合についてはどこにも書いてない。
型が普遍なんてのは、君が勝手に思い込んでいるだけだ。
というか、いわゆる「強い型」ってのはそうらしいが、C++はそうじゃないだろ。
ちなみに俺も反論を用意してたところだ。
https://godbolt.org/g/viYhGj
中身は795の場所で、ついでだから f = *(double*)&i; を試した。
予想通りこちらはfmov(movsd)が出た。(最適化は切ってある)
つまり、俺が768で言ったように、
*(long long*)&f = i; // mov命令でコピー
または
f = *(double*)&i; // fmov命令でコピー
になるんだよ。少なくともgccはキャストされればその型だと認識している。
君はこれを矛盾無く説明出来ないだろ。
嘘つけ。キャストした場合についてはどこにも書いてない。
型が普遍なんてのは、君が勝手に思い込んでいるだけだ。
というか、いわゆる「強い型」ってのはそうらしいが、C++はそうじゃないだろ。
ちなみに俺も反論を用意してたところだ。
https://godbolt.org/g/viYhGj
中身は795の場所で、ついでだから f = *(double*)&i; を試した。
予想通りこちらはfmov(movsd)が出た。(最適化は切ってある)
つまり、俺が768で言ったように、
*(long long*)&f = i; // mov命令でコピー
または
f = *(double*)&i; // fmov命令でコピー
になるんだよ。少なくともgccはキャストされればその型だと認識している。
君はこれを矛盾無く説明出来ないだろ。
843デフォルトの名無しさん (オッペケ Srd1-0Zlk)
2017/11/19(日) 18:51:00.89ID:Q6cWJ/Rgr >キャストした場合についてはどこにも書いてない
はて、N4700の6.10/p8ほぼそのままの文面が少し上に貼り付けてあったような…
>>821
N4700 3.9, 4.5/p1, 6.8全般, 6.10/p8, 12.3/p1, 12.3/p(5.3), その他「launder」が登場する記述全般
はて、N4700の6.10/p8ほぼそのままの文面が少し上に貼り付けてあったような…
>>821
N4700 3.9, 4.5/p1, 6.8全般, 6.10/p8, 12.3/p1, 12.3/p(5.3), その他「launder」が登場する記述全般
844デフォルトの名無しさん (ワッチョイ 02bd-VFQ0)
2017/11/19(日) 18:52:07.63ID:p3uF8GIb0 正しいそうなコードが吐かれたことは未定義動作でないという証拠には全くならない
なぜなら未定義動作というのは
コンパイル時のエラー、実行時のエラー(または例外)、一見正常っぽく気体通り動く、その他、
というあらゆる事象を包含し得るので、、、
もちろんコンパイラの変更で(ことによったらコンパイル条件の変更だけでも)
ある日突然狂ったコードが吐かれる危険性があるが
そうなっても未定義動作をプログラムした人の責任
よって現時点で正しいげなコードが吐かれることをいかに力説しても無駄で、
規格の矛盾の指摘にはつながらない
なぜなら未定義動作というのは
コンパイル時のエラー、実行時のエラー(または例外)、一見正常っぽく気体通り動く、その他、
というあらゆる事象を包含し得るので、、、
もちろんコンパイラの変更で(ことによったらコンパイル条件の変更だけでも)
ある日突然狂ったコードが吐かれる危険性があるが
そうなっても未定義動作をプログラムした人の責任
よって現時点で正しいげなコードが吐かれることをいかに力説しても無駄で、
規格の矛盾の指摘にはつながらない
845デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 18:53:33.74ID:xhmNfS4m0 >>842
オブジェクトの型に関与しない操作についていちいち記述があるわけないだろ。
まさか「〜によりオブジェクトの方は変わらない」とかの記述が全演算子&標準関数その他諸々について必要だ
なんて言うわけじゃないよね?
未定義動作の結果はなんでもアリだと言っただろう。
その結果(想定の命令コードが生成されたこと)が未定義動作の結果のひとつだとして、何の矛盾も無い。
オブジェクトの型に関与しない操作についていちいち記述があるわけないだろ。
まさか「〜によりオブジェクトの方は変わらない」とかの記述が全演算子&標準関数その他諸々について必要だ
なんて言うわけじゃないよね?
未定義動作の結果はなんでもアリだと言っただろう。
その結果(想定の命令コードが生成されたこと)が未定義動作の結果のひとつだとして、何の矛盾も無い。
846片山博文MZ ◆T6xkBnTXz7B0 (ワッチョイ f9b3-HT85)
2017/11/19(日) 19:03:59.08ID:R56+Z6E80 inline const self_type *const_this()
{
return this;
}
template <typename T_TYPE>
inline T_TYPE *drop_const(const T_TYPE *obj)
{
return const_cast<T_TYPE *>(obj);
}
{
return this;
}
template <typename T_TYPE>
inline T_TYPE *drop_const(const T_TYPE *obj)
{
return const_cast<T_TYPE *>(obj);
}
847デフォルトの名無しさん (ワッチョイ f9b3-AWKa)
2017/11/19(日) 19:04:38.54ID:RgqRbH7C0 ソースが仕様、ソース読めってやつか。
848デフォルトの名無しさん (ワッチョイ 82ae-Eq1o)
2017/11/19(日) 19:25:00.73ID:7jEiMXMd0 そう言って居直るやつは問題だが
ソースを読まない言い訳にするやつもダメ
腐敗は両岸から起きうることだ
ソースを読まない言い訳にするやつもダメ
腐敗は両岸から起きうることだ
849デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 19:53:33.03ID:SsMAbqSz0 >>844-845
うむ。それは一理ある。
>>845
では逆から行こう。reiniterpret_castのど頭、
> 5.2.10 Reinterpret cast
> 1. The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T.
vをTに型変換したのが結果だとそのまま書いてある。
これはどう解釈すれば、「型はどうやっても変更できない」と取れるのだ?
さすがに無理だろ。
> 7. An object pointer can be explicitly converted to an object pointer of a different type.
これも型を変更できると読めるが。そして再び1に戻ると、
> 1. ---- If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue;
つまり当然有効なlvalueであり、デリファレンスも可能だ。
だからキャストを反映してmovなりfmovが出るのだ。
違うか?
君が言うようにメモリ上の型が普遍なら、どうやっても i には fmov が出ては駄目だろ。
(と思ったが、君は837ではないのか、、、)
うむ。それは一理ある。
>>845
では逆から行こう。reiniterpret_castのど頭、
> 5.2.10 Reinterpret cast
> 1. The result of the expression reinterpret_cast<T>(v) is the result of converting the expression v to type T.
vをTに型変換したのが結果だとそのまま書いてある。
これはどう解釈すれば、「型はどうやっても変更できない」と取れるのだ?
さすがに無理だろ。
> 7. An object pointer can be explicitly converted to an object pointer of a different type.
これも型を変更できると読めるが。そして再び1に戻ると、
> 1. ---- If T is an lvalue reference type or an rvalue reference to function type, the result is an lvalue;
つまり当然有効なlvalueであり、デリファレンスも可能だ。
だからキャストを反映してmovなりfmovが出るのだ。
違うか?
君が言うようにメモリ上の型が普遍なら、どうやっても i には fmov が出ては駄目だろ。
(と思ったが、君は837ではないのか、、、)
850デフォルトの名無しさん (ワッチョイ 82ae-Eq1o)
2017/11/19(日) 20:02:38.24ID:7jEiMXMd0851デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 20:09:33.36ID:xhmNfS4m0 >>849
> これはどう解釈すれば、「型はどうやっても変更できない」と取れるのだ?
式の型 (static type) は変わるが、オブジェクトの型 (dynamic type) は変わらない。
> 君が言うようにメモリ上の型が普遍なら、どうやっても i には fmov が出ては駄目だろ。
未定義動作ならなんでもアリだと言った。
> これはどう解釈すれば、「型はどうやっても変更できない」と取れるのだ?
式の型 (static type) は変わるが、オブジェクトの型 (dynamic type) は変わらない。
> 君が言うようにメモリ上の型が普遍なら、どうやっても i には fmov が出ては駄目だろ。
未定義動作ならなんでもアリだと言った。
852デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 20:15:36.23ID:SsMAbqSz0 >>851
それで突っぱねるのなら平行線だね。
俺は仕様書に詳しいわけでは無いから動作から説明するしかない。
君は仕様書には詳しいようだが、キャストした場合にも型が変更されないという記述を出して来れない。
ま、デッドロックだ。
とはいえ状況は色々分かったよ。ありがとう。
それで突っぱねるのなら平行線だね。
俺は仕様書に詳しいわけでは無いから動作から説明するしかない。
君は仕様書には詳しいようだが、キャストした場合にも型が変更されないという記述を出して来れない。
ま、デッドロックだ。
とはいえ状況は色々分かったよ。ありがとう。
853デフォルトの名無しさん (オッペケ Srd1-0Zlk)
2017/11/19(日) 20:42:27.06ID:Q6cWJ/Rgr >つまり当然有効なlvalueであり、デリファレンスも可能だ。
仕様を引用して説明されてもこのとんちんかんな発言を繰り返すあたり、
知らないから間違えているのではなくオツムが悪いので必然的に無知になったと言うことに>>851は気付くべき
仕様を引用して説明されてもこのとんちんかんな発言を繰り返すあたり、
知らないから間違えているのではなくオツムが悪いので必然的に無知になったと言うことに>>851は気付くべき
854デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 20:47:51.98ID:xhmNfS4m0 >>852
> 俺は仕様書に詳しいわけでは無いから動作から説明するしかない。
なら↓お前の理解に基づいてこの動作を説明できるか試してみるといいかもしれない。
https://wandbox.org/permlink/2aKzO4VN3KRDB6Gu
> 君は仕様書には詳しいようだが、キャストした場合にも型が変更されないという記述を出して来れない。
式の型 (static type) とオブジェクトの型 (dynamic type) は別物だという客観的な
前提 [intro.defs] を素直に読みさえすれば何度も見えてるはずなんだけどな。
> 俺は仕様書に詳しいわけでは無いから動作から説明するしかない。
なら↓お前の理解に基づいてこの動作を説明できるか試してみるといいかもしれない。
https://wandbox.org/permlink/2aKzO4VN3KRDB6Gu
> 君は仕様書には詳しいようだが、キャストした場合にも型が変更されないという記述を出して来れない。
式の型 (static type) とオブジェクトの型 (dynamic type) は別物だという客観的な
前提 [intro.defs] を素直に読みさえすれば何度も見えてるはずなんだけどな。
855デフォルトの名無しさん (ワッチョイ c6e7-RjUU)
2017/11/19(日) 20:54:00.37ID:XAwzlQ9S0 こいつわかってて引っ掻き回してるだけのような気がするわ
そうじゃなかったら馬鹿すぎる
そうじゃなかったら馬鹿すぎる
856デフォルトの名無しさん (ワッチョイ 02e7-GXP8)
2017/11/19(日) 21:10:07.51ID:JvH46D6m0 ある型の変数を入力として、別の型にキャストされた値を返すのはそりゃできるだろう
元の変数の型を変えることはそりゃ無理だろう
元の変数の型を変えることはそりゃ無理だろう
857デフォルトの名無しさん (ワッチョイ a19f-RjUU)
2017/11/19(日) 21:20:19.91ID:SsMAbqSz0858デフォルトの名無しさん (ワッチョイ 0233-dUYE)
2017/11/19(日) 21:40:24.30ID:xhmNfS4m0 >>857
お前の中でどういう理解になっているかは把握できていない。
その答えからすると、
"*(long long*)&f = i;" なら未定義動作にならないけど "auto p = (long long*)&f; *p = i;" なら未定義動作になる、
という理解なのかな。まぁそんなことは無いんだけどさ。
お前の中でどういう理解になっているかは把握できていない。
その答えからすると、
"*(long long*)&f = i;" なら未定義動作にならないけど "auto p = (long long*)&f; *p = i;" なら未定義動作になる、
という理解なのかな。まぁそんなことは無いんだけどさ。
■ このスレッドは過去ログ倉庫に格納されています
ニュース
- 東京都「都民の税金1.5兆円が国に奪われている」「全国に分配されている」に地方民ブチギレ [Hitzeschleier★]
- 高市首相の答弁書に「台湾有事答えない」と明記 存立危機発言当時 [蚤の市★]
- 「もうキモくてキモくて…」29歳女性が語る“おぢアタック”の実態。「俺ならイケるかも」年下女性を狙う勘違い中年男性に共通点が★4 [Hitzeschleier★]
- JA全農が「新おこめ券」…来年9月末の有効期限を新設、必要経費のみ上乗せ [蚤の市★]
- 【おこめ券】鈴木憲和農相 小泉前農相の備蓄米放出を“反省”「備蓄の円滑な運営を図ってまいります」 [Hitzeschleier★]
- 1人3千円の食品高騰対策、何に使える? あいまいなまま衆院通過 [蚤の市★]
- 【悲報】新米、全く売れなくて倉庫が満杯になってしまうwwwwwwwwwwwwwwwwwwww [802034645]
- トランプ、G7に代わるcore 5を発表 [805596214]
- はいはい
- 不眠症あるあるだけど眠たすぎて体調が良くない
- 【実況】博衣こよりのえちえちダンガンロンパ2🧪★5
- 【悲報】日本共産党、ツイッター速報にブチギレ法的措置WWWWWWWWWWWWWWWWWWWWWWWWWWWW [935793931]
