[C言語] int型配列の基本と使い方

C言語におけるint型配列は、整数を格納するための連続したメモリ領域を提供します。

配列は固定サイズで宣言され、要素は0から始まるインデックスでアクセスされます。

宣言はint array[サイズ];の形式で行い、初期化はint array[] = {1, 2, 3};のように行います。

配列の要素にアクセスするにはarray[インデックス]を使用します。

配列のサイズはコンパイル時に決定され、動的に変更することはできません。

配列は関数に渡す際にポインタとして扱われます。

この記事でわかること
  • int型配列の宣言と初期化方法
  • 配列のメモリ配置とサイズの制限
  • 配列の要素へのアクセスと変更方法
  • 配列とポインタの関係および操作方法
  • 多次元配列や文字列操作、データ構造の実装例

目次から探す

int型配列の基本

配列の宣言と初期化

C言語でint型の配列を宣言する際には、以下のように記述します。

#include <stdio.h>
int main() {
    // int型の配列を宣言し、初期化
    int numbers[5] = {1, 2, 3, 4, 5};
    // 配列の要素を出力
    for (int i = 0; i < 5; i++) {
        printf("%d ", numbers[i]);
    }
    return 0;
}
1 2 3 4 5

このコードでは、5つの要素を持つint型の配列numbersを宣言し、初期化しています。

配列の要素は中括弧{}を使って指定します。

配列のメモリ配置

配列は連続したメモリ領域に格納されます。

各要素はメモリ上で隣接して配置され、配列の先頭要素のアドレスを基準にしてアクセスされます。

以下のコードは、配列の各要素のアドレスを表示します。

#include <stdio.h>
int main() {
    int numbers[3] = {10, 20, 30};
    // 各要素のアドレスを出力
    for (int i = 0; i < 3; i++) {
        printf("Address of numbers[%d]: %p\n", i, (void*)&numbers[i]);
    }
    return 0;
}
Address of numbers[0]: 0x7ffee3bff6a0
Address of numbers[1]: 0x7ffee3bff6a4
Address of numbers[2]: 0x7ffee3bff6a8

この例では、配列numbersの各要素のアドレスが4バイトずつ増加していることがわかります。

これはint型が通常4バイトであるためです。

配列のサイズと制限

配列のサイズは宣言時に指定し、変更することはできません。

サイズを超えてアクセスすると、未定義の動作を引き起こす可能性があります。

以下のコードは、配列のサイズを超えたアクセスの例です。

#include <stdio.h>
int main() {
    int numbers[3] = {1, 2, 3};
    // サイズを超えたアクセス(未定義の動作)
    printf("%d\n", numbers[3]);
    return 0;
}

このコードはコンパイルは可能ですが、実行時に予期しない結果をもたらす可能性があります。

配列のサイズを超えたアクセスは避けるべきです。

配列の要素へのアクセス

配列の要素は、インデックスを使用してアクセスします。

インデックスは0から始まります。

以下のコードは、配列の要素を変更する例です。

#include <stdio.h>
int main() {
    int numbers[3] = {5, 10, 15};
    // 配列の要素を変更
    numbers[1] = 20;
    // 変更後の配列の要素を出力
    for (int i = 0; i < 3; i++) {
        printf("%d ", numbers[i]);
    }
    return 0;
}
5 20 15

この例では、numbers[1]の値を20に変更しています。

配列の要素はインデックスを指定することで簡単にアクセスおよび変更が可能です。

int型配列の使い方

配列の要素の変更

配列の要素は、インデックスを指定することで簡単に変更できます。

以下の例では、配列の特定の要素を変更しています。

#include <stdio.h>
int main() {
    int numbers[4] = {10, 20, 30, 40};
    // 配列の2番目の要素を変更
    numbers[1] = 25;
    // 変更後の配列の要素を出力
    for (int i = 0; i < 4; i++) {
        printf("%d ", numbers[i]);
    }
    return 0;
}
10 25 30 40

このコードでは、numbers[1]の値を25に変更しています。

配列の要素はインデックスを指定することで直接変更可能です。

配列のループ処理

配列の要素を処理する際には、ループを使用することが一般的です。

以下の例では、forループを使って配列の全要素を出力しています。

#include <stdio.h>
int main() {
    int numbers[5] = {1, 2, 3, 4, 5};
    // 配列の要素をループで出力
    for (int i = 0; i < 5; i++) {
        printf("%d ", numbers[i]);
    }
    return 0;
}
1 2 3 4 5

この例では、forループを使用して配列numbersの全要素を順番に出力しています。

ループを使うことで、配列の全要素に対して効率的に操作を行うことができます。

配列のソート

配列の要素を並べ替えるには、ソートアルゴリズムを使用します。

以下の例では、バブルソートを使って配列を昇順にソートしています。

#include <stdio.h>
void bubbleSort(int arr[], int n) {
    for (int i = 0; i < n-1; i++) {
        for (int j = 0; j < n-i-1; j++) {
            if (arr[j] > arr[j+1]) {
                // 要素を交換
                int temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
}
int main() {
    int numbers[5] = {64, 34, 25, 12, 22};
    // 配列をソート
    bubbleSort(numbers, 5);
    // ソート後の配列を出力
    for (int i = 0; i < 5; i++) {
        printf("%d ", numbers[i]);
    }
    return 0;
}
12 22 25 34 64

このコードでは、バブルソートを用いて配列numbersを昇順に並べ替えています。

バブルソートはシンプルなソートアルゴリズムで、隣接する要素を比較して必要に応じて交換します。

配列のコピー

配列をコピーするには、要素を一つずつコピーする必要があります。

以下の例では、配列の要素を別の配列にコピーしています。

#include <stdio.h>
int main() {
    int original[3] = {10, 20, 30};
    int copy[3];
    // 配列のコピー
    for (int i = 0; i < 3; i++) {
        copy[i] = original[i];
    }
    // コピーした配列を出力
    for (int i = 0; i < 3; i++) {
        printf("%d ", copy[i]);
    }
    return 0;
}
10 20 30

この例では、original配列の要素をcopy配列に一つずつコピーしています。

配列のコピーは、ループを使って各要素を個別にコピーすることで実現できます。

配列とポインタの関係

配列名とポインタ

C言語では、配列名は配列の先頭要素のアドレスを指すポインタとして扱われます。

以下の例では、配列名を使ってポインタのように操作しています。

#include <stdio.h>
int main() {
    int numbers[3] = {10, 20, 30};
    // 配列名は先頭要素のアドレスを指す
    printf("Address of numbers: %p\n", (void*)numbers);
    printf("Address of numbers[0]: %p\n", (void*)&numbers[0]);
    // ポインタを使って配列の要素にアクセス
    printf("First element: %d\n", *numbers);
    return 0;
}
Address of numbers: 0x7ffee3bff6a0
Address of numbers[0]: 0x7ffee3bff6a0
First element: 10

この例では、numbersという配列名が配列の先頭要素のアドレスを指していることがわかります。

また、*numbersを使って配列の最初の要素にアクセスしています。

配列を関数に渡す方法

配列を関数に渡す際には、配列の先頭要素のポインタを渡します。

以下の例では、配列を関数に渡してその要素を出力しています。

#include <stdio.h>
// 配列を受け取る関数
void printArray(int *arr, int size) {
    for (int i = 0; i < size; i++) {
        printf("%d ", arr[i]);
    }
    printf("\n");
}
int main() {
    int numbers[4] = {5, 10, 15, 20};
    // 配列を関数に渡す
    printArray(numbers, 4);
    return 0;
}
5 10 15 20

このコードでは、printArray関数に配列numbersを渡しています。

関数は配列の先頭要素のポインタを受け取り、配列の要素を出力します。

ポインタを使った配列操作

ポインタを使って配列の要素を操作することも可能です。

以下の例では、ポインタを使って配列の要素を変更しています。

#include <stdio.h>
int main() {
    int numbers[3] = {1, 2, 3};
    int *ptr = numbers; // 配列の先頭要素を指すポインタ
    // ポインタを使って配列の要素を変更
    *(ptr + 1) = 20;
    // 変更後の配列を出力
    for (int i = 0; i < 3; i++) {
        printf("%d ", numbers[i]);
    }
    return 0;
}
1 20 3

この例では、ポインタptrを使って配列numbersの2番目の要素を20に変更しています。

ポインタ演算を用いることで、配列の要素を柔軟に操作することができます。

応用例

多次元配列の利用

多次元配列は、配列の配列として扱われ、行列のようなデータを表現するのに便利です。

以下の例では、2次元配列を使って行列を初期化し、出力しています。

#include <stdio.h>
int main() {
    // 2次元配列の宣言と初期化
    int matrix[2][3] = {
        {1, 2, 3},
        {4, 5, 6}
    };
    // 2次元配列の要素を出力
    for (int i = 0; i < 2; i++) {
        for (int j = 0; j < 3; j++) {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    return 0;
}
1 2 3
4 5 6

このコードでは、2行3列の行列を表す2次元配列matrixを宣言し、初期化しています。

ネストされたforループを使って、行列の各要素を出力しています。

配列を使った文字列操作

C言語では、文字列はchar型の配列として扱われます。

以下の例では、文字列を配列として宣言し、文字列の長さを計算しています。

#include <stdio.h>
#include <string.h>
int main() {
    // 文字列をchar型の配列として宣言
    char str[] = "Hello, World!";
    // 文字列の長さを計算
    int length = strlen(str);
    // 文字列とその長さを出力
    printf("String: %s\n", str);
    printf("Length: %d\n", length);
    return 0;
}
String: Hello, World!
Length: 13

この例では、strという文字列をchar型の配列として宣言し、strlen関数を使って文字列の長さを計算しています。

配列を使ったデータ構造の実装

配列を使って、スタックやキューなどのデータ構造を実装することができます。

以下の例では、配列を使ってスタックを実装しています。

#include <stdio.h>
#define MAX 5
int stack[MAX];
int top = -1;
// スタックに要素をプッシュ
void push(int value) {
    if (top == MAX - 1) {
        printf("Stack Overflow\n");
    } else {
        stack[++top] = value;
    }
}
// スタックから要素をポップ
int pop() {
    if (top == -1) {
        printf("Stack Underflow\n");
        return -1;
    } else {
        return stack[top--];
    }
}
int main() {
    // スタックに要素を追加
    push(10);
    push(20);
    push(30);
    // スタックから要素を削除して出力
    printf("Popped: %d\n", pop());
    printf("Popped: %d\n", pop());
    return 0;
}
Popped: 30
Popped: 20

このコードでは、配列stackを使ってスタックを実装しています。

push関数でスタックに要素を追加し、pop関数でスタックから要素を削除しています。

スタックの基本操作を配列で実現しています。

よくある質問

配列のサイズを動的に変更できますか?

C言語の標準的な配列は、宣言時にサイズが固定され、動的に変更することはできません。

しかし、動的メモリ割り当てを使用することで、配列のように動的にサイズを変更することが可能です。

mallocrealloc関数を使用してメモリを動的に確保し、必要に応じてサイズを変更することができます。

例えば、int *array = malloc(sizeof(int) * initial_size);のようにして初期サイズを確保し、reallocを使ってサイズを変更します。

配列の初期化方法は他にありますか?

配列の初期化方法にはいくつかの方法があります。

最も一般的なのは、中括弧{}を使って要素を列挙する方法です。

例えば、int numbers[3] = {1, 2, 3};のように初期化します。

また、全要素を0で初期化する場合は、int numbers[3] = {0};と記述することもできます。

さらに、配列のサイズを省略して初期化することも可能で、int numbers[] = {1, 2, 3};と書くと、コンパイラが自動的にサイズを決定します。

配列とポインタの違いは何ですか?

配列とポインタは似たように扱われることがありますが、異なる概念です。

配列は固定サイズのメモリ領域を指し、宣言時にそのサイズが決まります。

一方、ポインタはメモリのアドレスを格納する変数であり、指す先のメモリ領域を動的に変更することができます。

配列名は配列の先頭要素のアドレスを指すポインタとして扱われますが、配列自体はポインタではありません。

ポインタは、int *ptr;のように宣言し、ptr = &variable;のようにアドレスを代入して使用します。

まとめ

この記事では、C言語におけるint型配列の基本的な概念から応用的な使い方までを詳しく解説しました。

配列の宣言や初期化、メモリ配置、サイズの制限、要素へのアクセス方法を理解することで、プログラムの効率的なデータ管理が可能になります。

また、配列とポインタの関係や多次元配列、文字列操作、データ構造の実装といった応用例を通じて、配列の多様な活用方法を学びました。

これを機に、実際のプログラミングで配列を活用し、より複雑なデータ処理に挑戦してみてください。

当サイトはリンクフリーです。出典元を明記していただければ、ご自由に引用していただいて構いません。

関連カテゴリーから探す

  • URLをコピーしました!
目次から探す