スラドに聞け:いま使っている言語の仕様、把握している? 212
ストーリー by hylom
仕様書は読んでみると楽しいですよ 部門より
仕様書は読んでみると楽しいですよ 部門より
m_nukazawa曰く、
もうかなり前の話になってしまうのだが、C言語における『未定義動作』の存在を知った時は衝撃を受けた[本の虫:Old New Thing: 未定義動作はタイムトラベルを引き起こす(他にもいろいろあるけど、タイムトラベルが一番ぶっ飛んでる)、Success is a Journey, not a Destination:全てのCプログラマが未定義な振る舞いについて知っておくべきこと #1/3]。以降、gccのWstrict-aliasingオプションは必ず付けるようにしているし、ポインタの怪しい型キャストはしないようにしている。
それなりに親しんでいるつもりのテクノロジでも、重要なことを知らないまま使っていて、落とし穴にはまることがままある。必要と思ってはいても、つい仕事が忙しい、探して手に入れるのが面倒であるなどを理由にして、Webの断片的な情報や入門書で用を足し、言語仕様書などを読まないで済ませてしまっている読者の方はタレコミ主以外にもいるのではないかと思う。
さて、あなたは自分が使うテクノロジ・言語仕様のドキュメントを読むだろうか? また、それをどこで手に入れるだろう? VimやEclipseの取扱説明書は読む? ユニットテストフレームワークのドキュメントに満足している? MSDNのディスクはあなたの本棚の上でホコリをかぶっているのだろうか?
……などなど、あなたとあなたが使っているテクノロジとの交際方法について、広く自由に語っていただければ幸いである。
ちなみにタレコミ主としては、C言語以外にもあるだろう「未定義動作」的な話、実際に落とし穴にはまった際のエピソードなども、語っていただければと期待している。
MIPS CPU (スコア:2)
モバイルギア(WindowsCE機)のアプリケーションを
開発していたときに、C のソースで構造体を使ったら
何をやってもハードウェア例外発生。
MIPS ではデータ配置が 4バイトとの倍数というルールを知らなかった。
けっきょくダミーバイトを埋め込んで解決したけど、未熟だったなあ。
構造体の配置 [microsoft.com]
Re:MIPS CPU (スコア:2)
x86とMSVC6PP5辺りでの事だけど、構造体のメンバに__m128な変数を定義した場合、その__m128な変数は16バイト境界に合わない場合が有ったような気がするする。
__declspec(align(16))とはいったい...。
MIDI OUT の4番ピンが5Vでなくても良いこと (スコア:2)
Re:MIDI OUT の4番ピンが5Vでなくても良いこと (スコア:1)
unspecifiedもundefinedも、動作を規定していないことは同じだが、unspecifiedは、仕様として正常な部分について、あえて規定しないことを示す。undefinedは、異常系動作がどうなるかを規定しないことを示す。まえは「未規定」と「未定義」を使ったけれど、最近は違うのかな?
C言語で言えば、char型は8ビット以上という条件はあるが、実際のサイズは実装者定義(implementation defined)=実装依存であり、規格としてはあえて規定していない(unspecified)。一方、NULL pointerをdereferenceした時の動作や整数を0で除算したときの結果はundefined。
あと、規定がshall/must (必須・しなければならない) なのか、should (推奨・することが望ましい) なのか、may (許可・してもよい) なのかで変わる。shall not、should notは使うがmay notは使わない。理由は……わかるよね?
あと、requiredとかoptionalとかもあったな。これはRFCだったっけ。
どこかにありませんか? (スコア:1)
日本語のLanguage Specification
未定義や処理系依存が多すぎて苦労しとるのですが・・・
Re:どこかにありませんか? (スコア:1)
未定義や処理系依存が多すぎて苦労しとるのですが・・・
エラー。
文が終端されていません。
ヒント: 文は「。」で終端します。
# Cでセミコロンの入れ忘れとかあるよねー。
Re: (スコア:0)
つアーヴ語
Re:どこかにありませんか? (スコア:2)
Re:どこかにありませんか? (スコア:1)
found ambiguous meaning term 「じゃ」
老人の発言を示唆する「じゃ」と提案を意味する「じゃ」とを環境もしくは文脈から特定できません。
Re:どこかにありませんか? (スコア:1)
わたしも昔っから「I ZO N」って発音してたけど、ときおり「I SO N」が正しいって突っ込まれるんよね……存在を「ZONZAI」って発音するかよって。
生存は「SEISON」って言わないよね。
Re:どこかにありませんか? (スコア:1)
自然言語の場合、TPOとかいう暗黙のコンパイルスイッチどころか、
話し手と聞き手で言語仕様が違ってたりしますからねぇ。
Re:どこかにありませんか? (スコア:2)
それってもしかして、0と1に置き換えても...
Re:どこかにありませんか? (スコア:1)
floatで整数を数えあげちゃいけない@C言語 (スコア:1)
十数年仕事で(アマ時代を入れると20年以上)使っていたのに知らなかったので数日はまった。
バグったコードからエラー原因を簡素化したテストコードは以下。
float型(i)とint型(k)で1ずつ加算していって異なったら
標準エラーに出力。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:2)
floatと整数と言えば。
を見て、もすぬごい衝撃がががが。
Fast inverse square root [wikipedia.org]とか、Cで書きたくなくなる。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:2)
共用体の存在を、こってり忘れていた。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:2)
Z80用の単精度浮動小数点ライブラリを自分で書いてみたクチだから、どれくらい浮動小数点での加減算が信用できない(精度が足りなくなる)か身に染みて分かる。
今は浮動小数点形式の構造ばかりか、スタックの構造やらポインタ、果てはデータのメモリ内での記憶方法なんぞを知らなくても良い時代になったと思えばいいのかなあ。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
なぜ1024倍でないのか?
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
二進数の整数で扱うなら、1000倍より1024倍の方が計算が簡単なんだけど、知らない?
二進化十進数なら話は別だと思うけど。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
NCデータがどういう情報かはご存知ですか?
しりませんが、それが何か?
通常、浮動小数点で扱ってる数値データなんでしょ?
それを、固定小数点で扱いたい、って話なんでしょ?
何か問題でも?
# 相変わらずな御仁だなあ
そしてキミからは、具体的には何の反論も出てこない、という相変わらずさじゃ無いといいけど。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:2)
NCデータと通常称されるものは、NC工作機械に入力されるテキストデータ。
テキストデータなので浮動小数点も固定小数点もない。
それを読み取ったCNC側が内部でどう扱っているかは別問題としてあるが、
通常外部に公開されていない。
また"G91X1;"と"G91X1.;"が同じ動きをするかどうかは設定次第。
よくある設定だと小数点抜きの場合um単位、小数点をつけるとmm単位の指令と解釈される。
三菱のCNCなら"#1015 cunit プログラム指令単位"の設定内容を確認する。
そもそも別の設定項目でメトリック系とインチ系が切り換えられたりするから、
NCデータ単体では各数値の表す意味は不明。
# 組み込みマクロにSINとかあるけど精度調べたことなかったなあ。
# 計算精度より先に位置決め精度のほうが頭打ちになる機械ばかりだしどう確認しよう。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
これて浮動小数点で得られるものを、固定小数点で表したい、ってはなしだよね。
なら、
とかにしないと。
掛け算しようとすると、固定小数点なので、
乗除のたびこうい計算が必要になるわけだね。
で、どうなった?
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
0.001mmをゲタ履かせて整数の1で表したいって話でしょ。
それなら、マイクロメートル使いなよ。
できないわけじゃない [srad.jp]みたいだけど、何が問題なの?
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
NCデータと通常称されるものは、NC工作機械に入力されるテキストデータ。
テキストデータなので浮動小数点も固定小数点もない。
つまり、二進化十進数 [wikipedia.org]ってことね。
既に書いた [srad.jp]通り、それなら話は別。
で、機械に食わせる二進化十進数を1000倍して小数点を無くすかずらすかして、何か嬉しいの?
小数点以下の0が9個以上連続する、とかなら判らんでもないけど、3個くらいなら人間が手を加えるにしても、大した話じゃ無いと思うけど。
数点抜きの場合um単位、小数点をつけるとmm単位
「um」って、「μm」のこと?
そっちの業界では、そー書くの?
そもそも、マイクロメートルを扱えるなら、そうすればいいだけじゃん、と思うけど、違うの?
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
ではないの?だとしたら1024でも1000でも計算コストは変わらないよね。
1024 * (int)nだろうと、(int)(1024.0 * n)だろうと、1024倍と1000倍でコストは変わらないね。
実際、どちらの場合も、コンパイラが吐くニーモニックのステップ数は同じになる。
ただし、掛算とビットシフトが同じコストと考えるならば、だけどね。
実際には同じではないので、コンパイラも1024倍の時は、掛算命令でなくビットシフト命令を吐くわけだけど。
これも、掛け算したらもはや単位は長さではなく面積なので、
長さ 1unit=1/1,000 mm
面積 1unit=1/1,000,000 mm2
と仕様書に書いておけばすむ話。
そんなことで済むなら、そもそも#3069125 [srad.jp]は何だったのか、って話になっちゃうね。
それにもし、そうしたいのであれば、普通「長さ 1unit=1μm」だよね。
マイクロメートル、学校で習ったよね?
面積に至っては、そんなに0を並べちゃ、残念ながら見やすいとは言えなくなっちゃうね。
もし、そんに0が並んでも見やすいって言い張るのなら、小数点以下に2つゼロが並ぶのも問題無い、ってことになって、1000倍する意味がなくなるね。
そもそも、機械に食わせるデータに、見やすさなんか関係あるの?
もし、機械がmmしか扱えないとしても、適切なフィルタ書いてやれば済むんじゃね?
その程度のスクリプト、キミにだって書けるでしょ?
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
# IEEE754脳のまぜっかえし
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
(int)(1024.0 * n)って、ビットシフトで計算するんですか?
当然しませんが、そーゆー意味じゃないです。
#3069313 [srad.jp]を受けた発言です。
業界によりますが、長さをmmで扱うのが当然のところでは、1000mmを単純に1mと略さないのと同じ程度には、0.001mmを単純に1μmと書かないところがあります。
そーゆー業界に身を置くなら、慣れるのが吉。
業界を変えるのは超困難だけど、自分を変えることはできるので。
0が二つ三つ程度の話ならなおさら。
でも、「1unit=1/1,000mm」と書くのはokって話なんだよね?
キミに文句を言ってもしかたないけど、ミョーな業界ルールだねぇ。
ところで、私は機械可読なデータの話のつもりだったんだけど、設計図とかの話にズレてる気がする。
気のせいですか?
それとも、データの中で「1unit=1/1,000mm」とかって宣言可能って話?
だったら、最初 [srad.jp]からそれで良かったのでは?
思った結果にならなかったときに、生データをその場で当たらなければならないことは往々にしてるんですよ。
どーしても慣れない、ってことなら、単位を変換するスクリプト書けばいんじゃね?
機械可読なデータなら難しくは無いでしょ。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
この場合、1000.0の代わりに1024.0を使う意味がなくなります。
そーでもないんだけどね。
浮動小数点といえども、所詮二進整数の組合せなので。
# コンパイラがそこまで最適化してくれるかは知りませんが。
印刷された数値列を直接読むって結構ありますよ。
スクリプトを噛ました後に印刷すればいいんじゃね?
なんか、「1unit=1/1,000mm」と書くとか、スクリプトを書くとか、慣れるとか、いろいろ手はありそうなのに、できない理由ばかり書いてる気がするね。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
自社の後継者のみならず他社からも。
そーゆー業界に居るなら、業界のルールに従って、それに慣れるのが一番です。
たかが0三つくらいの話なんでしょ?
これが単純で最適な解なんじゃないでしょうか。
「自社の後継者のみならず他社」に至るまで、その「最適な解」を受け入れてくれれば、その通りです。
で、実際受け入れてもらえるんですか?
もし、受け入れてもらえないのなら、「最適な解」と言うより、非現実劇な解と言うべきでしょう。
もし、受け入れてもらえるのなら、何をここでウダウダ言ってんだよ、さっさとやりなよ、としか言いようが無いです。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
なんか論点がずれてきている気がします。
その原因は、二進化十進数なら話は別 [srad.jp]とあるのを読み飛ばしてるからじゃないですかね?
「1000倍がいいんじゃないの。生データを見るときもそのまま見れるし」というのが、常識というか当然だと思うんですけど。
で、業界のルールは変えることができるですか?
できないなら、慣れるのが一番だし、できるなら、さっさとやれ、ってだけです。
大体、そーゆー「ボクの考えた最強の」みたいなヤツは、実現性は皆無ですけど、もしかしたら実現することもあるかもしれませんね。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
扱う数値の最小単位が 1/(9^3) だったら九進数の話になるというのがあんたの主張なのか?
違いますよ。
誰も言ってもいない話を持ち出されても、困惑するばかりです。
ただ、元が九進数なら、九進数のまま扱ってもいいと思いますよ。
# そんな「業界」があるか疑問ですが(笑)。
十分な長さがある浮動小数点を使うか、(9^3)倍して整数を使えばいい話だろ。
表示の話をすれば、(9^3)倍して整数に表示できるかどうかは、適用分野(業界と言い換えてもいい)によります。
元々そう表示されていないのであれば、普通は許されないでしょうね。
適用分野のルールを変えようとするより、慣れる方が良いです。
さっさと慣れましょう。
浮動小数点で表示、というのは、まあ普通ないでしょう。
そんなバイナリを表示されても、普通は読めませんしね。
まあ、通常は十進数の少数として表示するんじゃないですか?
計算の話で言うと、十分な精度が保てるのであれば、整数で扱ってもいいでしょうし、浮動小数点数でもいいですし、固定小数点数で表してもOKです。
整数で扱うのと、固定小数点で扱うのは、精度を無視して計算して良いなら、基本的には同じですね。
加えて、コンピュータで計算するなら、普通は二進数で計算するでしょう。
その場合に、固定小数点数で計算するなら、2^n倍するでしょうね。
二進化十進数として計算してもいいでしょう。
これも単位を変えて整数で扱う方法と、固定小数点で扱う方法があります。
COBOLを使うんでなければ、まあやらないと思いますが。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
にあるように、定数倍の演算は整数ではなくfloatなので、二進数の整数で1024倍する、ということは考えなくていいと思われます。
浮動小数点数を、固定小数点もしくは1024倍して整数に変換するには、ビットシフトすれば十分で、乗算不要です。
一方、1000倍の場合はそうはいきません。
当然知ってますよね?
# Cを前提にするなら、そこまで最適化してくれるコンパイラがあるかどうかは知りませんが、Cを持ちだしたのは、私ではありません。
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:2)
水の存在に気づかない魚のごとく、という感じでしょうか
人間の慣れの力は強力すぎて、"ひと目見てあきらかにおかしい"事にも気づかなくなる。
それゆえ、人から見たら「気づかないほうがおかしい」バグの原因にもなる。
// 『ライト、ついてますか?』
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:1)
浮動小数点のことを浮動小数と書かれると、ものすごく違和感がありますね。
#小数点が動くから、浮動小数点。浮動小数では意味不明。
まあ、普段はいちいちツッコミを入れたりはしませんが、このコメントのような文脈で「浮動小数のバックグランド」って書かれたら、本当に浮動小数点のバックグランドを理解しているのか怪しいなあと、説得力半減。
浮動小数点数 (スコア:1)
もっと言えば、浮動小数点だと小数点そのものの挙動のことを指しているように思えちゃうので、浮動小数点数かな。
屍体メモ [windy.cx]
Re:floatで整数を数えあげちゃいけない@C言語 (スコア:2)
わたしの場合ですが、ロジックが不自然でなければ、整数型でも、等号より大なりなどの比較演算子を使うようにしています。
一応、コードの変更で加算が入るかも、という正当な理由はあるのですが、どちらかというとパラノイアな「なんとなくこっちのほうが安心」という気持ちに従っているだけの気もします。
// などと書いていたら、『「等号に掛からなくなるような当初想定しなかった変更があっても、とりあえずエラーにならない」コーディングは逆に、のちのち大きなバグを生む種になりかねないのでは?』と不安になってきたぞ、と。
PHP (スコア:1)
C言語ぽい文法なのに、たまに変なアレンジが入っているのが嫌、というか怖い。
「switch 文の中で continue を書くと、break と同じ動作」ってのにハマり、
調べてその事実にたどり着いたときは、衝撃でしばらく作業が手につかなかったw
Re:PHP (スコア:2)
そこでgotoですよ。
// goto自体の可否についてはまた別の話ということで...。
「読んでみると楽しいですよとは何ごとか!」 (スコア:1)
「全部読んで頭に叩き込んでからプログラミングせんか!!」
# この発言はフィクションです。別に先輩に言われたとかではありません。
# プログラミングしてる時においおい読んでいけばいいんじゃないのと思うACであった
いやいや、それ良いアイデアかも (スコア:2)
C++でプログラミングできる人類は一人も居ないことになりますからね。
// あ、でも正規表現は使いたい
// ムーブセマンティクスを理解できる日が来る気がしない、けど非AC
MSDNってもうディスクなんか無いけど (スコア:1)
> MSDNのディスクはあなたの本棚の上でホコリをかぶっているのだろうか?
かつてはディスク無しオプションでサブスクリプション契約すると1ヶ月分安くなってたような記憶があるけど、
今はもうディスク配布してないよ。
C言語の後置++ってわんぱく (スコア:1)
int a[]={10, 11, 12};
int *p = a;
*p++ = p[1]; /* なんかトリッキー… */
printf("%d %d %d", a[0], a[1], a[2]);
これをコンパイルすると
gcc4.7以前だと 11 11 12
gcc4.8以降だと 12 11 12
わんぱくですね。
Cの予約語 '_' (スコア:1)
'_'大文字で始まるものと'__'から始まる識別子は
Cの予約語であるというのはかなりのベテランでも知らない人が多い
_TEST とか __index__ のようなものを定義してしまい、
標準ヘッダの定義が置き換えられてしまった結果。
理解不能なコンパイルエラーが発生して原因の究明までに
大変な時間がかかった事があった。
hylomに聞け (スコア:1)
今使ってるいる日本語の仕様、把握している?
シェルスクリプトも侮れない (スコア:1)
Java Puzzler (スコア:1)
Javaの世界では,この手の「あまり知られてないマイナーな言語仕様」「勘違いしている人が多い文法」などをもとにした,「このプログラムを実行するとどうなるでしょう?」というクイズがJava Puzzlerとして一般化しています。
書籍 [amazon.co.jp]でも出ていますし,カンファレンスなどでも定番の出し物 [java-users.jp]になってます。
NaN (スコア:0)
プログラミング言語の話とはちょっと違うが、浮動小数点演算でありがちな思い込みを一つ
正確な表現では無いが、NaNというのはフラグが立つだけで、有効では無い値での演算が停止したり、値が途中でゼロクリアされるわけではない
都合があって、組込システムで周期的にNaNのチェックをして、演算結果をリセットするコードを書いたことがある.....
#どんな時でも馬鹿よけの仕組みは必要です
当方の環境では再現不能です (スコア:2, おもしろおかしい)
お使いのパーザが「このトピックの読者」ではなく「言語仕様書の読者」と解釈してしまうのは,代名詞のスコープ処理まわりか,人称代名詞の一般名詞による代替処理まわりが,日本語の基本仕様に宣っていないのではないでしょうか。
Re:shortは16ビットじゃないしlongは32ビットじゃない (スコア:1)
16bitの変数が使いたければ int16_t を、
32bitの変数が使いたければ int32_t を使いましょう。
C99で規格化されています。
Re:shortは16ビットじゃないしlongは32ビットじゃない (スコア:1)
答えは1つめですね。
int16_t などは「処理系定義」(implementation-defined)です。int16_t がなくてもC99として問題ありませんが、int16_t が定義されている処理系では、int16_tは「そのサイズがピッタリ16bitであること」「負数の表現方法は2の補数であること」が保証されます。(素の int は、負数の表現方法も規定されていません。まあ大抵は2の補数ですけど、例えば「符号ビットと絶対値」みたいな内部表現の処理系も許されます。)
あとは、変な処理系向けの型としては、「int_least16_t」(16bit以上で最小の型)や「int_fast16_t」(16bit以上で処理系最速の型)もあります。こっちは必須。