C言語なら俺に聞け 156

■ このスレッドは過去ログ倉庫に格納されています
1デフォルトの名無しさん (ワッチョイ 9bb7-/QqT)
垢版 |
2020/09/28(月) 14:41:30.00ID:QxfbhGyV0
!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言語なら俺に聞け 155
https://mevius.5ch.net/test/read.cgi/tech/1589120427/
VIPQ2_EXTDAT: checked:vvvvv:1000:512:: EXT was configured
2020/09/28(月) 17:15:25.66ID:VnC2vdM30
2get
2020/09/28(月) 18:59:35.35ID:ZZCh9OIz0
https://mevius.5ch.net/test/read.cgi/tech/1589120427/979
スタートアップを差し替えられるのは MS-DOS 時代の bcc または msc6(msvc6 とは違います!!!) くらいしか思い浮かばないのです…
4デフォルトの名無しさん (ワッチョイ 12ad-4LA+)
垢版 |
2020/09/29(火) 04:43:56.48ID:EnsnwIhp0
リンカでリンクすれば良いだけでは?
2020/09/29(火) 08:52:38.84ID:Pb7kfi6i0
gccなんかld -Tでどうにでもできるやん
6デフォルトの名無しさん (ワッチョイ b37c-N+m6)
垢版 |
2020/10/04(日) 09:52:20.51ID:sdY50qgq0
ttps://ideone.com/FVBJ8Q
最後の結果が納得いかないのですが
こういうものなのでしょうか?
7デフォルトの名無しさん (ワッチョイ ffad-EdVv)
垢版 |
2020/10/04(日) 13:02:04.66ID:4IGvE5yV0
>>6
内部で2進数になっててそれを10進数に変換しているので仕方がない。
完全な形でなんとかしたい場合は内部で10進数で保持したり計算したりしてくれるライブラリを使ってそれ用にプログラムを作るしかない。
自分で工夫してやる場合は整数で計算後に割るとかだな。
2020/10/04(日) 13:05:33.55ID:jSKQ3LlrF
%f って四捨五入してる訳じゃないんです?
2020/10/04(日) 14:51:56.18ID:cq4wRGXQM
切り捨てじゃない?
2020/10/04(日) 15:38:21.66ID:LHD68+0w0
そこでCOBOLですよ。
やはり初心者にはCOBOL
11デフォルトの名無しさん (ワッチョイ c393-gW4a)
垢版 |
2020/10/04(日) 17:44:38.81ID:OhT0M+ch0
void型の値を変数に格納するにはどうすればいいですか?

int main(void) { (void)5; }
というコードではコンパイル時にてエラーが出ないため、void型の値はC言語において定義されたものだと思いました。
でもそのvoid値を格納するための変数を以下のように宣言すると、エラーが出てしまいます。
int main(void) { void hoge; }
また、void型が占有するメモリサイズを調べる前段階として、printf関数に渡す前に、以下のコードを実行してみてもエラーが出ます。
int main(void) { sizeof ((void)5); }

どうすれば、void型の値を変数に格納できますか?
なお、C言語環境を構築するのが面倒そうなので、構築が簡単なVisualC++環境で未だにC言語の勉強してます。
2020/10/04(日) 18:06:44.78ID:hQVA1bdd0
>>8-9
JISX3010:2003 を確認してみたら 7.19.6.1 内に「適切な桁数へ値の丸めも行う」という記述は見つけた。
浮動小数点の扱いについてはいくつかの動作モデルが認められている旨が 5.2.4.2.2 にあり、
処理系がどれを選択したのかは float.h で定義されるいくつかのマクロでわかることになってる。

数学的なめんどい理屈があって、どのモデルであったとしても
十進数として見たときには切り捨てとも四捨五入とも言えないと思う。
2020/10/04(日) 18:12:48.79ID:hQVA1bdd0
>>11

JIS3010:2003 の 6.3.2.2 にこういう規定が書かれている。
> (型 void をもつ式) の (存在しない) 値は、いかなる方法でも使ってはならない。
> ボイド式には、暗黙の型変換も明示的な型変換 (void への型変換を除く。) も適用してはならない。
> 他の型の式をボイド式として評価する場合、その値又は指示子は捨てる。
> (ボイド式は副作用のために評価する。)

つまり void は値を捨てるという意図を便宜的に型として表したものであって、
void 型にした時点でその値を利用しないという表明になる。
14デフォルトの名無しさん (ワッチョイ c393-gW4a)
垢版 |
2020/10/04(日) 18:36:30.14ID:OhT0M+ch0
>>13
・microsoftなどの処理系開発者には、プログラマがコード上でvoid型の型も値も利用できない仕様となるように求める。
・プログラマがvoid型への明示的な型変換を求めた場合は、目的の値も型も何も返さないが、C言語の裏側でゴニョゴニョと何か分からない用途に利用される

ということですか?
15デフォルトの名無しさん (ワッチョイ c393-gW4a)
垢版 |
2020/10/04(日) 19:40:33.20ID:OhT0M+ch0
それとも、void型とは、データ型というよりも、コンパイラに対して「ここでは値は得られませんよ」と教える機能を与えられた式ですか?
関数定義の引数や返り値で void が指定された場合は、「引数や返り値は得られませんよ」とコンパイラに教えてあげてるのと同様、
(void)5 という式の評価結果であるボイド式では、「この式を評価しても値は得られませんよ」と裏でコンパイラに教えてあげてるだけですか?
そして、そのJISのいう「副作用」というのは、「値は得られませんよ」とコンパイラに教えてあげることを指してますか?

また、キャスト演算子の引数や、関数の引数や返り値で指定できるので、(型のように使用されるから型じゃないけど)便宜上、void型と呼ばれているだけですか?
2020/10/04(日) 19:42:41.40ID:hQVA1bdd0
>>14
何かの関数を呼び出した場合、たとえば printf("hello, world"); と書いたときに
printf も返却値はある (出力したバイト数を返す) が返却値を受け取ることをするのを忘れたのか
返却値を処理する意志がないのか、このコードからは読み取れない。
だからそういうときに (void)printf("hello, world"); と書くことで値を捨てることを明確にする、というような使い方が出来る。

プログラムの検査をするある種のソフト (いわゆる lint) は返却値を受け取っていない状態を
「疑わしい」として検出することがある。
プログラマがどういう意図を持っているかまでは機械的にチェックできないから、
何か意図があるのなら明記してくれやってわけ。

https://docs.oracle.com/cd/E19205-01/820-1209/bjaim/index.html

まあ言語仕様上は書いても書かなくても何の差もないし、
書かないことの方が多いと思うんだけど、
プログラマの意図を表明するのに使えるコメントみたいなものだという感覚でいればいいと思う。
17デフォルトの名無しさん (ワッチョイ ffad-EdVv)
垢版 |
2020/10/04(日) 19:47:21.47ID:4IGvE5yV0
以前gccで void *p; のように宣言されている p に p++ やってるのがコンパイルエラーにならなくて驚いた事がある。
gccの拡張なのな。
2020/10/04(日) 19:47:37.95ID:hQVA1bdd0
>>15
> そのJISのいう「副作用」というのは、

引数 (ときには 0 個) を与えて返却値が返ってくるというのが関数としての「作用」で、
それ以外に状態に影響を与えることは全て副作用。
たとえば printf が文字を表示したりするのも副作用。

ってなわけで、「ボイド式は副作用のために評価する。」というのは
返却値はどうでもよくて計算の過程で生じさせる副作用の方に意味があるような
式だよ〜〜ってこと。
2020/10/04(日) 19:52:24.09ID:hQVA1bdd0
>>17
gcc だと sizeof(void) が 1 を返すのにもびっくりする。
C++ だと SFINAE の中で sizeof を使ったトリックを使うこともあるんだが、
g++ ではつじつまを合わせるためか変則的な挙動があってよくわからんことになってる。
2020/10/04(日) 20:20:31.56ID:tJ8GLyXg0
>>16
>返却値を処理する意志がないのか、このコードからは読み取れない。
>だからそういうときに (void)printf("hello, world"); と書くことで値を捨てることを明確にする、というような使い方が出来る。

大昔に lint を試したことがあって、それは lint 用の書き方とばかり思っていました…
21デフォルトの名無しさん (ワッチョイ c393-gW4a)
垢版 |
2020/10/04(日) 20:50:24.88ID:OhT0M+ch0
知りたいことと回答が噛み合わないので、よくわからなかったです。
知りたいことは、(void)printf("hello, world"); が、なぜ「値を捨てることを明確にする」という結果になるかということです。
また、副作用についての言葉の意味を質問してるのではなく、void型においては具体的に何の副作用が起きてるのかを知りたかったです。
2020/10/04(日) 21:09:12.86ID:kIcOnbZ00
>>21
(void)... という記述は値を捨てることを明示する以外に意味が無いから、かな。
「void型において副作用が起きる」などということは無い。副作用を起こす可能性があるのは
(void)キャスト対象の式のほうで、その副作用は(void)の有無に関わらず生じる。

正確なところを知りたいなら自分で規格読んだらいいんじゃないの?
2020/10/04(日) 21:13:07.48ID:hQVA1bdd0
>>21
> なぜ「値を捨てることを明確にする」という結果になるか

void 型になった以上はその値は使うことができないから。
わざわざ使えなくしているんだから、
使い忘れたんじゃなくて捨ててるんだなとしか解釈のしようがない。

> 具体的に何の副作用が

文字を表示するという例では不足?
値を返す以外に起こることは全て副作用なので、
変数に書き込むこともループする (ことによって時間を消費する) ことも全て副作用だよ。
2020/10/04(日) 21:14:38.31ID:hQVA1bdd0
>>22
なるほど! >>21 は副作用というのを void の効果のことと誤解しているのか。
それは読み取れなかった。
2020/10/04(日) 21:26:28.40ID:hQVA1bdd0
>>15
void が型か型じゃないかということになると仕様上の理屈では型としか言いようがない。
ただし、 void 型な値は存在しない。
JIS の言葉で言えば「void 型の値の集合は空とする」ということになっている。

void へ型変換するということは非存在に変換されるので値として利用不可能になる。
26デフォルトの名無しさん (ワッチョイ c393-gW4a)
垢版 |
2020/10/04(日) 21:49:13.97ID:OhT0M+ch0
>>22
>(void)... という記述は値を捨てることを明示する以外に意味が無いから、かな。
今のところvoidの定義に「値を捨てることを明示する」という記述は見つけられなかったです。

>「void型において副作用が起きる」などということは無い。副作用を起こす可能性があるのは
言葉足らずでした。もちろん、void型の式という意味です。

>(void)キャスト対象の式のほうで、その副作用は(void)の有無に関わらず生じる。
繰り返しになりますが、void型の式におけるその具体的な副作用を質問していました。

その他のレスは重複するので省略します。
2020/10/04(日) 21:50:10.81ID:FWH29Af20
voidそのものは実体を持たないがポインタを派生することは出来る
というかポインタのためだけに存在しているようなもの
28デフォルトの名無しさん (ワッチョイ c393-gW4a)
垢版 |
2020/10/04(日) 21:55:51.38ID:OhT0M+ch0
たぶん皆さんのいう情報源は、Cの中級者向けの教科書として有名な「Cクイックリファレンス第二版」だと思います。
この本に「キャスト演算は、関数の戻り値のような、式の値を明示的に棄却する」という一文があります。
これ以上の詳しい説明がないので、知りたかったです。
2020/10/04(日) 21:58:09.05ID:hQVA1bdd0
>>26
値を返す以外に起きることは全て副作用なので具体的にと言っても困るんやが……。
■ このスレッドは過去ログ倉庫に格納されています