PowerPoint版, 13MB

Download Report

Transcript PowerPoint版, 13MB

C言語によるプログラミング入門
「プログラミングと計測・制御」講義資料
1
プログラミング言語

機械語

アセンブリ言語

アセンブル
C言語


コンパイル

低級言語(低水準言語)と高級言語(高水準言語)

コンパイル方式とインタプリタ方式
2
プログラミング言語とソフトウェア

OS

デバイスドライバ

ミドルウェア

デスクトップアプリケーション

Webアプリケーション
3
C言語(の|を学ぶ)利点

実行可能な処理 (ハードウェアに密着した処理)

実行速度

プログラムのサイズ (ファイルサイズ・メモリ使用
量)

コンピュータやプログラミングそのものに対する理
解
4
“計測・制御”は?

組み込みシステム

マイコンの制御プログラム


計測プログラム
制御プログラム
アセンブリ言語

5
プログラムの作成・実行の流れ
 ex01.c

6
ex02.c
プリプロセッサディレクティブ


#includeディレクティブ
main()関数
int型の変数
printf()関数, scanf()関数
文字列定数
コメント
return文






7
当面の定型部分
#include <stdio.h>
int main(void)
{
/* 必要な命令をここに記述する */
return (0);
}
8
コーディングスタイル

インデント・空行・コメント

関数名・変数名などの単語はつなげて書く。

int, main, age, printf, return
プリプロセッサディレクティブを用いた命令を途中
で改行する場合、行末に\が必要。同じ行にほかの命
令を書けない。
文字列定数の途中では改行できない。



連続した文字列定数はまとめられるため、複数の文字列
定数に分ければ改行を挟むことができる。
 ex03.c

9
#include
<stdio.h>
#include \
<stdlib.h>
#include <string.h> #include <math.h>
#include <time.h> int main(void)
---/* 誤り */
printf("親譲りの無鉄砲で
小供の時から損ばかりしている。");
/* 正しい */
printf("親譲りの" "無鉄砲で"
"小供の時から" "損ばかりしている。");
/* ↑と↓は全く同じ */
printf("親譲りの無鉄砲で小供の時から損ばかりしている。");
10
変数

プログラム中で扱われるデータを記憶しておくため
の入れ物

変数は型を持つ

利用する前に宣言が必要

(ローカル)変数はブロックの先頭で宣言
11
基本型
種類
型名
文字型
char
別名
signed char
unsigned char
整数型
浮動小数点型
signed short int
short int, signed short, short
unsigned short int
unsigned short
signed int
int, signed
unsigned int
unsigned
signed long int
long int, signed long, long
unsigned long int
unsigned long
float
double
long double
12
ex04.c
[Windows 7 (64ビット), VC++ 2010]
char型:
-128~127
signed char型:
-128~127
unsigned char型: 0~255
signed short型: -32768~32767
unsigned short型: 0~65535
signed int型:
unsigned int型:
-2147483648~2147483647
0~4294967295
signed long型:
-2147483648~2147483647
unsigned long型: 0~4294967295
13
ex04.c
[FreeBSD 7.x (amd64), GCC 4.2.1]
char型:
-128~127
signed char型:
-128~127
unsigned char型: 0~255
signed short型: -32768~32767
unsigned short型: 0~65535
signed int型:
unsigned int型:
-2147483648~2147483647
0~4294967295
signed long型:
-9223372036854775808~9223372036854775807
unsigned long型: 0~18446744073709551615
14
変数の宣言
型名 変数名;
char c;
short age;
int salary;
long national_debt;
int x, y; /* まとめて宣言 */
national_debt
NationalDebt
nationalDebt (キャメルケース)
15
識別子

キーワード(int・returnなど)以外

先頭は [A-Za-z_]

2文字目以降は [0-9A-Za-z_]
× int return;
× int 10gatsu;
× int national-debt;
16
代入

= (代入演算子) を用いる
char c;
int i;
double d;
c = 'A';
i = 20;
d = 3.45;
/* 宣言と同時に代入も可能 */
char c = 'B';
int x = 10, y = 20;
double d = 5.5;
17
文字型



実体は整数
"A"・・・文字列定数
'A'・・・文字定数
ASCIIコード表
00
08
10
18
20
28
30
38
40
48
50
58
60
68
70
78
18
NUL
BS
DLE
CAN
SP
(
0
8
@
H
P
X
`
h
p
x
01
09
11
19
21
29
31
39
41
49
51
59
61
69
71
79
SOH
HT
DC1
EM
!
)
1
9
A
I
Q
Y
a
i
q
y
02
0A
12
1A
22
2a
32
3a
42
4a
52
5a
62
6a
72
7a
STX
NL
DC2
SUB
"
*
2
:
B
J
R
Z
b
j
r
z
03
0B
13
1B
23
2b
33
3b
43
4b
53
5b
63
6b
73
7b
ETX
VT
DC3
ESC
#
+
3
;
C
K
S
[
c
k
s
{
04
0C
14
1C
24
2c
34
3c
44
4c
54
5c
64
6c
74
7c
EOT
NP
DC4
FS
$
,
4
<
D
L
T
\
d
l
t
|
05
0D
15
1D
25
2d
35
3d
45
4d
55
5d
65
6d
75
7d
ENQ
CR
NAK
GS
%
5
=
E
M
U
]
e
m
u
}
06
0E
16
1E
26
2e
36
3e
46
4e
56
5e
66
6e
76
7e
ACK
SO
SYN
RS
&
.
6
>
F
N
V
^
f
n
v
~
07
0F
17
1F
27
2f
37
3f
47
4f
57
5f
67
6f
77
7f
BEL
SI
ETB
US
'
/
7
?
G
O
W
_
g
o
w
DEL
printf()関数


ディスプレイに表示する(標準出力に出力する)関数
実引数に、表示する文字列定数を指定
/* 関数呼び出し */
関数名(実引数1, 実引数2, ...)
printf("Hello, World!\n")
19
エスケープシーケンス
エスケープ
シーケンス
意味
\a
警報
\n
改行
\'
文字 '
\"
文字 "
\\
文字 \
20
printf("\a");
printf("Hello,\nWorld!\n");
×
○
×
○
char c = ''';
char c = '\'';
printf("He said "Hello."");
printf("He said \"Hello.\"");
演習

学籍番号と自分の名前を表示するプログラムを作る

学籍番号の後で改行すること
出力例
11E○○○○X
森本 容介
21
演習

ベルを鳴らしてみる
22
変数の値を表示する



printf()関数の第1引数に、「%」からはじまる変換
指示子を含める
第2引数以降に、置き換える値を指定する
変換指示子の%の後ろの文字をフォーマット文字と
いう
printf("私は%d歳です。\n", 18);
 私は18歳です。
int height = 170, weight = 60;
printf("身長は%dcm、体重は%dkgです。\n", height, weight);
 身長は170cm、体重は60kgです。
23
printf()関数の主なフォーマット文字
フォーマット
文字
意味
d
符号付き10進整数
o
符号なし8進整数
u
符号なし10進整数
x, X
符号なし16進整数 / 10進数の10~15を表す記号は、フォー
マット文字がxなら小文字のa~f、Xなら大文字のA~F。
f
小数
e, E
浮動小数点数の指数表記 / フォーマット文字がeなら仮数e指
数、Eなら仮数E指数の形式で出力。仮数は、整数部が1桁の
小数、指数は、+または-から始まる整数。
c
文字
s
文字列
%
%自体 ("%%"が"%"に置き換えられる)
24
ex05.c
変換指示子を含まない例:
programming language
char型変数:
A
int型変数:
987 / 1733 / 3db / 3DB
-987
double型変数:
123.456700 / 1.234567e+02 / 1.234567E+02
-0.000432 / -4.321000e-04 / -4.321000E-04
"%"自体:
降水確率は30%
25
scanf()関数



キーボードから入力する(標準入力からの入力を読み
込む)関数
第1引数は、変換指示子を含む文字列定数
第2引数以降に、代入先の変数を&付きで指定
int i;
scanf("%d", &i);
%c, %d, %f(float), %lf(double)
26
ex02.c (再掲)
int age;
printf("How old are you? > ");
scanf("%d", &age);
/* 10年後の年齢を表示する */
printf("In ten years you will be %d years old.\n", age + 10);
27
マニュアルの読み方
28
演習

名字の頭文字と年齢を聞き、出力するプログラムを
作る
動作例
---名字の頭文字は? > S
年齢は? > 21
Sさんの年齢は21歳です。
 ex06.c
29
算術演算

演習: 整数を2つ入力すると、和・差・積・商・剰余
を表示するプログラムを作る
演算子
a + b
a - b
a * b
a / b
a % b
30
役割
和
差
積
商
剰余
例
7 +
7 7 *
7 /
7 %
3  10
3  4
3  21
3  2
3  1
動作例
---a = 7
b = 3
a
a
a
a
a
+
*
/
%
b
b
b
b
b
=
=
=
=
=
10
4
21
2
1
キーボード
から入力
 ex07.c
演算子


演算子: 演算を表す(行う)記号
オペランド(被演算子): 演算の対象となる値・変数
演算子
i + 3
二項演算子
31
オペランド
&age
単項演算子
式と評価

式: 定数・変数・[演算子+オペランド]
i = j * 5
i, j, 5, j * 5, i = j * 5
j が 3 なら・・・
32
式
評価した値
j
3
5
5
j * 5
15
i = j * 5
15
優先順位
33
演算子
結合
()(関数呼び出し) [] . -> ++(後置) --(後置)
左
↑
++(前置) --(前置) +(単項) -(単項) ! ~ ()(キャスト演算子)
*(単項, 間接演算子) &(単項, アドレス演算子) sizeof sizeof()
右
高
*(二項) / %
左
↑
+(二項) -(二項)
左
↑
<< >>
左
< <= > >=
左
== !=
左
&(二項)
左
^
左
↓
|
左
↓
&&
左
低
||
左
↓
?:
右
= += -= *= /= %= &= ^= |= <<= >>=
右
,
左
演算子の優先順位と結合
i = 3 + 4 * 5;
i = 3 - 4 - 5;
i = -j - 4;
i = j = 3;
i = (3 + 4) * 5;
34
型とキャスト

ex08.c


暗黙の型変換
キャスト演算子
5 /
5.0
5 /
5.0
3 = 1
/ 3 = 1.666667
3.0 = 1.666667
/ 3.0 = 1.666667
[ i = 5, j = 3 ]
i / j = 1
(double)i / j = 1.666667
(double)(i / j) = 1.000000
35
sizeof演算子


型・変数・定数などの大きさを求める
返される値は size_t 型
sizeof(型名)
sizeof 式
typedef・・・既存の型に別名をつける
typedef 既存の型名 別名;
[FreeBSD 7.x (amd64), GCC 4.2.1] の場合
typedef unsigned long __uint64_t;
typedef __uint64_t
__size_t;
typedef __size_t
size_t;
36
ex09.c
[Windows 7 (64ビット), VC++ 2010]
sizeof(char)
= 1
sizeof(short int)
sizeof(int)
sizeof(long int)
= 2
= 4
= 4
sizeof(float)
= 4
sizeof(double)
= 8
sizeof(long double) = 8
sizeof(size_t)
37
= 4
sizeof
sizeof
sizeof
sizeof
sizeof
'A'
3
3.0
"A"
"ABC"
sizeof (3 + 5)
sizeof (3.0 + 5)
=
=
=
=
=
4
4
8
2
4
= 4
= 8
ex09.c
[FreeBSD 7.x (amd64), GCC 4.2.1]
sizeof(char)
= 1
sizeof(short int)
sizeof(int)
sizeof(long int)
= 2
= 4
= 8
sizeof(float)
= 4
sizeof(double)
= 8
sizeof(long double) = 16
sizeof(size_t)
38
= 8
sizeof
sizeof
sizeof
sizeof
sizeof
'A'
3
3.0
"A"
"ABC"
sizeof (3 + 5)
sizeof (3.0 + 5)
=
=
=
=
=
4
4
8
2
4
= 4
= 8
char c = 'A'; について考える


char型・・・1バイト
文字定数・・・int型 = ここの環境では4バイト
char c = 'A';
'A': 00000000 00000000 00000000 01000001
c : 01000001
char c = (char)'A';
39
課題-1

身長と体重を入力すると、BMIを出力するプログラ
ムを作る


身長(cm)・体重(kg)は整数で入力
BMIは小数で出力
𝐵𝑀𝐼 =
体重(𝑘𝑔)
身長(𝑚)
2
動作例
---身長は? (cm) > 165
体重は? (kg) > 55
BMIは 20.202020 です
40
if文
if (制御式) 文

制御式を評価した値が0でなければ文を実行する

ex10.c
if (制御式) 文1 else 文2

制御式を評価した値が0でなければ文1を、0なら文2
を実行する

41
ex11.c
式と評価 (復習)

式: 定数・変数・[演算子+オペランド]
int i = 3;
/* 定数 */
if (5) ・・・;
/* 変数 */
if (i) ・・・;
/* 二項の-演算子: 減算の結果 */
if (i - 3) ・・・;
/* 代入演算子: 代入した値 */
if (i = 5) ・・・;
42
制御式によく使う演算

関係演算

論理演算
43
関係演算

2つのオペランドを比較する演算
演算子
a == b
a != b
a < b
役割
aとbが等しければ1、そうでなければ0
aとbが等しくなければ1、そうでなければ0
aがb未満であれば1、そうでなければ0
a <= b
a > b
a >= b
aがb以下であれば1、そうでなければ0
aがbより大きければ1、そうでなければ0
aがb以上であれば1、そうでなければ0
44
関係演算子の利用例
if (i == j)
printf("'i' is equal to 'j'\n");
if (i > j)
printf("'i' is larger than 'j'\n");
---if (i % 2)
printf("%d is an odd number.\n", i);
if (i % 2 == 0)
printf("%d is an even number.\n", i);
45
演習

以下の2つのif文の違いを考える
int i = 3;
if (i == 5) ・・・; /* (1) */
if (i = 5) ・・・; /* (2) */

以下のprintf()関数の出力を考える
int i = 3;
printf("%d\n", i == 5); /* (3) */
printf("%d\n", i < 5); /* (4) */
printf("%d\n", i = 5); /* (5) */
46
論理演算


真理値を対象とした演算
C言語では、0以外が真、0が偽
演算子
a && b
a || b
!a
47
役割
aとbの両方とも0以外であれば1(真)、そう
でなければ0(偽) ・・・ 論理積
aとbの片方でも0以外であれば1(真)、そう
でなければ0(偽) ・・・ 論理和
aが0であれば1(真)、そうでなければ
0(偽) ・・・ 論理否定
論理演算の真理値表
論理積
論理和
a
b
a && b
a
b
a || b
1
1
1
1
1
1
1
0
0
1
0
1
0
1
0
0
1
1
0
0
0
0
0
0
論理否定
48
a
!a
1
0
0
1
論理演算子の利用例
if (age >= 27 && age <= 33)
printf("You are around 30 years old.\n");
if (year % 4 == 0 && year % 100 != 0 || year % 400 == 0)
・・・;
if (!(year % 4) && year % 100 || !(year % 400))
・・・;
---if (i % 2)
printf("%d is an odd number.\n", i);
if (!(i % 2))
printf("%d is an even number.\n", i);
49
演習

整数を2つ入力すると、その排他的論理和を出力す
るプログラムを作る
排他的論理和
a
b
1
1
0
1
0
1
0
1
1
0
0
0
 ex12.c
50
a
XOR
b
動作例
---a = 1
b = 1
a XOR b は 偽
---a = 0
b = 1
a XOR b は 真
かキ
らー
入ボ
力ー
ド
論理演算子の短絡評価
演算子
a && b
a || b
短絡評価
aが0の場合、bを評価しなくても結果が確定
する  bは評価されない(実行されない)
aが0以外の場合、bを評価しなくても結果が
確定する  bは評価されない(実行されない)
/*
* いずれもiが1の場合
* jに1を代入
* 論理演算の結果は
* 使わない
*/
i == 1 && (j = 1);
i != 1 || (j = 1);
51


条件文を簡潔に書ける可能性
がある
言語によっては多用 (C言語
ではあまり見ない)
if文のネスト

ex13.c
if (score >= 90)
printf("秀\n");
else if (score >= 80)
printf("優\n");
else if (score >= 70)
printf("良\n");
else if (score >= 60)
printf("可\n");
else
printf("不可\n");
52
if (score >= 90)
printf("秀\n");
else
if (score >= 80)
printf("優\n");
else
if (score >= 70)
printf("良\n");
else
if (score >= 60)
printf("可\n");
else
printf("不可\n");
複合文

宣言・文の集合を { と } で囲ったもの (ブロック)
int i, j;
/* 中略 */
ブロック
53
if (i <
{
int
tmp
i =
j =
}
j)
tmp;
= i;
j;
tmp;
宣言
文
可読性の向上・バグの予防
if (i % 2)
printf("%d is an odd number.\n", i);
else
printf("%d is an even number.\n", i);
---if (i % 2)
{
printf("%d is an odd number.\n", i);
}
else
{
printf("%d is an even number.\n", i);
}
54
演習

整数を3つ入力すると、その最大値と最小値を出力
するプログラムを作る
動作例
---整数1 > 15
整数2 > 24
整数3 > 8
最大値: 24
最小値: 8
かキ
らー
入ボ
力ー
ド
 ex14.c
55
switch文 (1)

制御式を評価した値が






定数1と一致すればcase 定数1:の
直後へ移動
定数2と一致すればcase 定数2:の
直後へ移動、
・・・、
どの定数とも一致しなければ
default:の直後へ移動
制御式は、評価した値が整数
となる式
caseの後ろは、整数定数や文
字定数
56
switch (制御式)
{
case 定数1:
文1 ・・・
case 定数2:
文2 ・・・
case 定数3:
文3 ・・・
default:
文x ・・・
}
switch文 (2)
int i;
/* (中略) */
switch (i)
{
case 3:
iが3の場合
iが5の場合
文
case 5:
文
default:
文
}
57
iが3でも5でも
ない場合
switch文 (3)


case ・・・: や default: をラベルという
switch文を途中で抜ける場合は、break文を用いる

ほとんどの場合、各ラベルに対応するbreak文が必要

defaultラベルは省略可

 ex15.c
58
switch文 (4)

caseの後ろは、
整数定数や文
字定数
59
switch (制御式)
{
case 5: /* 整数定数 */
case 'a': /* 文字定数 */
/*
* 以下は間違い
* コンパイルできない
*/
case 5: /* 同じ値のラベルが複数 */
case 1.5: /* 浮動小数点数 */
case "a": /* 文字列定数 */
case i: /* 変数 */
case < 3: /* 3未満のつもり */
}
if文とswitch文
if (i == 1)
{
printf("1年生\n");
}
else if (i == 2)
{
printf("2年生\n");
}
else if (i == 3)
{
printf("3年生\n");
}
else
{
printf("それ以外\n");
}
60
switch (i)
{
case 1:
printf("1年生\n");
break;
case 2:
printf("2年生\n");
break;
case 3:
printf("3年生\n");
break;
default:
printf("それ以外\n");
break;
}
演習

月を入力すると、季節を表示するプログラムを作る





switch文を使う
春:3-5月
夏:6-8月
秋:9-11月
冬:12-2月
動作例
---月 (1-12) > 6
6月は夏です
---月 (1-12) > 10
10月は秋です
---月 (1-12) > 15
 ex16.c
61
15月はありません
かキ
らー
入ボ
力ー
ド
単項 + - 演算子
演算子
単項+
単項-
役割
オペランドの値
例
+5
オペランドの符号を反転した値 -5
i = 5 - - j;
二項の - 演算子
(優先順位低)
62
単項の - 演算子
(優先順位高)
複合代入演算子

算術演算と代入演算をまとめて、簡潔に記述
算術演算子と
代入演算子

複合代入演算子
a = a + b
a = a - b


a += b
a -= b
a = a * b
a = a / b
a = a % b



a *= b
a /= b
a %= b
&= ^= |= <<= >>= も複合代入演算子

63
a = a & b  a &= b など
インクリメント・デクリメント演算子
演算子
役割
評価した値
++a
オペランドに1を足す (インクリメント)
インクリメント後
--a
オペランドから1を引く (デクリメント)
デクリメント後
a++
オペランドに1を足す (インクリメント)
インクリメント前
a--
オペランドから1を引く (デクリメント)
デクリメント前
/* 以下の4文は同じ */
/* 前置と後置 */
1.
2.
3.
4.
j = ++i;
 i += 1; j = i;
j = i++;
 j = i; i += 1;
64
++i;
i++;
i += 1;
i = i + 1;
条件演算子 (1)
演算子
a ? b : c
役割
aが0以外であればbを、
そうでなければcを評価
(C言語で唯一の三項演算子)
aが0以外(真)
a ? b : c
aが0(偽)
65
/*
* [iがjより大きければi]
* [そうでなければj]
* を、maxに代入
*/
max = i > j ? i : j;
条件演算子 (2)
a ? b : c



aが0以外の場合、cは評価されない
aが0の場合、bは評価されない
論理演算子の短絡評価同様、条件文を簡潔に書ける
可能性がある
i > j ? (max = i, min = j) : (max = j, min = i);
if (i > j) { max = i; min = j; }
else { max = j; min = i; }
66
演習

右のソースコード
(ex17.c)のコメント部
分に1文を追加し、プロ
グラムを完成させる
#include <stdio.h>
int main(void)
{
int i;
printf("3 + 5 = ");
scanf("%d", &i);
/*
* 条件演算子を用いて、
* 正解であれば「正解です」
* 不正解であれば「間違いです」
* と表示
*/
return (0);
}
67
カンマ演算子 (コンマ演算子)
演算子
a, b


役割
aを評価した後、bを評価する
演算結果はbの評価値
1つの式しか記述できない場所に、複数の式を記述
できる (複数の式を、カンマ演算子で1つの式にす
る)
実用的な例はfor文の回で紹介
68
式と文

式にセミコロンをつければ文 (式文)

1つの文しか記述できない場所に、複数の文を記述
したい  複合文

1つの式しか記述できない場所に、複数の式を記述
したい  カンマ演算子
69
while文
while (条件式) 文




条件式を評価した値が0でない間、文を繰り返し実
行する
文を実行する前に、条件式が毎回評価される
初回に条件式を評価した値が0なら、文は一度も実
行されない
 ex18.c
70
breakとcontinue

break文・・・ループを終了する

continue文・・・残りの処理を飛ばし、次回のルー
プの条件判断へ進む

 ex19.c
71
演習
1.
ex19.cのbreak文とcontinue文の順番を(それら
を含むif文ごと)入れ替えて実行する
2.
プログラムを途中で(強制)終了するには、キー
ボードで[Ctrl]+Cを入力する
3.
意図通りに動かない理由を考える
72
for文
for (式1; 式2; 式3) 文

文を繰り返し実行する



式1: for文に入る前に一度だけ評価される
式2: 評価した値が0でない間、文が繰り返し実行される
式3: 文の実行終了後に毎回評価される

 ex20.c

breakとcontinueは、while文と同じ

73
continueした場合でも、式3は評価される
無限ループ

継続条件が常に成立する(終了条件が常に成立しな
い)繰り返し
while (1) 文
for (式1; 1; 式3) 文
/*
* for文の式2は省略できるので
* 普通は以下のように記述
* (式1・式3も省略可)
* /
for (式1; ; 式3) 文
74
for文とwhile文

for文とwhile文のどちらを使っても、同じループが
実現できる
“文”でcontinueし
ている場合を除く
for (式1; 式2; 式3) 文
while (式2) 文
75
式 1;
while (式2)
{
文・・・
式3;
}
for ( ; 式2; ) 文
ループのネスト

ex21.c
for (i = 0; i < 10; ++i)
{
for (j = 0; j <= i; ++j)
{
printf("O");
}
printf("\n");
}
O
OO
OOO
OOOO
OOOOO
76
iが0のループ,
iが1のループ,
iが2のループ,
iが3のループ,
・・・
jが0のとき (1回)
jが0から1まで (2回)
jが0から2まで (3回)
jが0から3まで (4回)
演習

ex21.cを改変して、
10段の二等辺三角形に
する
ス
ペ
ー
ス
 ex22.c
77
O
OOO
OOOOO
OOOOOOO
OOOOOOOOO
OOOOOOOOOOO
OOOOOOOOOOOOO
OOOOOOOOOOOOOOO
OOOOOOOOOOOOOOOOO
OOOOOOOOOOOOOOOOOOO
カンマ演算子の利用

ex23.c
for (i = 1, j = 0; i <= 100; ++i)

ex24.c
for (d = 0; u; u /= 10, ++d)
78
関数


決められた処理を行う命令のまとまり
引数を受け取り、戻り値を返す

引数: 関数の動作に必要な値




呼び出し側・・・実引数
受け取り側(関数側)・・・仮引数
戻り値: 関数を実行した結果の値
(標準)ライブラリ関数: C言語の規格で定められ、処
理系が提供する関数


79
printf()
scanf()
ライブラリ関数の利用

プリプロセッサディレクティブを用いて、必要な
ヘッダファイルをインクルードする

printf()やscanf()には、stdio.hが必要
#include <stdio.h>

よく使うライブラリ関数に必要なヘッダファイル




80
数学: math.h
入出力: stdio.h
雑多: stdlib.h
文字列操作: string.h
ライブラリ関数の例


pow()・・・累乗を計算する
 ex25.c
[MSDNの関数リファレンス]
Calculates x raised to the power of y
double pow(
double x,
double y
);
Required header: <math.h>
 double型の実引数xとyを与えると
xのy乗をdouble型で返す
math.hが必要
81
pow()のおまけ

言語によっては、累乗の演算子を用意
C言語
pow()関数
pow(5, 3) /* 5の3乗 */
Perl
**演算子
5 ** 3 # 5の3乗
Basic ^演算子
5 ^ 3 ' 5の3乗
/* C言語の^演算子は別の役割 */
printf("%d\n", 5 ^ 3);
 6 !?
82
演習


角度(度)を入力すると、その正弦(sin)を表示するプ
ログラムを作る
動作例
ソースコードの先頭に
#define _USE_MATH_DEFINES
#include <math.h>
と記述すると、円周率を
M_PI と記述できる
例: double pi = M_PI;
(処理系依存)
 ex26.c
83
---角度(度) > 30
sin 30° = 0.500000
---角度(度) > -45
sin -45° = -0.707107
---角度(度) > 270
sin 270° = -1.000000
キ
ー
ボ
ー
ド
か
ら
入
力
関数を作る
戻り値の型 関数名(仮引数の宣言)
{
/* 処理 */
return 式; /* 戻り値 */
}
仮引数の宣言:
[仮引数の型 仮引数の名前]
をカンマ区切りで並べる
例: (char x, int y, double z)
84
自作の累乗関数
戻り値は
double型
関数名は
expo
引数はdouble型と
unsigned int型
double expo(double x, unsigned int y)
{
double e = 1;
/* 0の0乗は1 */
while (y-- > 0)
{
e *= x;
}
戻り値は
return (e);
double型
}
85
関数呼び出し (1)


実引数の値が、仮引数にコピーされる
関数呼び出し式を評価すると、関数の戻り値が得ら
れる
関数名(実引数1, 実引数2, ...)
コピー
型名 関数名(型名 仮引数1, 型名 仮引数2, ...)
{
/* 略 */
return 式;
}
86
戻
り
値
関数呼び出し (2)
double expo(double x, unsigned int y)
{
/* 略 */
xに5、yに3がコピーされ、
expo()関数内で普通の変数
として利用できる
return (e);
}
d = expo(5, 3);
87
expo()関数の戻り値である125
(double型)がdに代入される
return文
return 式;


return文を実行、または関数の最後( } )まで実行す
ると、関数呼び出しを行った場所へ戻る
return文は、



88
関数の最後でなくてもよい
1つの関数内に複数あってもよい
が、最後に1つだけの方が分かりやすい
関数の定義と呼び出し


関数は呼び出す場所より前(ソースコード中で上)に、
定義されていなければならない  ex27.c
関数呼び出しが前に来る場合は、関数プロトタイプ
宣言を行う


関数を使うにあたって、引数の個数と型、戻り値の型な
どを知らせる
 ex28.c
/* 戻り値の型 関数名(仮引数の宣言); */
double expo(double x, unsigned int y);
/* 仮引数名は省略してもよい */
double expo(double, unsigned int);
89
引数・戻り値の不要な関数

引数が不要
戻り値の型 関数名(void)

戻り値が不要
void 関数名(仮引数の宣言)
return文は、式を書かない
return;
90
main()関数

引数を受け取らず、int型の値を返す関数

引数を受け取ることもできる


コマンドライン引数など
戻り値(この講義では、すべて0)にも意味があり、
その値を使うこともできる
91
変数のスコープ (1)

スコープ = 有効範囲

(ローカル)変数:





92
ブロックの先頭で宣言
ブロック内でのみ有効
ブロックが異なれば、同じ変数名を使用可
ブロックがネストしている場合、内側のブロックもス
コープに含まれる
内側のブロックで同じ名前の変数を宣言している場合、
外側の変数が見えなくなる(内側の変数が有効)
変数のスコープ (2)
int main(void)
{
int i = 1;
void func1(int i)
{
/* ... */
}
{
int i = 2;
void func2(void)
{
int i;
/* ... */
/* ... */
}
{
}
/* ... */
}
93
}
値渡しと参照渡し

関数に引数を渡す方法

値渡し





参照渡し



94
実引数の値が仮引数にコピーされて渡される
実引数に変数を指定し、仮引数の変数の値を変更しても、呼び
出し側の変数へは影響しない
C言語の関数は値渡し
 ex29.c
実引数に指定した変数と仮引数の変数が同じものを指す
渡された関数内で仮引数の変数を変更すると、呼び出し側の変
数も変更される
C言語でも参照渡しに近いことができる
演習


整数を4つ入力すると、最大値・最小値・平均値・
標準偏差を表示するプログラムを作る
途中まで作ってあるex30.cを完成させる
動作確認用
最大値
最小値
平均値
標準偏差
整数1
整数2
整数3
整数4
1
2
3
4
4
1
2.5
1.118034
5
2
10
7
10
2
6
2.915476
44
33
22
11
44
11
27.5
12.298374
95
課題-2


3の倍数と3がつく数を判定する関数を作る
途中まで作ってあるkadai-2.cを完成させる
3の倍数か3がつく数
なら “1”、そうでない
なら “0” と表示する
“0”を入力すると、プ
ログラムを終了する
96
Input
0
Input
1
Input
0
Input
1
Input
1
Input
0
Input
a positive integer (0: exit) > 5
a positive integer (0: exit) > 15
a positive integer (0: exit) > 25
a positive integer (0: exit) > 35
a positive integer (0: exit) > 45
a positive integer (0: exit) > 55
a positive integer (0: exit) > 0
かキ
らー
入ボ
力ー
ド
課題-2のヒント
97
8765
8765
876
876
%
/
%
/
87
87
8
8
%
/
%
/
8765
10 
10 
10 
10 
10 
10 
10 
10 
5
876
6
87
7
8
8
0
4321
4321
432
432
%
/
%
/
43
43
4
4
%
/
%
/
4321
10 
10 
10 
10 
10 
10 
10 
10 
1
432
2
43
3
4
4
0
コンパイルの大まかな流れ
1.
2.
3.
4.
プリプロセス (プリプロセッサ)
狭義のコンパイル (コンパイラ)
アセンブル (アセンブラ)
リンク (リンカ)
(処理系によって異なる)
98
プリプロセス

ソースファイルに対する前処理
プリプロセッサが行う

コメントの削除

プリプロセッサディレクティブ = プリプロセッサに
対する指令



99
#includeディレクティブ
#defineディレクティブ
#includeディレクティブ
指定されたファイルを読み込み、#includeディレク
ティブの書かれた位置に挿入する


例) printf()関数のプロトタイプ宣言は、stdio.h、また
はstdio.hからインクルードされる別のヘッダファイルに
stdio.h
存在
#include <stdio.h>
int main(void)
{
・・・・
}
100
置
き
換
え
る
/** Copyright (c) 1990, 1993
*
The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Chris Torek.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
*
notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
*
notice, this list of conditions and the following disclaimer in the
*
documentation and/or other materials provided with the distribution.
・
・
・
・
・
#defineディレクティブ (1)
#define マクロ名 置換後の文字の並び


マクロ定義を行う
“マクロ名” が “置換後の文字の並び” に置換される
#define NUMBER 10
#define MYNAME "森本"
for (i = 0; i < NUMBER; ++i)
 for (i = 0; i < 10; ++i)
printf("私の名前は" MYNAME "です\n");
 printf("私の名前は" "森本" "です\n");
101
#defineディレクティブ (2)


複数回使われる値の変更が容易になる
ソースコードを読みやすくできる

例) 消費税の税率を
#define CONSUMPTION_TAX 0.05
としておけば、税率が変わっても1カ所の修正で済む
意味も分かりやすい (price *= 1 + CONSUMPTION_TAX;)

例) 円周率は、math.hの中で
#define M_PI 3.14159265358979323846
と定義 (処理系依存)
102
#defineディレクティブ (3)
/* 読みやすさを考慮しなければ・・・ */
#include <stdio.h>
#define
#define
#define
#define
#define
MAIN_FUNCTION int main(void)
START {
END }
HELLO_WORLD "Hello, World!"
RETURN_0 return (0);
MAIN_FUNCTION
START
printf(HELLO_WORLD "\n");
RETURN_0
END
103
プリプロセス以降

狭義のコンパイル: コンパイラが行う


アセンブル: アセンブラが行う


アセンブリ言語のコードを生成
オブジェクトファイルを生成
リンク: リンカが行う

104
オブジェクトファイルやライブラリを結びつけ、実行
ファイルを生成
コンパイルの例
[FreeBSD 7.x (amd64), GCC 4.2.1]
> cc -v ex01.c
Using built-in specs.
Target: amd64-undermydesk-freebsd
Configured with: FreeBSD/amd64 system compiler
Thread model: posix
gcc version 4.2.1 20070719
[FreeBSD]
/usr/libexec/cc1 -quiet -v -D_LONGLONG ex01.c -quiet -dumpbase ex01.c -auxbase ex01 -version -o /var/tmp//ccuBdLL8.s
ignoring duplicate directory "/usr/include"
#include "..." search starts here:
プリプロセス+狭義のコンパイル
#include <...> search starts here:
/usr/include
End of search list.
GNU C version 4.2.1 20070719
[FreeBSD] (amd64-undermydesk-freebsd)
compiled by GNU C version 4.2.1 20070719
[FreeBSD].
GGC heuristics: --param ggc-min-expand=100 --param ggc-min-heapsize=131072
Compiler executable checksum: 96788610ce23a7669daff533acf5d31d
/usr/bin/as -V -Qy -o /var/tmp//ccLCv0s5.o /var/tmp//ccuBdLL8.s
アセンブル
GNU assembler version 2.15 [FreeBSD] 2004-05-23 (x86_64-obrien-freebsd) using BFD version 2.15 [FreeBSD] 2004-05-23
/usr/bin/ld --eh-frame-hdr -V -dynamic-linker /libexec/ld-elf.so.1 /usr/lib/crt1.o /usr/lib/crti.o /usr/lib/crtbegin.o L/usr/lib -L/usr/lib /var/tmp//ccLCv0s5.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-asneeded /usr/lib/crtend.o /usr/lib/crtn.o
GNU ld version 2.15 [FreeBSD] 2004-05-23
Supported emulations:
elf_i386_fbsd
elf_x86_64_fbsd
105
リンク
コンパイルの例
[Windows 7 (64ビット), VC++ 2010]

プリプロセス
> cl /P ex01.c

狭義のコンパイル
> cl /FA /c /Tc ex01.i

リンク
> cl ex01.obj
106
情報の表現


コンピュータ内部の情報は0と1から構成される
0または1を表すデータの最小単位が1bit(ビット)
1bit(ビット)
0か1の2値 (21通り)
1B(バイト) = 8bits
28通りの値を表現
1kB(キロバイト) = 1024B
1MB(メガバイト) = 1024kB
1GB(ギガバイト) = 1024MB
1TB(テラバイト) = 1024GB
1PB(ペタバイト) = 1024TB
1EB(エクサバイト) = 1024PB
1024 = 210
107
整数の表現 (1)
コンピュータの内部では、整数は2進数で表現

【2進数】
23
22
21
20
1101
=
1×23
1×22
+
+ 0×21 + 1×20
【10進数】
103 102 101 100
1234
= 1×103 + 2×102
+ 3×101 + 4×100
108
2進数
10進数
16進数
2進数
10進数
16進数
0
0
0
1011
11
B
1
1
1
1100
12
C
10
2
2
1101
13
D
11
3
3
1110
14
E
100
4
4
1111
15
F
101
5
5
10000
16
10
110
6
6
10001
17
11
111
7
7
100000
32
20
1000
8
8
1000000
64
40
1001
9
9
10000000
128
80
1010
10
A
11111111
255
FF
整数の表現 (2)

ex31.c: 10進数を2進数に変換する
321を10進数で表現するには
321/10 + 321%10
32/10 + 32%10
3/10 + 3%10
3
2
1
13を2進数で表現するには
13/2 + 13%2
6/2 + 6%2
3/2 + 3%2
1/2 + 1%2
109
0
1
1
1
整数の表現 (3)
void dtob(int num)
{
int q, r;

自分自身を呼び出す
 再帰呼び出し
/* 中略 */
q = num / 2;
r = num % 2;
if (q)
{
dtob(q);
}
printf("%d", r);
① num/2を2進数で表示した後に
② num%2を(2進数で)表示
return;
}
110
q(num/2)が0ならr(num%2)を表示するだけ
整数の表現 (4)

C言語では
8進数: 先頭に “0” をつける
16進数: 先頭に “0x” または “0X” をつける
2進数: 直接表現できない



i = 2011; /* 10進定数 */
i = 03733; /* 8進定数 */
i = 0x7db; /* 16進定数 */
printf("%u", i); /* 符号なし10進整数 (2011) */
printf("%o", i); /* 符号なし8進整数 (3733) */
printf("%x", i); /* 符号なし16進整数 (7db) */
111
整数の表現 (5)

int型が32ビットの処理系(ビッグエンディアン)で、
int i = 13;
とすると・・・
バイト
ビット
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 1
変数iの値を記憶するメモリ領域

4,294,967,296(232)通りの整数を格納できる
112
整数の表現 (6)


負の整数を表現するためには、最上位ビット(符号
ビット)を “1” にする
1の補数




対応する正の整数のビットを反転する
00001101(13)  11110010(-13)
8ビットなら -127~127 を表現可能
2の補数




113
対応する正の整数のビットを反転し、1を加える
00001101(13)  11110011(-13)
8ビットなら -128~127 を表現可能
現在のコンピュータは、ほとんどが2の補数を採用
整数の表現 (7)
内部表現 符号なし 符号ビッ 1の補数 2の補数
整数
トのみ
00000000
0
0
0
0
00000001
1
1
1
1
00000010
2
2
2
2
00000011
3
3
3
3
00000100
4
4
4
4
⋮
⋮
⋮
⋮
⋮
01111111
127
127
127
127
10000000
128
0
-127
-128
10000001
129
-1
-126
-127
⋮
⋮
⋮
⋮
⋮
11111011
251
-123
-4
-5
11111100
252
-124
-3
-4
11111101
253
-125
-2
-3
11111110
254
-126
-1
-2
11111111
255
-127
0
-1
114
小数の表現


浮動小数点数: 仮数×基数指数 で表現
数
浮動小数点数
321
3.21×102
3210000000000
3.21×1012
0.00000000000321
3.21×10-12
一般的な浮動小数点型の内部表現
指数
符号ビット
115
仮数
基数は2
浮動小数点数の精度

10進小数を2進小数に変換すると、たいてい端数処
理が生じる (丸め誤差)


仮数に割り当てられたビット数では精度が足りない
ことがある


例) 10進小数の0.1を2進小数にすると、
0.0001100110011... となる
端数処理をしたあとで10進小数に戻しても、0.1とはな
らない
例) 仮数が10進数で1.23456789012のとき、仮数を23
ビットで表現する記憶領域には、すべての桁を十分な精
度で格納できない
 ex32.c
116
ビット単位の演算
演算子
a & b
a | b
a ^ b
~a
a << b
a >> b
117
役割
aとbのビット単位の論理積
aとbのビット単位の論理和
aとbのビット単位の排他的論理和
aのビットを反転 (1の補数)
aをbビット左シフト
aをbビット右シフト
シフト演算
0
0
1
1
0
1
0
1
0
0
↑ 2ビット左シフト
0
0
1
1
0
1
0
1
0
0
0
0
1
1
0
1
2ビット右シフト ↓

1
あふれたビットは捨て、空いたビットには



0
左シフト: 0を入れる
右シフト: シフト前の数字(第1オペランド)が正なら0を
入れ、負なら処理系依存
符号なし整数に対するbビットの左シフトは2b倍、
右シフトは2-b倍することに相当
118
ex33.c
10進数
ビット列
a
b
a & b
a | b
a ^ b
~a
a << 3
a >> 2
0
0
0
0
0
1
0
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
1
0
0
0
0
0
0
1
0
0
0
0
0
0
0
1
1
0
1
0
0
1
1
0
0
0
0
1
0
1
1
1
0
0
1
1
1
1
0
0
0
1
5
3
1
7
6
-6
40
1
aの2-2倍 (切り捨て)
119
2の補数
aの23倍
ex34.c
100
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0
1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
100 & 1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
100 >> 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1
1
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
100 >> 2 & 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1
100
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0
1 << 2
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
100 & 1 << 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0
120
配列

同じ型の変数の集合
1つ1つの変数を要素という

配列の宣言

要素の型名 配列の変数名[要素数];
int ia[5]; /* int型の要素が5つ */
double da[3]; /* double型の要素が3つ */

従来のC言語の仕様では、宣言の要素数は定数 (コン
パイル時に値が決まっている必要がある)
121
配列の要素


配列の各要素は、変数名[添え字]
添え字は、0からはじまる整数
int ia[5]; と宣言すると・・・
ia[0], ia[1], ia[2], ia[3], ia[4] の5つの
要素を、int型の変数として利用できる
ia[5](6番目)は利用できない
ia[0]はint型
iaはint型ではない
122
配列の初期化

先頭の要素から順番に、初期値をカンマ区切りで並
べ、全体を { } で囲う
/* ia[0]~ia[4]を、1~5で初期化 */
int ia[5] = { 1, 2, 3, 4, 5 };
/* char型配列の初期化例 */
char ca[3] = { 'A', 'B', 'C' };
/* 初期化する場合は、要素数は不要 */
int ia[] = { 1, 2, 3, 4, 5 }; /* 要素数は5 */
char ca[] = { 'A', 'B', 'C' }; /* 要素数は3 */
123
配列に関する決まり


要素数は、プログラムの途中で変更できない
配列の代入はできない
int a1[5], a2[5] = { 5, 4, 3, 2, 1 }, i;
a1[5] = 1; /* やってはいけない */
a1 = { 1, 2, 3, 4, 5 }; /* エラー */
a1 = a2; /* エラー */
/* 配列のコピー方法の例 */
for (i = 0; i < 5; ++i)
{
a1[i] = a2[i];
}
124
配列と関数

配列を関数の実引数・仮引数にするのは、ポインタ
を学習してから
void func1(int, int);
void func2(int []);
int ia[2] = { 1, 2 };
/* ○ 実引数は配列の要素 */
func1(ia[0], ia[1]);
/* △ ポインタを学習してから */
func2(ia);
125
配列の利用例

基本的な使い方  ex35.c

for文の利用  ex36.c

配列のコピー  ex37.c
126
演習




int型の配列の要素を、
昇順に並び替えるプロ
グラムを作る
途中まで作ってある
ex38.cを完成させる
次ページに方法の例
よりよい方法を見つけ
た場合は、それを使う
127
動作例
---Input an
Input an
Input an
Input an
Input an
-41
-7
9
10
26
integer
integer
integer
integer
integer
(1)
(2)
(3)
(4)
(5)
>
>
>
>
>
9
-41
10
26
-7
キ
ー
ボ
ー
ド
か
ら
入
力
int ia[10]; のソート方法の例
方法その1
𝑖𝑎 0 > 𝑖𝑎 1 なら、𝑖𝑎 0 と𝑖𝑎 1 を入れ替える
𝑖𝑎[1] > 𝑖𝑎[2]なら、𝑖𝑎[1]と𝑖𝑎[2]を入れ替える
⋮
𝑖𝑎[8] > 𝑖𝑎[9]なら、𝑖𝑎[8]と𝑖𝑎[9]を入れ替える
これを繰り返すと、そのうち入れ替えがなくなる
そのとき、配列は昇順に並んでいる
方法その2
𝑖𝑎[0]~𝑖𝑎[9]のうち一番大きい要素と𝑖𝑎[9]を入れ替える
(𝑖𝑎 9 が一番大きければ入れ替えない, 以下同じ)
𝑖𝑎[0]~𝑖𝑎[8]のうち一番大きい要素と𝑖𝑎[8]を入れ替える
⋮
𝑖𝑎[0]~𝑖𝑎[1]のうち一番大きい要素と𝑖𝑎[1]を入れ替える
128
配列の要素数を求める
配列の大きさ
要素数 =
要素の大きさ

 ex39.c
129
コンピュータの仕組み

コンピュータは、ハードウェアとソフトウェアに
よって動作する

ハードウェア: 物理的な装置

ソフトウェア: ハードウェアを動作させるための情報
130
コンピュータの5大装置
1.
2.
3.
4.
5.
131
制御装置:
演算装置:
記憶装置:
入力装置:
出力装置:
各装置の動作を制御する
計算を行う
情報を記憶する
外部からコンピュータへ情報を入力する
コンピュータから外部へ情報を出力する
信号・データの流れ
中央処理装置 (CPU)
制御信号の流れ
演算装置
コンピュータ本体
データの流れ
制御装置
入力装置
主記憶装置
補助記憶装置
132
出力装置
周辺装置
出力装置
(ディスプレイ)
入力装置
(マウス)
入力装置
(キーボード)
パソコン本体
(筐体)
133
補助記憶装置
(ハードディスク)
主記憶装置
(メインメモリ)
中央処理装置
(CPU)
134
CPU
(裏側)
CPUソケット
CPUクーラー
135
ハードディスク
メモリソケット
136
メインメモリ
ソフトウェア

ソフトウェア: ハードウェアを動作させるためのプ
ログラム(命令の集まり)

基本ソフトウェア




オペレーティングシステム (OS)
ハードウェアの制御, 資源管理
Windows, Linux, Mac OS, ...
応用ソフトウェア



137
応用ソフトウェア
基本ソフトウェア
ハードウェア
具体的な仕事をするプログラム
Webブラウザ, ワープロソフト, 表計算ソフト, ...
基本ソフトウェアの機能を使って動作
プログラムの実行とメインメモリ

プログラムの実行




補助記憶装置に保存されたプログラムを、メインメモリ
に読み込む
メインメモリ上に、プログラムの命令の集まり、静的な
データ、内容が動的に変化する作業領域などが展開され
る
CPUは、命令を読み込みながら実行する
メインメモリは、1バイトごとに番地(メモリアドレ
ス)が振られている
138
変数とメモリアドレス
アドレス


⋮
C言語で用いる変数は、メ
インメモリ上に領域が確保
される
メモリ上の配置イメージ 
char c;
int i;
⋮
500
501
変数c
502
503
504
先
頭
ア
ド
レ
ス
505
506
変数i
507
508
509
510
511
512
⋮
139
⋮
アドレス演算子
演算子
&a

役割
aの先頭アドレスを取得する
アドレスを表示するためのprintf()関数のフォー
マット文字は“p” (出力形式は処理系依存)
 ex40.c
プログラムから見えるのは
仮想的なアドレス
ハードウェア部品(通常は
CPU内)で実アドレスとの
変換を行う
140
実行結果1 [Windows 7 (64ビット), VC++ 2010]
変数 c のメモリアドレス: 003CFB33
変数 i のメモリアドレス: 003CFB34
---実行結果2 [FreeBSD 7.x (amd64), GCC 4.2.1]
変数 c のメモリアドレス: 0x7fffffffe9ff
変数 i のメモリアドレス: 0x7fffffffe9f8
ポインタ (1)


アドレスは、ポインタ変数に保存する (ポインタは、
アドレスを指す)
ポインタの宣言
ポインタが指す先の型名 *ポインタ変数名;
int i; /* int型の変数 */
int *ip; /* int型へのポインタ */
ip = &i; /* アドレスの代入 */
*ip = &i; ではない
141
ポインタ (2)
アドレス
⋮
int i = 3;
int *ip = &i;
とすると・・・
⋮
500
501
502
3
int型変数i
500
int型への
ポインタip
503
504
505
506

ポインタは、指し示す先
の型に関する情報を持つ
507
508
509
510
511
512
⋮
142
⋮
間接演算子
演算子
*a
役割
a(ポインタ)が指す場所に格納されているもの

a がchar型へのポインタなら *a はchar型、int型
へのポインタなら *a はint型

ポインタの基本的な使い方  ex41.c
143
関数とポインタ

C言語の関数は値渡し

引数としてポインタを渡すことにより、呼び出し側
の変数を間接的に書き換えることができる

 ex42.c
変数をscanf()関数に書き換えて
もらうため、引数はポインタ
scanf("%d", &i);
144
変数の値を渡しても、scanf()関
数からは書き換えられない
演習


2つのint型変数の値を入れ替える関数を作る
途中まで作ってあるex43.cを完成させる
動作例
---i = 3
j = 5
i = 3
j = 5
i = 5
j = 3
145
かキ
らー
入ボ
力ー
ド
配列とポインタ


配列の要素は、連続したメモリ
領域に格納される
配列変数名は、その配列の先頭
要素へのポインタ
char ca[] = { 1, 2, 3, 4, 5 };

右の例では・・・




&ca[0] は 502
&ca[3] は 505
ca は 502
sizeof ca は例外 (ポインタの大き
さではなく、配列の大きさ)
アドレス
⋮
500
ca[0]
501
502
1
503
2
504
3
505
4
506
5
ca[1]
ca[2]
ca[3]
ca[4]
507
508
509
510
511
512
⋮
146
⋮
⋮
ex44.c

配列の性質を確認するプログラム
147
動作例
---&ca[0]
&ca[1]
&ca[2]
ca
=
=
=
=
0033FC80
0033FC81
0033FC82
0033FC80
&ia[0]
&ia[1]
&ia[2]
ia
=
=
=
=
0033FC84
0033FC88
0033FC8C
0033FC84
sizeof(char) ずつ増える
&ca[0] と同じ
sizeof(int) ずつ増える
&ia[0] と同じ
ポインタへの加減算



配列要素を指すポインタに整数aを足す[引く]と、a
個後ろ[前]の要素を指すポインタとなる
int型へのポインタならsizeof(int)単位で、double
型へのポインタならsizeof(double)単位で、加減算
される (1バイト単位ではない)
 ex45.c
for (i = 0; i < len; ++i)
*(ip + i) *= 2;
for (i = 0; i < len; ++i)
printf("%d\n", *ip++);
148
配列と関数

C言語の関数は値渡し

配列を値渡しすることはできない

ポインタを値渡しすることにより、間接的に配列を
渡せる

配列がコピーされるわけではないので、渡された関
数でポインタが指す先の内容を書き換えると、呼び
出し側の配列も書き換えられる
149
ex46.c
decuple_array(ia, len);
配列の先頭要素へのポインタを渡す
配列の要素数を渡す
(呼び出された側で
は分からない)
void decuple_array(int *ip, size_t len)
{
for ( ; len > 0; --len)
{
*ip++ *= 10;
}
ポインタの指す内容を書き換える
}
= 呼び出し側の配列の内容を変更
150
[配列要素へのポインタ]の仮引数 (1)
void decuple_array(int *, size_t); /* プロトタイプ宣言 */
void decuple_array(int *ip, size_t len) { } /* 関数定義 */
↑どちらも同じ↓
void decuple_array(int [], size_t); /* プロトタイプ宣言 */
void decuple_array(int ip[], size_t len) { } /* 関数定義 */
---どちらで宣言しても、同じように使える
ポインタとして ・・・ *(ip + 1)
配列風に ・・・・・・ ip[1]
151
[配列要素へのポインタ]の仮引数 (2)
配列風に記述すると、配列を値渡ししているように見えるが、
実際は違う(ポインタを値渡ししている)ので注意
decuple_array(ia, len);
配列の内容がコピーされているのではない
void decuple_array(int ip[], size_t len)
{
int i;
for (i = 0; i < len; ++i)
{
ip[i] *= 10;
}
}
152
文字と文字列



文字は、char型変数に格納
C言語には、文字列型の変数はない
C言語での文字列は、0(エスケープシーケンスを用
いれば '\0')で終わる文字の並び


配列として: char型の配列
ポインタとして: 文字列定数の先頭文字へのポインタ
'A'
… 文字定数
"ABC" … 文字列定数
"A"
… 文字列定数
153
ex09.c
[Windows 7 (64ビット), VC++ 2010]
sizeof(char)
= 1
sizeof(short int)
sizeof(int)
sizeof(long int)
= 2
= 4
= 4
sizeof(float)
= 4
sizeof(double)
= 8
sizeof(long double) = 8
sizeof(size_t)
154
= 4
sizeof
sizeof
sizeof
sizeof
sizeof
'A'
3
3.0
"A"
"ABC"
sizeof (3 + 5)
sizeof (3.0 + 5)
=
=
=
=
=
4
4
8
2
4
= 4
= 8
文字列

 ex47.c

先頭の文字から、'\0' がでるまでの間が文字列
155
2種類の文字列
アドレス
⋮
アドレス
⋮
⋮
500
700
501
'B'
ca1[0]
701
'H'
*cp
502
'C'
ca1[1]
702
'I'
*(cp + 1)
503
'D'
ca1[2]
703
'J'
*(cp + 2)
504
'\0'
ca1[3]
704
'\0'
*(cp + 3)
505
506
⋮
sizeof(char *)
は処理系依存
⋮
705
⋮
配列として:
char ca1[] = "BCD";
ポインタとして:
char *cp = "HIJ";
⋮
1000
1001
156
⋮
1002
cp
701
1003
1004
⋮
⋮
文字列とポインタ

文字列定数を評価すると、先頭文字へのポインタ
(char *型)が得られる
MSDNの関数リファレンス
char *strcpy(
char *strDestination,
const char *strSource
);
strcpy(str, "abc");
157
文字列の代入



char型の配列による文字列は、初期化時を除いて、
=演算子での代入はできない
strcpy()やstrncpy()関数で代入(コピー)を行う
(string.hのインクルードが必要)
ポインタによる文字列を書き換えてはいけない
char str1[] = "abc";
char *str2 = "abc";
str1 = "def";
/* × */
strcpy(str1, "def"); /* ○ */
str2 = "ghi";
/* ○ */
strcpy(str2, "ghi"); /* × */
158
string.h

マニュアルを参照
159
課題-3


文字列中の大文字を小文字に、小文字を大文字に変
換する関数を作る
途中まで作ってあるkadai-3.cを完成させる
動作例
---文字列 > My name is Yosuke Morimoto.
My name is Yosuke Morimoto.
mY NAME IS yOSUKE mORIMOTO.
キーボードから入力
160
データの関連
学籍番号
名前
学籍番号
1001
1001
Sato
名前
Sato
1002
Takahashi
身長
1003
Tanaka
体重
1004
Ito
162
学籍番号
54
名前
1005
Yamamoto
学籍番号
名前
身長
体重
身長
身長
1003
体重
Tanaka
174
学籍番号
69
名前
162
54
177
68
174
69
学籍番号
168
60
名前
身長
1005
体重
Yamamoto
171
58
身長
171
体重
58
161
体重
1002
Takahashi
177
68
1004
Ito
168
60
構造体


関連のあるデータをまとめたデータ構造
 ex48.c
/* 構造体の宣言 */
struct タグ名 {
メンバ宣言1
メンバ宣言2
⋮
};
struct student {
char id[5];
char name[10];
int height;
int weight;
};
/* 構造体変数の宣言 */
struct タグ名 変数名;
struct student sato;
162
構造体のメンバ
構造体に関する演算子
演算子
a . b
a -> b
役割
構造体aのメンバb
a(構造体へのポインタ)が指す構造体のメンバb
struct xy {
int x;
int y;
};
struct xy
struct xy
printf("x
printf("y
163
xy = { 1, 2 };
*p = &xy;
= %d\n", p -> x);
= %d\n", (*p).y);
構造体の配列

 ex49.c
164