こんにちは､ そしてようこそ｡
この講義では､ 演算子とは思えないような､ ちょっと不思議な演算子についてお話したいと思います｡
というのも､ これまで習った演算子はすべて､ 記号を使って数値の計算をすることを指したものばかりだからです｡
そして､ これらの演算子は､ 実は関数のようなものなのです｡
そこで､ sizeof演算子でのキャストについて説明します｡
まずキャスト演算子についてお話するために､ データがどのように変換されているのか､
型変換について少しお話しなければなりません｡
私たちはデータ型とそこにあるさまざまなデータ型についてすべて学びました｡
しかし､ 実際にデータを異なる型に割り当てようとすると､
c言語ではいくつかの暗黙の変換が行われます｡
そこで､ 異なる型間のデータの変換が自動的に行われることがあり､
これを言語による暗黙の変換､ またはプログラムによる明示的な変換と呼んでいる｡
プログラマー自身が開発者が何かをすることができる｡
基本的にキャスト演算子を使って変換を行うことができるのです｡
暗黙的に変換されるデータは本当に重要で､ これを理解しなければなりません｡
なぜなら､ これから開発するほとんどのCプログラムを効果的に開発するためには､
これらの変換のルールを理解しなければならないからです｡
なぜなら､ 整数と浮動小数点数､ 10進数と整数がよく出てくるからです｡
そして､ それらを時々混ぜて使うことになるのです｡
そして､ その際､ どのように変換されているかを知る必要があります｡
あとは､ キャスト演算子を使って､ できるだけそれを回避するようにしましょう｡
しかし､ キャスト演算子を使わないときは､ 何が起こっているのか理解してください｡
そして､ 異なるタイプのfloatやdoubleにデータを代入するとどうなるかというと､
データは切り捨てられるか､ 昇格されるかのどちらかです｡
この2つの用語は､ よく耳にする言葉です｡
切り捨ては精度が落ちること､ 昇格は精度が上がることを意味します｡
ですから､ これらのタイプを混ぜないようにしますが､ 便利な場合もあります｡
理解すべきは､ 以前の講義でcが非常に柔軟であることを知っていることです｡
そしてそれは､ 言語の設計者が意識的に決めたことなのです｡
しかし､ このように自由度が増すと､ トレードオフとして､ それを乱用することができるようになるのです｡
それで､
このタイプを混ぜるという考え方を悪用しないことです｡
整数には整数､ 浮動小数点数には浮動小数点数というように､ できるだけ同じ型を使うようにしましょう｡
しかし､ それができないときは､
暗黙の変換を理解するか､ キャスト演算子を使って明示的な変換を行うか､
どちらかになります｡
つまり､ もうひとつの問題､ もうひとつのコンセプトは､
cは柔軟であるが､ それを乱用してはいけないということです｡
つまり､ cの整数型変数に浮動小数点値が代入されると､
int x, float yとなり､ xはyに等しくなります｡
数値の小数点以下の部分が切り捨てられることになる｡
つまり､ 数値int xが0に等しい場合､ float
fは12に等しい｡ 125で､ xにfを代入すると､
xの値は12になる｡
その精度を失うことになるのです｡ intにfloatを代入しているので､
値が切り捨てられます｡ intは整数しか格納できない｡
つまり､ プログラミング言語とコンパイラによって､ 自動的に12に変換されるわけだ｡
輸入分のみ保存されることになります｡
ここで､ 逆に整数型変数を浮動小数点型変数に代入しても､
数値の変化は起きない｡
その値はシステムで変換され､ 浮動変数に格納される｡
そうすれば､ フローに割り当てることを気にする必要がなくなります｡
フローに12を割り当てても､ 12になるだけです｡ 0.
整数に対して演算を行う場合､ これは単に値を代入してfloatにしたりfloatをintにしたりするのとは異なります｡
これは式がある場合､ 加算や減算を行う場合などです｡
引き算や足し算をするとき､ 2つのオペランドがあります｡
そして､ 演算子にはintを､ オペランドにはfloatを指定することができるのです｡
その変換がどのように行われているのかを知る必要があります｡
つまり､ 式中のオペランドが2つとも整数であれば､
除算の結果生じた小数の部分はすべて捨てられます｡
つまり､ 整数xなら20ということですね｡
yは整数で､ 12です｡ そして､ 20÷12をするんですね｡
1ポイントなんとかなんとか､ はないだろう｡ 1が出るだけでしょ｡
なぜなら､ やはりintは整数しか格納できないからです｡
つまり､ 2つの数値がintで､ 割り算をしているわけです｡
浮動小数点数にはならないよ｡ 小数点以下の数字は出てきませんよ｡
さて､ 一方の演算子がint､ もう一方がfloatの場合､ 演算は浮動小数点演算として形成されることになります｡
つまり､ float fが20の場合｡ 0,
float aは10, int, そしてそこで割り算をすると､
あるいは12......すみません､ その方が当てはまりますが､ 結果は浮動小数点数で､ 1ポイント8888とか1ポイントになります｡
このデータを何かに割り当てているわけではないんですね｡ これは､ 何を返すのか､ という表現です｡
つまり､ 2つのintを分割すると､ 整数になってしまうんですね｡
intとdoubleやfloatだと､ 必ずfloatになるので､ 10進数の浮動小数点演算になるんです｡
そして､ これが暗黙の変換です｡ それは､ 本当に何もしなければ､ プログラムによって何が起こっていて､
何が行われているかを理解するために必要なことです｡
しかし､ 明示的な変換を行うようにした方がよい｡
そして､ これは多かれ少なかれキャスティングと呼ばれているに過ぎません｡
そして､ 変換したいときに多くの言語でキャスティングが表示されますね｡
そして､ あなたがやっているのは明示的な変換であり､
データをどうしたいかを言っているに過ぎない｡
そうでなければ､ データが降格したり､
消失したりする可能性があるからです｡
2つのintを割り算するときに､ 均等に割り切れないと､
そのデータがすべて失われてしまうんです｡
そのため､ 明示的に指定することで､ 正確な型変換を要求することが可能です｡
これはキャストと呼ばれ､ 数量の前に目的の型の名前を括弧で囲むことで行われます｡
つまり､ 括弧と型名がキャップ演算子を構成している｡
左括弧をして､ データ型を指定して､ 括弧を書くんですね｡
そして､ その右側にあるものが何であれ､ 右側にある式が何であれ､
あるいは単一の変数であっても､ それを括弧の中にあるものに変換するのである｡
そのため､ ロングなど実際の型が欲しい場合は､ その単語型に置き換えています｡
そのため､ 型渡し演算子は､ 単項マイナス､ 単項プラスを除くすべての算術演算子より優先順位が高い｡
まだ前例があることを学んでいない｡
次回の講義でご紹介します｡ 優先順位とは､ 基本的に何が起こるか､
実行される操作の順序のことです｡
そこで､ その例をいくつかご紹介します｡ この時点で理解しておかなければならないのは､ タイプキャスト演算子は､
単項マイナス､ 単項プラスの2つを除く他のすべての演算子に優先するということです｡
ここでは例として21という数字があります｡ 51で､ キャスト演算子があるのは､
括弧の中にあって型があるので､ キャスト演算子だとわかるからです｡
そして､
私たちが基本的に言っているのは､ 21を取るということです｡ 51 intに変換する｡
浮動小数点数を変換して持っていくと､ ちょうどint､
整数である21となるのです｡
右側と同じで､ 26を変換しています｡ 99 を int に変換します｡
では､ 実際にこの式を文の中で実行するとどうなるかというと､ 21＋26と評価されます｡
データを0から切り捨ててしまう｡
51から整数で､ 0と同じ｡ 99.
これがキャスト演算子で､ 括弧の中にデータ型が含まれるものなら何でもOKです｡
よく見かけると思います｡
仮に21＋26と言った場合､ それをfloatにキャストすると､ ドット0が追加されるだけです｡
普通､ より精密なタイプにキャストすることはないですからね｡
より精密なタイプから､ より精密でないタイプへ鋳造するのです｡
つまり､ floatからintへという感じですね｡
そのため､ いくつかのプログラムでは､ 異なるタイプを使用しているときに､
この現象が見られることがあります｡ 算術演算をする場合は､ なるべく異なる型を使わないようにする必要があります｡
でも､ そうすると､ これが見えてくるんです｡
オペレーターのサイズも､ 他の多くのオペレーターと似て非なるもので､
ちょっと不思議な感じです｡ そして､ これは実際に関数のように見えます｡
しかし､ sizeofは演算子である｡ アクションを実行するのです｡
機能的には何もしていないのです｡
これは､ 指定された型がメモリ上で何バイト占有しているかを示しているのです｡
つまり､ 引数を取るので､ 関数のように見えます｡
そして､ これからその例を示しますが､ これはメモリ内のバイト数を返すだけです｡ 実行中のシステム､ プラットフォーム､
オペレーティングシステム､ コンピュータのアーキテクチャ､
ハードウェアによって､ 異なるデータ型は異なるサイズでメモリに表現されることを忘れないでください｡
例えば､ int型は､ あるシステムでは4バイト､ 別のシステムでは8バイトになることがあります｡
そこで､ C言語の特殊なキーワード演算子であるsizeof演算子を使って､ データ型を渡すと､
それがメモリ上で何バイト使っているかを教えてくれるんだ｡
つまり､ sizeofは実際には演算子であり､ 関数ではありません｡
これはコンパイル時に評価され､ 引数に可変長の配列が使われていない限り､ 実行時には評価されません｡
ということに触れておきます｡ これは基本的に､ 配列のsizeofの中にある変数があっても､
実行時にコンパイル時に解決されることはないので､
それほど重要な知識ではない､ ということです｡
sizeof演算子の引数には､ 変数､ 配列名､ int
floatなどの基本データ型名､ 派生データ型名､
式などを指定することができます｡
つまり､ sizeof xにyを加えたものということができます｡
そしてそれは基本的に､ sizeof xにsizeof yを加えたもの､
あるいは結果の数値を言うことになる｡ xがint､ yがintでsizeofが16なら､ これはインチ4バイトと言うことになる｡
int oneがfloatで結果が浮動小数点演算だったら､
floatが8バイトとか｡
でも､ いろいろなことに使えるし､ いろいろなことに使ったほうがいい｡ 例えば､ Sizeof intは､
int型の変数が占めるバイト数になります｡
つまり､ システムによって4または8を返すことになります｡
また､ 式にsizeof演算子を適用すると､ 先ほど述べたように､
その結果は値の大きさになります｡
その結果､ 面積の表現が生まれるのです｡ つまり､ 2つのintを合わせてもintになるわけです｡
だから､ やはりサイズになるんですね｡ しかし､ ポインターの話をするときにもsizeof演算子が使われているのがわかると思います｡
オペレーターだからこそ､ 今話題にしたかったんです｡
しかし､ このクラスを通して､ より多くのコンセプトについて話しながら､ この例やキャスティングの例をたくさん提供していくつもりです｡
具体的には､ ポインタの話をするときにsizeof演算子の出番が多くなります｡
ポインタがそうであるように､ どれだけのメモリを確保するかを計算するときには､
正確を期すためにsizeofを使うからです｡
でも､ それ以外のことにも使えるんですよ｡
そのため､ 可能な限り sizeof 演算子を使用して､ プログラムにハードコードのサイズを計算する必要がないようにします｡
ハードコードされたサイズのマジックナンバーは良いものではありません｡
異なるシステム上でintをハードコードする場合､
あるシステムでは4ですが､ 別のシステムでは8かもしれませんので､
できるだけsizeofを使ってください｡
その他､ ちょっと不思議な演算子として､
アスタリスク演算子があります｡
アスタリスク､ もう掛け算で話したじゃないか､ と言われたかもしれませんね｡
しかし､ このアスタリスクは､ 左側と右側の2つのオペランドを取る｡
変数にアスタリスク演算子を適用して､ 右の引数を1つだけにしてstar変数名と言うだけでは､
別のものを表します｡
実はポインターを表しているんです｡
ポインターをデリファレンスしているのです｡
この点については､ ポインタの話をするときに詳しく説明するつもりなので､
ここでは触れません｡
しかし､ もしスターaのようなものがあったとしても､ それは実際に有効なものなので心配しないでください｡
それは､ アスタリスク・ザ・ポインター演算子をやっているのです｡
また､ クエスチョンマークのコロンが表示されることがあります｡
これは､ 意思決定に使われる演算子ですね｡
conditionがtrueの場合､ 左側のものが評価されれば､ コロンの後の右側の値が評価され､
そうでなければ同じように評価されます｡
if-else文の省略記法である｡
三項演算子と呼ばれるものです｡ しかし､ これらについては､
具体的なテーマについて話をするときに触れることにして､
今はあまり詳しく話したくないのです｡
ターニングオペレーターについては､ ディシジョンステートメントについて話すときに説明することにします｡ アスタリスク演算子unaryについては､
ポインタの話をするときにお話しします｡
しかし､ 今これを見ると､ 技術的にはオペレーターですが､ そのコンセプトについて話すときに､ その使用例を理解することができますので､
今述べておきたいと思います｡ ありがとうございます｡