C言語とJavaでの配列の使い方の違い

C言語とJavaでは配列の使い方(宣言の仕方)が違います。C言語とJavaのサンプルプログラムを載せておきます。

Javaの配列のサンプル

C言語の配列のサンプル

実行結果です(javaの例ですがCのサンプルコードでも同じ結果になります)。

$ java array
0  0  0  1
1  2  1  2
2  4  2  3
3  6  3  4
4  8  4  5
5 10  5  6
6 12  6  7
7 14  7  8
8 16  8  9
9 18  9 10

留意点は以下でしょうか。

= = 1点目 = =
Javaでは配列の宣言

int[ ]  a;
int  b[ ];

のどちらでも使える。型カッコの [ ] を型に付けても変数につけてもどちらでも良い。

C言語は

int  b[ ];

のみ(変数に付けるのみ)。

ただしこれは配列の宣言であるため、初期化するときか関数の引数として使う場合に限る。関数の引数として使う場合というのは、func関数があってその引数に配列(ポインタ)を持つ場合に使えるということ。

例:
void func( int b[ ] )
{
 ・・
}

= = 2点目 = =
Javaでは

int  a[10];

のようなC言語で言う配列の定義はできない。Javaは配列の宣言とメモリ確保の2段階の操作が必要ということ。

なお、Javaで以下のように1行で書いてしまうことは可能。

int[ ] a = new int[10];

= = 3点目 = =
配列の初期化はjavaでもnew演算子を使用せずにメモリ確保できる。これはC言語と同じ。

見かけは違うが、配列宣言した変数とポインタ変数の扱い方は同じです。

C言語の配列を宣言した変数とポインタ変数の扱い方が同じになることをサンプルプログラムを作って確認してみました。具体的には以下の変数(aとp)は、ポインタでも配列(添字)でもどちらでも操作できるということです。ただし注意書きあり(最後に後述)。

char a[ ];
char *p;

サンプルプログラムは以下です。左側の数字は行数です。

コピペ用です。


#include <stdio.h>

void funcB( char a1[] );
void funcC( char a2[] );

void main( void )
{
	char	s[] = "Apple";
	char	i;

	/* ポインタ変数 */
	char	*p1;
	char	*p2;

	/* ポインタp1をポインタで操作する */
	p1 = s;
	for( ; *p1; p1++ )
		printf( "%c", *p1 );
	printf( "\n" );

	/* ポインタp2を配列で操作する */
	p2 = s;
	for( i = 0; p2[i]; i++ )
		printf( "%c", p2[i] );
	printf( "\n" );

	/* 配列a1をポインタで操作する */
	funcB( s );

	/* 配列a2を配列で操作する */
	funcC( s );
}

/* 引数が配列である関数funcB */
void funcB( char a1[] )
{
	for( ; *a1; a1++ )
		printf( "%c", *a1 );
	printf( "\n" );
}

/* 引数が配列である関数funcC */
void funcC( char a2[] )
{
	char	i;
	for( i = 0; a2[i]; i++ )
		printf( "%c", a2[i] );
	printf( "\n" );
}

このサンプルプログラムの実行結果は以下となります。

$ ./a.out
Apple
Apple
Apple
Apple

ソースの説明をします。

15〜19行目は、ポインタ変数p1を通常のポインタの扱い方で操作しています。「Apple」という文字が印字されます。

21〜25行目は、ポインタ変数p2を配列(添字)で操作しています。結果はポインタで操作したときと同じになります。

27、28行目は、文字列sの先頭ポインタをfuncB関数に渡しています。funcB関数ではポインタを配列の形で受け取ります(35行目)。funcB関数の中では、配列宣言a1をポインタ変数の扱い方で操作して文字を印字しています。

30、31行目も、文字列sの先頭ポインタをfuncC関数に渡しています。funcC関数ではポインタを配列の形で受け取ります(43行目)。funcC関数の中では、配列宣言a2を通常の配列(添字)として操作しています。

ポインタ変数なのに配列(添字)で操作できる(21〜25行目)、配列の宣言なのにポインタで操作できる(27、28行目)というところがポイントかと思います。

注意点を記載しておきます。

配列の宣言(char a1[ ]; や char a2[ ]; など)は呼ばれる関数の引数には使用できますが、main関数内に書くことはできません。書くとコンパイルエラーになります。main関数内に書けるのは配列の定義となります。配列の定義とは、初期化した配列や領域を確保した配列のことです。

配列の定義
char s[ ] = “Apple”; //初期化した配列
char a[10]; //領域を確保した配列

配列の宣言
char b[ ]; //main関数内に書くとコンパイルエラーになります

また、配列の定義である変数はポインタのような操作はできません(あくまでも配列なので)。

つまり、

char a[10];

とした場合の、a++ や a=p(ポインタの代入)などはできません。