%=====================================================================
% 秋田高専 5E 計算機応用 テキスト
%テーマ 散布路留プログラム
%    本テキストの内容
%        ・
%        ・
%        ・
%        ・
%
% last updated 2005.4.13
%    created by  Masashi Yamamoto
%     e-mail yamamoto@akita-nct.jp
%=====================================================================
\documentclass[10pt,a4paper]{jarticle}
\usepackage{graphicx,amsmath,amssymb,ascmac,theorem,float}
\usepackage{listings}
\oddsidemargin 0mm  %左の余白 25.4mm-0mm奇数ページ
\evensidemargin 0mm %左の余白 25.4mm-0mm偶数ページ
\textwidth 160mm
\newcommand{\command}[1]{「\texttt{#1}」}
\newcommand{\tw}[1]{\texttt{#1}}
\newcommand{\vm}[1]{\boldsymbol{#1}}
%
\renewcommand{\lstlistingname}{リスト}
\lstset{language=C,%
        basicstyle=\footnotesize,%
        commentstyle=\textit,%
        classoffset=1,%
        keywordstyle=\bfseries,%
	frame=tRBl,framesep=5pt,%
	showstringspaces=false,%
        numbers=left,stepnumber=1,numberstyle=\footnotesize%
	}%
%
\begin{document}
\title{C言語の学習\\型変換・記憶クラス・初期化・演算子}
\author{山本昌志\thanks{独立行政法人　秋田工業高等専門学校　電気工学科}}
\date{2004年5月12日}
\maketitle
%
%=====================================================================
\section{本日の学習内容}
%=====================================================================
C言語の基本的な部分を学習する。内容は、教科書の5〜8章である。各章の内容と理解す
べきことは、以下の通りである。
%
\begin{list}{}{\leftmargin=5zw \rightmargin=2zw \labelsep=1zw
 \labelwidth=5zw \itemindent=0pt}
 \item[\textbf{5章}]\textbf{型変換}
		      \begin{itemize}
		       \item 暗黙の型変換により、データは自動的に無難な型に変換
			     される。
		       \item 任意の型に変換するためには、明示的な型変換(キャスト)
			     を使う。
		      \end{itemize}
 \item[\textbf{6章}]\textbf{記憶クラス}
		      \begin{itemize}
		       \item ローカル変数とグローバル変数の違い。
		       \item 自動変数(auto)と静的変数(static)の違い。
		      \end{itemize}
 \item[\textbf{7章}]\textbf{初期化}
		      \begin{itemize}
		       \item 配列の宣言と同時に代入演算子(\tw{=})を用いて、変数
			     に値が代入できる。
		      \end{itemize}
 \item[\textbf{8章}]\textbf{演算子}
		      \begin{itemize}
		       \item 関係演算子、等価演算子、論理演算子の使い方。
		       \item インクリメント、デクリメント演算子の使い方。
		       \item 代入演算子の使い方。
		      \end{itemize}
\end{list}
%
%
%=====================================================================
\section{型変換(教科書の5章)}
%=====================================================================
メモリーに格納されているビットの並びを考えると、コンピューターでは同じ型の変数同
士で演算を行うのが望ましい。プログラマーはそのようにソースコードを書くべきである
が、避けられないこともある。そのようなときに、暗黙の型変換、あるいは明示的な型変
換(キャスト)が使われる。
%
%---------------------------------------------------------------------
\subsection{暗黙の型変換(p.62)}
%---------------------------------------------------------------------
教科書には代入時型変換・関数の引数型変換・単項型変換・算術変換が書かれているが、
諸君にとって重要なのは、最初と最後の型変換である。暗黙の型変換は、いろいろとルー
ルが書かれているが、精度の高い方に変換され、プログラマーにとって都合の良い仕様な
ので、あまり気にする必要はない。唯一、整数と整数の除算のみ気を付ければよい。C言
語では、整数同士の除算の結果は整数となる。これについては、後の練習問題で体験して
もらう。
%
%-------------------------------
\subsubsection{代入時型変換(p.62)}
%-------------------------------
代入演算子(\tw{=})は、右辺の変数の値を、左辺の変数に代入する。右辺と左辺の型が異
なる場合に、型変換が行われる。リスト\ref{prog:type_trans}をみて、動作の内容を理
解して欲しい。
%
\begin{list}{}{\leftmargin=4em \labelwidth=3em}
 \item[9行] 倍精度実数型(\tw{double})の値を整数型(\tw{int})の変数へ代入
 \item[10行] 整数型(\tw{int})の値を倍精度実数型(\tw{double})の変数へ代入
 \item[12行] 変数 \tw{j} を10進数(\tw{\%d})で、\tw{y} の値を浮動小数点数
	    (\tw{\%f})で表示(教科書p.322変換指定子)。これらの間に、タブ
	    (\tw{$\backslash$t})で適当な空白を入れている(教科書p.28表2-4)。
\end{list}
%
\begin{lstlisting}[caption=代入時型変換の例,label=prog:type_trans]
#include <stdio.h>
int main(){
  int i,j;
  double x,y;
  
  i=123;
  x=4.567;
  
  j=x;
  y=i;

  printf("j = %d\tj = %f\n", j, y);
  
  return 0;
}
\end{lstlisting}\vspace{5mm}
%
\fbox{実行結果}
%
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
	j = 4   j = 123.000000
 \end{verbatim}
\end{quote}
%
リスト\ref{prog:type_trans}の結果について、以下を考えよ。
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]代入時型変換が行われている行を示せ。また、代入時型変換
			 が行われていない行を示せ。
  \item[\textbf{[練習2]}]実行結果がなぜそのようになったか考えよ。
 \end{itemize}
\end{quote}
%
%
%----------------------------
\subsubsection{算術変換(p.64)}
%----------------------------
コンピューター内部で算術演算の処理を行う場合、それは同じ型の方が都合がよい。同じ
性質のビット列の方が都合が良いことは明らかである。そのため、演算を行う2つ型が異
なる場合、どちらかに統一しなくてはならない。C言語では、表現能力の高い型へ統一さ
れて演算が行われることになっている。

倍精度実数と整数の演算を行う場合、それは倍精度実数で計算されるので、プログラマー
は気にしなくて良いのである。反対に、整数型に統一されると、桁落ちにより計算精度が
著しく低下する。これを避けるようにC言語の仕様は決まっている。
%
%---------------------------------------------------------------------
\subsection{明示的な型変換(キャスト)}
%---------------------------------------------------------------------
データの型を変更したい場合に明示的な型変換(キャスト)を使う。これを使うことにより、
倍精度実数型のデータを整数型に、あるいはその反対など、プログラマーのお望みの型に
変換できる。例えば、整数型のデータ \tw{i} と \tw{j} の除算などに便利である。
\tw{i=3, j=4}として、\tw{i/j}を計算すると \tw{0} になってしまいプログラマーの意
図したとおりに動作しない。このときに、\tw{(doubel)i}として、整数型の変数の値を一
時的に倍精度実数にして計算すると問題が解決される。
%
%
\begin{list}{}{\leftmargin=4em \labelwidth=3em}
 \item[9行] 整数変数 \tw{i} の値を一時的に、倍精度実数に変換している。そうすると、
	    倍精度実数と整数の除算になる。次に、暗黙の型変換が適用され、最終的には倍
	    精度実数同士の除算になり、倍精度実数の演算結果が得られる。
\end{list}
%
\begin{lstlisting}[caption=キャストを使用した例,label=prog:cast]
#include <stdio.h>
int main(){
  int i,j;
  double x;
  
  i=3;
  j=4;
  
  x=(double)i/j;

  printf("x = %f\n", x);
  
  return 0;
}
\end{lstlisting}\vspace{5mm}
%
\fbox{実行結果}
%
\begin{quote}
 \setlength{\baselineskip}{12pt}
 \begin{verbatim}
	x = 0.750000
 \end{verbatim}
\end{quote}
%
以下の練習問題を実施せよ。
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]リスト\ref{prog:cast}を書き換えて、以下の結果を調べよ。
			 そして、その理由を考えよ。
			 \begin{align*}
			  &\text{\tw{x=i/j}}&
			  &\text{\tw{x=i/4.}}&
			  &\text{\tw{x=i*1.0/j}} \\
			  &\text{\tw{x=(double)(i/j)}}&
			  &\text{\tw{i/(double)j}}&
			 \end{align*}

 \end{itemize}
\end{quote}
%
%=====================================================================
\section{記憶クラス(教科書の6章)}
%=====================================================================
記憶クラスの話は、関数(サブルーチン)を使わないと御利益がない。そこで、本日はこの
プリントを読む程度にとどめるのが良いだろう。関数の学習の時に、ちゃんと説明する。
%---------------------------------------------------------------------
\subsection{ローカル変数とグローバル変数(p.68)}
%---------------------------------------------------------------------
変数には宣言をする場所によりローカル変数とグローバル変数がある。
%
\begin{list}{}{\leftmargin=10em \labelwidth=8em}
 \item[ローカル変数] 関数の外で宣言され、その関数の中だけで使用できる。関数がコー
		     ルされるとメモリー上に変数が配置される。その関数の処理が終
		     わるとその変数は消滅する。通常、よく使われる。
 \item[グローバル変数] 関数の外で宣言され、どの関数でも使用できる。プログラムが
		     起動されるとメモリー上に変数が配置される。プログラムが終了
		     するまで、変数は維持される。
\end{list}

教科書のp.69の図6-1を見て欲しい。ここでは、こんなものがあると思うだけでよい。関
数の時にもう少し分かりやすく説明する。ただ、グローバル変数はできるだけ使わない方
が良い。プログラムの独立性が低くなるし、非常に分かりづらいバグが発生することがあ
る。この意味については、もう少しプログラムに馴れれば理解できるであろう。

この授業で諸君は、グローバル変数を使うプログラムを書くことはほとんどないであろう。
%
%---------------------------------------------------------------------
\subsection{自動変数(auto)と静的変数(static)　(p.70, p.77)}
%---------------------------------------------------------------------
静的変数は、変数宣言の前に \tw{static} と付ければ良い。一方、今まで学習してきた変数は
\tw{static}が無いので、自動変数である。それらの違いは、次に通りである。

\begin{list}{}{\leftmargin=10em \labelwidth=8em}
 \item[自動変数] 関数内でのみ値を保持する。関数の動作が終わると、メモリーの解放
		 され、その値は2度と使えない。新たにその関数をコールすると、新た
		 にメモリーを確保する。この場合、前の場所と同じとは限らない。
 \item[静的変数] プログラムが起動されたときにメモリーが確保され、プログラムが終
		 了するまでそれが維持される。
\end{list}
%
この授業で諸君は、グローバル変数を使うプログラムを書くことはほとんどないであろう。
%=====================================================================
\section{初期化(教科書の7章)}
%=====================================================================
%---------------------------------------------------------------------
\subsection{暗黙の初期化(p.90)}
%---------------------------------------------------------------------
変数宣言をしただけで値の設定を行わない場合、暗黙の初期が行われる。変数宣言をす
ると、コンピューターのメモリーが予約される。予約されたメモリーの各ビットは、
\tw{0} か \tw{1} が詰まっているわけでなにがしかの値がある。この値であるが、変数
の記憶クラスによって異なる。
\begin{itemize}
 \item 自動変数とレジスタ変数の場合、値がどのようになっているか分からない。
 \item 静的変数(\tw{static})とグローバル変数の場合、0となっている。
\end{itemize}
%

自動変数の値の設定を行わないで、ゼロになっていると勘違いし、プログラムを作成しす
ることがある。自動変数を使うときには十分注意が必要である。
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]整数型の変数として、グローバル変数 \tw{i} 、ローカルの
			 自動変数 \tw{j} 、ローカルの静的変数 \tw{k} を宣言して、
			 それに格納されている値を調べよ。(ヒント:p.91の上の方の
			 プログラム)
 \end{itemize}
\end{quote}
%
%---------------------------------------------------------------------
\subsection{変数の初期化(p.91)}
%---------------------------------------------------------------------
教科書の p.91 に書かれているように、変数宣言とともに代入演算子を用いて、初期値を
設定できる。この設定する初期値は、コンパイル時に値が計算できなくてはならない。静
的変数(\tw{static})はコンパイル時に値が決定されて、それがメモリーの初期値となる。
自動変数はその関数が実行されるときに初めて、メモリーが確保されて、その値が設定さ
れる。この辺の話は、関数の時にするので、あまり気にしないで欲しい。
%
%=====================================================================
\section{演算子(教科書の8章)}
%=====================================================================
%---------------------------------------------------------------------
\subsection{算術演算子(p.107)}
%---------------------------------------------------------------------
算術演算子(教科書 p.107)については、今更説明するまでもないであろう。この中で、剰
余\footnote{教科書では余りと表現している}(\tw{\%})はかなり便利である。\tw{11\%4}
の演算結果は、\tw{3}である。覚えておくと良い。
%
%---------------------------------------------------------------------
\subsection{関係演算子、等価演算子、論理演算子(p.108〜)}
%---------------------------------------------------------------------
これらの演算は、主に論理演算に使われる\footnote{論理演算は、制御文\tw{if}
とともに使われることがほとんどである。}。論理が正しい(真 True)か誤り(偽 False)と
いう演算である。演算の結果は、真か偽のいずれかである。真の場合が 1 で、偽の場合
が 0 である。

%-------------------------------
\subsubsection{関係演算子(p.108)}
%-------------------------------
算術演算子の \tw{+} は2つのデータの加算を行い、その和を返す。\tw{5+8} が \tw{13}
になるようにである。関係演算子(p.108)も同じで、2つのデータの演算を行い値を返す。
関係演算子が返す値は、\tw{0} か \tw{1} である。たとえば、\tw{10<20}の演算結果は
 \tw{1} 、\tw{20>10}は \tw{0}になる。もちろん、演算を行う2つの数値は、実数でも良
 い。関係演算子は、大小の比較を行ってその判定をしていると考える。難しいことは、
 なにもない。
%
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]以下に示すそれぞれの \tw{a} の値を計算し、結果を表示す
			 るプログラムを作成せよ。4番目の演算結果については、演算
			 子の優先順位(p.135表8-3)が問題となる。
			 \begin{align*}
			  &\text{\tw{a=1+2}}&
			  &\text{\tw{a=1<2}}&
			  &\text{\tw{a=2>1}}\\
			  &\text{\tw{a=1+3>=2+2}}&
			  &\text{\tw{a=5*((1<2)+(2<4))}}&
			 \end{align*}
  \item[\textbf{[練習1]}]次の \tw{d} の値をC言語のプログラムで計算せよ。なぜ
			 \tw{d} の値がそのようになるのか考えよ。ヒント、教科書
			 p.34表3-1を見よ。
			 \begin{align*}
			  &\text{\tw{a=1122334455;}}&
			  &\text{\tw{b=1122334455;}}\\
			  &\text{\tw{c=a+b;}}&
			  &\text{\tw{d=1<c;}}
			 \end{align*}
 \end{itemize}
\end{quote}
%
%-------------------------------
\subsubsection{等価演算子(p.108)}
%-------------------------------
関係演算子が大小の比較を表すのに対して、等価演算子は等しいか否かを表す。
%
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]教科書のp.108の等価演算子の表を見ながら、以下の演算結果
			 の値を考えよ。もし分からない場合は、プログラムを作成し
			 て、計算して見よ。
			 \begin{align*}
			  &\text{\tw{100 == 100}}&
			  &\text{\tw{3 == 5}}&
			  &\text{\tw{3.0 == 3}}\\
			  &\text{\tw{6 != 5}}&
			  &\text{\tw{5 != 5}}
			 \end{align*}
 \end{itemize}
\end{quote}
%
%-------------------------------
\subsubsection{論理演算子(p.109)}
%-------------------------------
論理演算子は2年生の時に学習したブール代数の演算子である。ブール演算では、否定は
NOT で、論理積は AND で、論理和は OR で表す。しかし、p.109の表に示すような記号を
用いる。当然これも真理値表で書くことができて、表\ref{table:Not_A}〜
\ref{table:A+B}のように表す。

演算の対象が 0 の場合は偽 (0) として扱われ、1　の場合は真 (1) となる。これは簡単
でブール代数の演算そのものである。表\ref{table:Not_A}〜\ref{table:A+B}のようにな
る。
%
\begin{table}[H]
 \begin{center}
  \begin{tabular}{ccc}
%
   \begin{minipage}[t]{0.30\hsize}
    \caption{否定の演算}
    \label{table:Not_A}
    \begin{center}
     \begin{tabular}{c|c} \hline
      \tw{a} & \tw{!a} \\ \hline
      0 & 1 \\
      1 & 0 \\ \hline
     \end{tabular}
    \end{center}
   \end{minipage}
%
   \begin{minipage}[t]{0.35\hsize}
    \caption{論理積の演算}
    \label{table:A*B}
    \begin{center}
     \begin{tabular}{cc|c} \hline
      \tw{a} & \tw{b} & \tw{a \&\& b} \\ \hline
      0 & 0 & 0 \\
      0 & 1 & 0 \\
      1 & 0 & 0 \\
      1 & 1 & 1 \\ \hline
     \end{tabular}
    \end{center}
   \end{minipage}
%
   \begin{minipage}[t]{0.35\hsize}
    \caption{論理和の演算}
    \label{table:A+B}
    \begin{center}
     \begin{tabular}{cc|c} \hline
      \tw{a} & \tw{b} & \tw{a || b} \\ \hline
      0 & 0 & 0 \\
      0 & 1 & 1 \\
      1 & 0 & 1 \\
      1 & 1 & 1 \\ \hline
     \end{tabular}
    \end{center}
   \end{minipage}
%
  \end{tabular}
 \end{center}
\end{table} 
%

問題は、演算の対象が \tw{0} や \tw{1} 以外の場合である。プログラマーからすれば、
コンパイラーがエラーを出すか、実行時にエラーを出して止まってくれれば良いのだが、
実際にはそうはならない。C言語の仕様では \tw{0} と \tw{1} 以外の場合、それは真(1)
として扱うと決まっている。C言語では、
\begin{itemize}
 \item 0は偽
 \item 0以外は真
\end{itemize}
として取り扱われると覚えておく。そうすると、論理演算は表\ref{table:Not_A_in_C}〜
\ref{table:A+B_in_C}のようになる。
%
\begin{table}[H]
 \begin{center}
  \begin{tabular}{ccc}
%
   \begin{minipage}[t]{0.30\hsize}
    \caption{C言語の否定演算}
    \label{table:Not_A_in_C}
    \begin{center}
     \begin{tabular}{l|c} \hline
      \tw{a} & \tw{!a} \\ \hline
      0 & 1 \\
      0以外 & 0 \\ \hline
     \end{tabular}
    \end{center}
   \end{minipage}
%
   \begin{minipage}[t]{0.35\hsize}
    \caption{C言語の論理積}
    \label{table:A*B_in_C}
    \begin{center}
     \begin{tabular}{ll|c} \hline
      \tw{a} & \tw{b} & \tw{a \&\& b} \\ \hline
      0 & 0 & 0 \\
      0 & 0以外 & 0 \\
      0以外 & 0 & 0 \\
      0以外 & 0以外 & 1 \\ \hline
     \end{tabular}
    \end{center}
   \end{minipage}
%
   \begin{minipage}[t]{0.35\hsize}
    \caption{C言語の論理和}
    \label{table:A+B_in_C}
    \begin{center}
     \begin{tabular}{ll|c} \hline
      \tw{a} & \tw{b} & \tw{a || b} \\ \hline
      0    & 0     & 0 \\
      0    & 0以外 & 1 \\
      0以外 & 0    & 1 \\
      0以外 & 0以外 & 1 \\ \hline
     \end{tabular}
    \end{center}
   \end{minipage}
%
  \end{tabular}
 \end{center}
\end{table} 
%---------------------------------------------------------------------
\subsection{インクリメント、デクリメント演算子(p.110)}
%---------------------------------------------------------------------
インクリメント演算子(\tw{++})は 1 加算し、デクリメント演算子(\tw{--})は 1 減算す
る演算子である。教科書に書いてあるように、\tw{a=a+1} あるいは \tw{a=a-1}の代わり
に使われる。カウンターとして使っている変数の値を変化させるときに、使われることが
多く、代入演算子(\tw{=})を使うよりも、インクリメントやデクリメント演算子を使う方
がC言語風で格好良いのである。
%
\begin{lstlisting}[caption=インクリメントとデクリメントの例,label=prog:inc_dec]
#include <stdio.h>

int main(){
  int i,j;

  i=10;
  j=10;

  i++;
  j--;

  printf("i=%d  j=%d\n",i,j);

  return 0;
}
\end{lstlisting}\vspace{5mm}
%
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]リスト\ref{prog:inc_dec}の動作を確かめよ。
 \end{itemize}
\end{quote}
%
%
%---------------------------------------------------------------------
\subsection{代入演算子(p.118)}
%---------------------------------------------------------------------
単純代入演算子(\tw{=})は説明しなくても分かっていると思うだろうが、これがどうして
なかなかちゃんと理解されていないのである。単純代入演算子(\tw{=})は数学のイコール
($=$)と異なり、これは演算子である。演算子と言うことであるから、これを挟んだ変数
に対して操作をする\footnote{数学の$3+5=8$の意味は、演算子$+$が3 と 5 に作用して
その結果は、8に等しい。$+$ は演算子であるが、$=$ は演算子ではない。}。 その操作
は、左辺の式の値を右辺の変数に代入する。必ず、右辺は式\footnote{定数や変数が一つ
の場合も、式の範疇である。}で、右辺は変数でなくてはならない。もし、左辺と右辺が
等しいか否かの比較は等価演算子(\tw{==})を使う。C言語では、代入演算子(\tw{=})と等
価演算子(\tw{==})はしっかり区別を付けなくてはならない。

複合代入演算子もよく使われる。特に \tw{+=} は使われることが多いので、よく覚えておか
なくてはならない。\tw{a} の変数の値に \tw{b} を加算する場合、\tw{a=a+b}とすれば
よいが、C言語では\tw{a+=b}と書くのが普通である。前者でも問題なく実行できるが、後
者の方がC言語風で格好良いとされている。ほかの複合代入演算子も同じである。
%
%
\begin{lstlisting}[caption=複合代入演算子の例,label=prog:fukugoudainyu]
#include <stdio.h>

int main(){
  int i,j;

  i=3;
  j=6;

  i+=j;

  printf("i=%d  j=%d\n",i,j);

  return 0;
}
\end{lstlisting}\vspace{5mm}
%
\begin{quote}
 \begin{itemize}
  \item[\textbf{[練習1]}]リスト\ref{prog:fukugoudainyu}の動作の結果を考えよ。
 \end{itemize}
\end{quote}
%
%======= 参考文献 ====================================================
\bibliographystyle{junsrt}
\bibliography{reference} 
%=====================================================================
\end{document}
