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

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(ポインタの代入)などはできません。

C言語のargc、argv と Javaのargsの違い

C言語ではmain関数の引数にargcとargvを使います。

C言語
int main( int argc, char *argv[] ) ・・

Javaではmainメソッドの引数にはargsを使います。

Java
public static void main( String[] args ) ・・

プログラムに与えたパラメータをこれらのargvやargsを使って取得できるのですが、argvやargsに入る配列の中身はC言語とJavaでは異なります。C言語の場合は1つ目の引数を取得するにはargv[1]となりますが、Javaの場合はargs[0]となります。

また引数の個数を取得する場合もC言語の場合はargcを使いますが、Javaの場合はargs.lengthを使います。

sample1というプログラムがあり、パラメータに aa と bb を与えたとします。

実行例(C言語)
$ sample1 aa bb

実行例(java)
$ java sample1 aa bb

C言語ではaaを取得するにはargv[1]、bbを取得するにはargv[2]となります。なお、argv[0]ではプログラム名(sample1)が取得できます。Javaではaaを取得するにはargs[0]、bbを取得するにはargs[1]となります。

まとめるとこんな感じです。

実際にサンプルプログラムを作ってmain関数(mainメソッド)の引数をたどってみました。

C言語のサンプルプログラム(sample1.c)です。


#include <stdio.h>

int main( int argc, char *argv[] )
{
	int i;

	for( i = 0; i < argc; i++ )
		printf( "%s\n", argv[i] );
	
	return 0;
}

実行結果は以下となります。

$ gcc sample1.c -o sample1
$ sample1 aa bb
sample1
aa
bb

Javaのサンプルプログラム(sample1.java)です。


public class sample1
{
	public static void main( String[] args )
	{
		int i;
		
		for( i = 0; i < args.length; i++ )
			System.out.println( args[i] );	
	}
}

実行結果は以下となります。

$ javac sample1.java
$ java sample1 aa bb
aa
bb

C言語のプログラマはJavaをやるときに覚えおきましょう。