第6章 配列

第6章 配 列
配列の宣言
配列要素の初期値
配列の上限
メモリ領域
多次元配列
配列の応用
配列の宣言



一般形
型宣言子 配列名[要素数];
整数型
int a[10];
a[0]~a[9]
unsigned int u[20];
u[0]~u[19]
浮動小数点数(実数)型
float f[101];
f[0]~f[100]
double x[N+1];
x[0]~x[N]
符号付き整数
符号なし整数
単精度浮動小数点数
倍精度浮動小数点数
要素は必ず 0 から始まるため、最後の要素番号は(要素数-1)である
ことに注意
よくやるミス (ex6_2_1a.c)
#include <stdio.h>
プログラム例 6.2.1改
#define N 10
コンパイルの前に N を 10 にすり替えてくれる
int main(void)
{
int i, x[N], n=N, total=0;
double average;
for (i=1; i<=n; i++) printf("x[%d]=% d\n", i, x[i]=i);
for (i=1; i<=n; i++) total += x[i];
average = (double)total / n;
printf("総 和=% d\n", total);
printf("平均点=% .2f\n", average);
return 0;
}
配列要素の初期値
残りは 0 で初期化
int a[10] = {1, 2, 3, 4};
すべて 0 で初期化
int b[10] = {0};
static int c[10];
静的変数は 0 で初期化される
double d[10] = {0};
static double e[10];
すべて 0.0 で初期化
静的変数は 0.0 で初期化される
配列要素の初期値 (ex6_3_1a.c)
#include <stdio.h>
プログラム例 6.3.1改
#define N 10
初期値なしで宣言した場合(自動変数)
int main(void)
{
int i, x[N], n=N, total=0;
double average;
for (i = 0; i < n; i++) printf("x[%d]=% d\n", i, x[i]);
for (i = 0; i < n; i++) total += x[i];
average = (double)total / n;
printf("総 和=% d\n", total);
printf("平均点=% .2f\n", average);
return 0;
}
配列要素の初期値 (ex6_3_1b.c)
#include <stdio.h>
プログラム例 6.3.1改2
#define N 10
初期値 0 で宣言した場合(自動変数)
int main(void)
{
int i, x[N]={0}, n=N, total=0;
double average;
for (i = 0; i < n; i++) printf("x[%d]=% d\n", i, x[i]);
for (i = 0; i < n; i++) total += x[i];
average = (double)total / n;
printf("総 和=% d\n", total);
printf("平均点=% .2f\n", average);
return 0;
}
配列要素の初期値 (ex6_3_1c.c)
#include <stdio.h>
プログラム例 6.3.1改3
#define N 10
int main(void)
static をつけて宣言した場合(静的変数)
{
int i, n=N, total=0;
static int x[N];
static によりすべて 0 に初期化される
double average;
for (i = 0; i < n; i++) printf("x[%d]=% d\n", i, x[i]);
for (i = 0; i < n; i++) total += x[i];
average = (double)total / n;
printf("総 和=% d\n", total);
printf("平均点=% .2f\n", average);
return 0;
}
配列の上限(自動変数の場合)
#include <stdio.h>
#define N 200000 // <= 258522
プログラム例 6.6.3改
(ex6_6_3a.c)
int main(void)
{
int i, n=N;
int x[N]; // stack size limit = 258522*4?
long long sum=0;
倍長精度整数型(64bit)
for (i=0; i < n; i++) x[i] = i+1;
for (i=0; i < n; i++) sum += x[i];
printf("総 和=%lld\n", sum);
return 0;
}
long long 整数用書式修飾子
配列の上限(静的変数の場合)
#include <stdio.h>
#define N 200000000 // <= 499,107,120
プログラム例 6.6.3改2
(ex6_6_3b.c)
int main(void)
{
int i, n=N;
static int x[N]; // static limit = 499107120*4?
long long sum=0;
倍長精度整数型(64bit)
for (i=0; i < n; i++) x[i] = i+1;
for (i=0; i < n; i++) sum += x[i];
printf("総 和=%lld\n", sum);
return 0;
}
long long 整数用書式修飾子
配列の上限(大域変数の場合)
プログラム例 6.6.3改3
#include <stdio.h>
(ex6_6_3c.c)
#define N 200000000 // <= 499107117
int x[N]; // static limit = 499107117*4?
int main(void)
{
int i, n=N;
long long sum=0;
倍長精度整数型(64bit)
for (i=0; i < n; i++) x[i] = i+1;
for (i=0; i < n; i++) sum += x[i];
printf("総 和=%lld\n", sum);
return 0;
}
long long 整数用書式修飾子
メモリ領域

プログラム領域
プログラムコード
スタックより大、ヒープより小


静的領域
ヒープ領域
静的変数、大域変数
動的確保(malloc)
仮想メモリも使用可

スタック領域
デ
ー
タ
領
域
自動変数
比較的小さい
Windows XP(32 bit)の場合、1つのプログラムで
使えるメモリは 2 GB まで?
2次元配列の宣言

一般形
行
列
型宣言子 配列名[要素数][要素数];

整数型
int a[5][10];
unsigned int u[10][20]

a[0][0]~a[0][9]
a[1][0]~a[1][9]
…
a[4][0]~a[4][9]
実数型
float f[100][10];
double x[M+1][N+1];
f[0][0]~f[0][9]
f[1][0]~f[1][9]
…
f[99][0]~f[99][9]
5行10列
10行20列
u[0][0]~u[0][19]
u[1][0]~u[1][19]
…
u[9][0]~u[9][19]
x[0][0]~x[0][N]
x[1][0]~x[1][N]
…
x[M][0]~x[M][N]
要素は必ず 0 から始まるため、おのおのの最後の要素番号は
(要素数-1)であることに注意
2次元配列要素の初期値
int a[4][4] = {{1, 2, 3, 4},{ 5, 6, 7, 8},
{9,10,11,12},{13,14,15,16}};
int b[4][4] = {1, 2, 3, 4, 5, 6, 7, 8,
9,10,11,12,13,14,15,16};
int c[][4] = {{1, 2, 3, 4}, 5, 6, 7, 8,
省略可
9,10,11,12,{13,14,15,16}};
int d[][] = {{1, 2, 3, 4},{ 5, 6, 7, 8},
{9,10,11,12},{13,14,15,16}};
省略できない
{ }カッコだけでは折り返す場所の情報が伝わらない
2次元配列要素の初期値
行の大きさは省略できるが、列の大きさは省略できない
a[4][4] → a[][4]
記憶領域→1次元的
a[m][n] の行列表現
1行目
2行目
a12
・・・
a21 a22
・・・
a11
・
・
・
m行目
・
・
・
am1 am2
a1n
a2n
・
・
・
・・・
a11
amn
1行目
a12
・
・
・
a1n
a21
・
・
・
折り返し場所の情
報は省略できない
2次元配列要素の初期値

整数型
残りは 0 で初期化
int a[4][4] = {1, 2, 3, 4};
int b[4][4] = {0};
すべて 0 で初期化
static int c[4][4];
静的変数は 0 で初期化される

浮動小数点数型
double d[4][4] = {0};
static double e[4][4];
すべて 0.0 で初期化
静的変数は 0.0 で初期化される
2次元配列を用いた例(ex6_7_2a.c)
#include <stdio.h>
プログラム例 6.7.2改
#define N 4
int main(void)
{
int i, j, k=0, a[N][N];
1~16の通し
for (i = 0; i < N; i++)
番号を入力
for (j = 0; j < N; j++) a[i][j] = ++k;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("a[%d][%d]=%d\t", i, j, a[i][j]);
2次元的に
printf("\n");
表示
}
return 0;
}
ex6.7.2a のPAD
k←0
ex6.7.2a
i = 0...N-1
j = 0...N-1
k ← k+1
a[i] ← k
i = 0...N-1
j = 0...N-1
"a[%d][%d]=%d\t", i, j, a[i][j]
"\n"
2次元配列の1次元化(ex6_7_2b.c)
#include <stdio.h>
プログラム例 6.7.2改2
#define N 4
#define IDX(i,j) ((i)*N+(j))
2次元→1次元変換用マクロ
int main(void)
{
int i, j, a[N*N];
1~16の通し
番号を入力
for (i = 0; i < N*N; i++) a[i] = i + 1;
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++)
printf("a[%d][%d]=%d\t", i, j, a[IDX(i,j)]); 2次元的に
printf("\n");
表示
}
return 0;
}
3次元配列の宣言

一般形
段
行
列
型宣言子 配列名[要素数][要素数][要素数];

整数型
int a[6][11][21];

6段11行21列
a[0][0][0]~a[0][0][20]
a[0][1][0]~a[0][1][20]
a[5][0][0]~a[5][0][20]
…
…
a[5][1][0]~a[5][1][20]
a[0][10][0]~a[0][10][20]
…
…
a[5][10][0]~a[5][10][20]
実数型
double x[L+1][M+1][N+1];
x[0][0][0]~x[0][0][N]
x[0][1][0]~x[0][1][N]
x[L][0][0]~x[L][0][N]
…
…
x[L][1][0]~x[L][1][N]
x[0][M][0]~x[0][M][N]
…
…
x[L][M][0]~x[L][M][N]
要素は必ず 0 から始まるため、おのおのの最後の要素番号は
(要素数-1)であることに注意
エラトステネスの篩(ふるい)



整数集合 A = {2, 3, ..., n} を考える。
整数 i = 2, 3, ..., n/2 について i∈A ならば i より大きい i の倍
数を A から除いていく。
最後まで A に残ったものが n 以下の素数となる。
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97 101 103 107 109 113
………………………………………………………………………………………………
769 773 787 797 809 811 821 823 827 829 839 853 857 859 863
877 881 883 887 907 911 919 929 937 941 947 953 967 971 977
983 991 997
エラトステネスの篩(ふるい)
#include <stdio.h>
prime.c
#define N 1001
int main(void)
{
int i, j, k, a[N];
for (i = 2; i < N; i++) a[i] = 1; // 篩(a)の初期化
for (i = 2; i < N/2; i++)
if (a[i]) {
j = 2 * i;
while (j < N) {a[j] = 0; j += i;} // iの倍数を除く
}
k = 0;
for (i = 2; i < N; i++)
if (a[i]) {
printf("%5d", i);
if (++k % 15 == 0) printf("\n"); // 15個で改行
}
if (k % 15 != 0) printf("\n");
return 0;
}
エラトステネスの篩(ふるい)
のPAD

素数
i=2,...,N
a[i] ← True
←篩(a)の初期化
j ← 2i
i=2,...,N/2
a[i]
j≦N
prime
k←0
i の出力
i=2,...,N
i の倍数を除く
a[j] ← False
j ← j+i
a[i]
k ← k+1
k mod 15
≠0
改行
k mod 15
=0
改行
15個で改行
本日のパズル
次のプログラムは何を出力するか?
#define PRINTX printf("%d\n",x)
main()
{
int x=2, y, z;
x
x
x
x
}
*= 3 +
*= y =
= y ==
== ( y
2; PRINTX;
z = 4; PRINTX;
z; PRINTX;
= z ); PRINTX;
1
2
3
4