draft
This commit is contained in:
@@ -4,3 +4,67 @@
|
||||
|
||||
\subsection{Deep Dive - if と switch の根本的な違い}
|
||||
|
||||
初学者は\texttt{if}文と\texttt{switch}文の使い分けで困まる時があるようだ。
|
||||
前述したとおり、どちらも条件分岐を行うことができる。
|
||||
|
||||
しかし、2つには文法以外に明確な違いがある。それは、\texttt{switch}文のほうが「圧倒的」に\\処理速度が速いというところである。
|
||||
まず、その処理速度の違いを見てみる。
|
||||
|
||||
以下のPythonスクリプトで10万個の条件文を含むCソースコードを生成する:
|
||||
|
||||
\defaultlistingstyle
|
||||
\lstinputlisting[language=Python,title={\texttt{if}文10万個}]{../programs/ifvswitch/gen-if.py}
|
||||
\lstinputlisting[language=Python,title={\texttt{switch}文10万個}]{../programs/ifvswitch/gen-switch.py}
|
||||
|
||||
これらを実行し、Cソースコードを生成する:
|
||||
|
||||
\begin{lstlisting}
|
||||
$ python gen-if.py
|
||||
$ python gen-switch.py
|
||||
\end{lstlisting}
|
||||
|
||||
\newpage
|
||||
|
||||
以下が生成されたソースコードの一部始終:
|
||||
|
||||
\lstinputlisting[language=C,title={\texttt{if}文10万個のソースコード},consecutivenumbers=false,linerange={1-8,199996-200010}]{../programs/ifvswitch/ifs.c}
|
||||
|
||||
\lstinputlisting[language=C,title={\texttt{switch}文10万個のソースコード},consecutivenumbers=false,linerange={1-8,99998-100011}]{../programs/ifvswitch/switch-case.c}
|
||||
|
||||
\begin{lstlisting}
|
||||
// 検証に影響する最適化を無効にしてコンパイルする
|
||||
$ gcc -O0 ifs.c -o ifs
|
||||
$ gcc -O0 switch-case.c -o switch-case
|
||||
\end{lstlisting}
|
||||
|
||||
生成物をタイマに通して実行する:
|
||||
|
||||
\begin{lstlisting}
|
||||
$ time ./ifs
|
||||
|
||||
real 0m59.045s
|
||||
user 0m58.444s
|
||||
sys 0m0.001s
|
||||
|
||||
$ time ./switch-case
|
||||
|
||||
real 0m0.006s
|
||||
user 0m0.004s
|
||||
sys 0m0.002s
|
||||
\end{lstlisting}
|
||||
|
||||
実行結果から\texttt{switch}文の方が\texttt{if}文の約9840倍も高速であると分かる。
|
||||
|
||||
では、なぜ\texttt{switch}文の方が速いのか。それは、比較演算の数にある。
|
||||
|
||||
\texttt{if}文はその数と同じ数の比較演算が使われている。
|
||||
一方、\texttt{switch}文は比較に関する演算は一度しか行われない。
|
||||
|
||||
それぞれのバイナリを逆アセンブルする:
|
||||
|
||||
\begin{lstlisting}
|
||||
$ objdump -Mintel -d ifs
|
||||
$ objdump -Mintel -d switch-case
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
|
||||
17
section/calc.tex
Normal file
17
section/calc.tex
Normal file
@@ -0,0 +1,17 @@
|
||||
\section{簡易電卓}
|
||||
|
||||
2つの実数を入力し、四則演算を指定し、小数点6桁で結果を表示する。0 divも考慮すること。
|
||||
|
||||
\subsection{コードリスティング}
|
||||
|
||||
\lstinputlisting[language=C,title={簡易電卓}]{../programs/calc/main.c}
|
||||
|
||||
\subsection{実行結果}
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[width=\textwidth]{./assets/calc-1.png}
|
||||
\end{center}
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[width=\textwidth]{./assets/calc-2.png}
|
||||
\end{center}
|
||||
@@ -8,5 +8,5 @@
|
||||
\item OS: Arch Linux
|
||||
\item CPU アーキテクチャ: \texttt{x86\_64}
|
||||
\item C コンパイラ: \texttt{gcc バージョン 14.2.1 20250322 (GCC)}
|
||||
\item C コンパイラオプション: \texttt{}
|
||||
\item C コンパイラオプション: \texttt{-Wall}
|
||||
\end{itemize}
|
||||
|
||||
13
section/p312.tex
Normal file
13
section/p312.tex
Normal file
@@ -0,0 +1,13 @@
|
||||
\section{演習 3-12}
|
||||
|
||||
教科書のList 3-4をSwitch文で書き換えたプログラム。
|
||||
|
||||
\subsection{コードリスティング}
|
||||
|
||||
\lstinputlisting[language=C,title={演習 3-12}]{../programs/p312/main.c}
|
||||
|
||||
\subsection{実行結果}
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[width=\textwidth]{./assets/p312.png}
|
||||
\end{center}
|
||||
13
section/p313.tex
Normal file
13
section/p313.tex
Normal file
@@ -0,0 +1,13 @@
|
||||
\section{演習 3-13}
|
||||
|
||||
教科書のList 3-18 をSwitch文で書き換えたプログラム。
|
||||
|
||||
\subsection{コードリスティング}
|
||||
|
||||
\lstinputlisting[language=C,title={演習 3-13}]{../programs/p313/main.c}
|
||||
|
||||
\subsection{実行結果}
|
||||
|
||||
\begin{center}
|
||||
\includegraphics[width=\textwidth]{./assets/p313.png}
|
||||
\end{center}
|
||||
@@ -0,0 +1,42 @@
|
||||
\section{今回の構文}
|
||||
|
||||
\subsection{\texttt{switch}文}
|
||||
|
||||
\texttt{switch}文は\texttt{if}文と同じように条件分岐を行う文である。
|
||||
if文と違い、論理式・論理値による分岐ではなく、評価後の整数値によって分岐する。
|
||||
それぞれの条件は\texttt{case}ラベルで記載され、コロン(\texttt{:})の後に処理を記述する。
|
||||
処理の終わりは\texttt{break}文を書く。
|
||||
ケースは縦落ちすることができ、\texttt{break}文を書かずにしておくことで複数の値に同じ処理を割り当てることができる。
|
||||
\texttt{if}文における最後の\texttt{else}は\texttt{switch}文では\texttt{default}ラベルとなっている。\cite{switch_cppref}
|
||||
|
||||
\defaultlistingstyle
|
||||
\begin{lstlisting}[language=C,title={\texttt{switch}文}]
|
||||
switch (式) {
|
||||
case <値1>:
|
||||
<処理>... // 値1の場合の処理
|
||||
break;
|
||||
case <値2>:
|
||||
<処理>... // 値1の場合の処理
|
||||
break;
|
||||
default:
|
||||
<処理>... // それ以外の場合の処理
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
|
||||
\begin{lstlisting}[language=C,title={縦落ち(Fall-through)する\texttt{switch}文}]
|
||||
switch (式) {
|
||||
case <値1>:
|
||||
<処理>... // 値1の場合の処理
|
||||
break;
|
||||
case <値2>:
|
||||
case <値3>:
|
||||
<処理>... // 値2と値3の場合の処理
|
||||
break;
|
||||
case <値4>:
|
||||
<処理>... // 値4の場合の処理
|
||||
break;
|
||||
default:
|
||||
<処理>... // それ以外の場合の処理
|
||||
}
|
||||
\end{lstlisting}
|
||||
|
||||
Reference in New Issue
Block a user