MochiuWiki : SUSE, EC, PCB
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
C言語の基礎 - 配列・メモリ領域のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
C言語の基礎 - 配列・メモリ領域
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== メモリ領域を動的に確保する == C言語で、メモリ領域を動的に確保するには、stdlib.hのmalloc関数を使用する。<br> <source lang="c"> #include <stdlib.h> void *malloc(size_t size); </source> <br> malloc関数はsizeバイト分のメモリ領域を確保して、そのメモリ領域へのポインタを返す関数である。<br> なお、メモリ領域の確保に失敗した場合は、NULLを返す。<br> malloc関数で確保したメモリ領域は、free関数で解放する。<br> malloc関数を使用したメモリの動的確保は、多くの場合、以下のように実装する。<br> 以下の例として、int型のデータが10個入るサイズのメモリ領域を確保している。<br> <source lang="c"> int *ptr = nullptr; /* int型のデータが1 個入るサイズのメモリ領域を確保 */ if ((ptr = (int *)malloc(sizeof(int) * 10)) == NULL) { /* エラー処理 */ } /* 何らかの処理 */ /* メモリ領域の解放 */ free(ptr); </source> <br> 以下の例では、malloc関数を使用して、メモリ領域を動的に確保している。<br> <source lang="c"> #include <stdio.h> #include <stdlib.h> int main(void) { int *ptr = nullptr, *work = nullptr; /* int 型のデータが 10 個入るサイズのメモリ領域を確保 */ if ((ptr = (int *)malloc(sizeof(int) * 10)) == NULL) { fprintf(stderr, "メモリ領域を確保に失敗しました.\n"); exit(EXIT_FAILURE); } work = ptr; for ( int i = 0; i < 10; i++) { work[i] = i; printf("%d ", work[i]); } printf("\n"); /* メモリ領域の解放 */ free(ptr); return EXIT_SUCCESS; } </source> <br><br> == メモリ領域を確保して、その領域を0で初期化する == C言語で、メモリ領域を動的に確保して、その領域を0で初期化するには、stdlib.hのcalloc関数を使用する。<br> <source lang="c"> #include <stdlib.h> void *calloc(size_t nmemb, size_t size); </source> <br> calloc関数は、sizeバイトの大きさを持つオブジェクトがnmemb個分入るメモリ領域を確保して、その領域のすべてのビットを0で初期化する関数である。<br> メモリ領域の確保に成功した場合は、そのメモリ領域へのポインタを返し、失敗した場合はNULLを返す。<br> また、calloc関数で確保したメモリ領域は、free関数で解放する。<br> <br> 以下の例では、calloc関数を使用してメモリ領域を動的に確保している。<br> <source lang="c"> #include <stdio.h> #include <stdlib.h> int main(void) { double *ptr = nullptr; int nmemb = 3; /* double サイズ 3 個分の領域を確保 */ if ((ptr = (double *)calloc(nmemb, sizeof(double))) == NULL) { fprintf(stderr, "メモリ領域を確保に失敗しました.\n"); return EXIT_FAILURE; } /* 適当に値を入力 */ ptr[0] = 1950; /* メモリ領域の内容を表示する */ for ( int i = 0; i < nmemb; i++ ) { printf(" %.1f", ptr[i]); } printf("\n"); /* メモリ領域の解放 */ free(ptr); return EXIT_SUCCESS; } </source> <br><br> == 確保したメモリ領域のサイズを変更する == malloc関数やcalloc関数等で確保したメモリ領域のサイズを変更するには、stdlib.hのrealloc関数を使用する。<br> <source lang="c"> #include <stdlib.h> void *realloc(void *ptr, size_t size); </source> <br> realloc関数は、まず、ptrが指すメモリ領域を解放した後、大きさがsizeである新しいメモリ領域を確保する関数である。<br> 新しいメモリ領域は、可能な限り開放する前の古いメモリ領域の内容を引き継ぐが、古いメモリ領域の大きさを超えた部分の値は不定となる。<br> また、realloc関数は、メモリ領域の確保に成功した場合は、そのメモリ領域へのポインタを返し、失敗した場合はNULLを返す。<br> <br> 以下の例では、realloc関数を使用して、確保したメモリ領域のサイズを変更している。<br> <source lang="c"> #include <stdio.h> #include <stdlib.h> int main(void) { int *ptr = nullptr; /* intサイズ10個分のメモリ領域を確保 */ if ((ptr = (int *)malloc(sizeof(int) * 10)) == NULL ) { fprintf(stderr, "メモリ領域が確保できません.\n"); return EXIT_FAILURE; } /* 確保したメモリ領域に値を格納して表示 */ printf("realloc 関数使用前.\n"); for ( int i = 0; i < 10; i++ ) { ptr[i] = i; printf(" %d", ptr[i]); } printf("\n"); /* intサイズ10個分から15個分のメモリ領域に拡張する */ if ((ptr = (int *)realloc(ptr, sizeof(int) * 15)) == NULL) { fprintf(stderr, "メモリが確保できません。\n"); return EXIT_FAILURE; } /* 確保したメモリ領域に値を格納して表示 */ printf("\nrealloc関数使用後.\n"); for ( int i = 0; i < 15; i++ ) { ptr[i] = i; printf(" %d", ptr[i]); } printf("\n"); /* メモリ領域の解放 */ free(ptr); return EXIT_SUCCESS; } </source> <br><br> == メモリ領域を解放する == malloc関数やcalloc関数、realloc関数で確保したメモリ領域を解放するには、stdlib.hのfree関数を使用する。<br> free関数は、ptrが指すメモリ領域を解放する関数である。<br> <source lang="c"> #include <stdlib.h> void free (void *ptr); </source> <br> 以下の例として、free関数を使用してメモリ領域を開放している。<br> <source lang="c"> #include <stdio.h> #include <stdlib.h> int main(void) { int *ptr = nullptr; /* int サイズのメモリ領域を確保 */ if ((ptr = (int *)malloc(sizeof(int))) == NULL) { fprintf(stderr, "メモリ領域の確保に失敗しました.\n"); exit(EXIT_FAILURE); } /* メモリ領域の解放 */ free(ptr); printf("メモリ領域を解放しました.\n"); return EXIT_SUCCESS; } </source> <br><br> == 配列やメモリ領域の内容を初期化する == 配列を初期化する場合は、以下のように配列の宣言時に初期化子を使用する。<br> <source lang="c"> int a1[] = {1, 2, 3}; /* それぞれ異なる値で初期化 */ int a2[256] = {0}; /* 同一の値で初期化 */ </source> <br> また、malloc関数等を使用して動的に確保したメモリ領域を初期化する場合や、配列を宣言時以外に初期化する場合は、<br> 反復処理等を使用して、個々の要素に対して個別に値を格納していく必要がある。<br> <br> 文字配列(文字列)を初期化する場合は、memset関数を使用する。これについては、ページの"文字列を初期化する"を参照する。<br> <br><br> == 配列やメモリ領域の内容をコピーする == C言語で、配列やメモリ領域の内容をコピーするには、string.hのmemcpy関数またはmemmove関数を使用する。<br> <br> memcpy関数は、s2が指すオブジェクトからs1が指すオブジェクトにn文字コピーする関数である。<br> なお、領域の重なり合うオブジェクト間でコピーが行われるときの動作は未定義である。<br> <br> memmove関数は、memcpy関数と似ているが、領域の重なり合うオブジェクト間でコピーを行う場合でも正しく動作する。<br> <source lang="c"> #include <string.h> void *memcpy(void * restrict s1, const void * restrict s2, size_t n); void *memmove(void *s1, const void *s2, size_t n); </source> <br> 以下の例では、memcpy関数を使用して、int型の配列をコピーしている。<br> <source lang="c"> #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 8 int main(void) { int x1[] = {1, 2, 3, 4, 5, 6, 7, 8}; int x2[N] = {0}; /* メモリ領域内の内容をコピー */ memcpy(x2, x1, sizeof(int) * N); /* x1 と x2 の各要素を表示 */ for ( int i = 0; i < N; i++ ) { printf("x1[%d] : %d, x2[%d] : %d\n", i, x1[i], i, x2[i]); } return EXIT_SUCCESS; } </source> <br><br> == 配列やメモリ領域の内容を比較する == C言語で、配列やメモリ領域の内容を比較するには、string.hのmemcmp関数を使用する。<br> <br> memcmp関数は、s1が指すオブジェクトの始めのn文字と、s2が指すオブジェクトの始めのn文字を比較する関数である。<br> memcmp関数は、比較するオブジェクトが同じなら0、s1 > s2なら正の整数、s1 < s2なら負の整数を返す。<br> <source lang="c"> #include <string.h> int memcmp (const void *s1, const void *s2, size_t n); </source> <br> 以下の例では、memcmp関数を使用して、int型の配列を比較している。<br> <source lang="c"> #include <stdio.h> #include <stdlib.h> #include <string.h> #define N 8 int main(void) { int x1[] = {0, 1, 2, 3, 4, 5, 6, 7}; int x2[] = {0, 1, 2, 3, 4, 5, 6, 6}; int x3[] = {0, 1, 2, 3, 4, 5, 6, 8}; int x4[] = {0, 1, 2, 3, 4, 5, 6, 7}; /* x1 と x2 を比較 */ if ( memcmp(x1, x2, sizeof(int) * N) == 0 ) { printf("x1とx2は同じ要素を持つ配列です.\n"); } else { printf("x1とx2は異なる要素を持つ配列です.\n"); } /* x1 と x3 を比較 */ if ( memcmp(x1, x3, sizeof(int) * N) == 0 ) { printf("x1とx3は同じ要素を持つ配列です.\n"); } else { printf("x1とx3は異なる要素を持つ配列です.\n"); } /* x1 と x4 を比較 */ if ( memcmp(x1, x4, sizeof(int) * N) == 0 ) { printf("x1とx4は同じ要素を持つ配列です.\n"); } else { printf("x1とx4は異なる要素を持つ配列です.\n"); } return EXIT_SUCCESS; } </source> <br><br> == 配列やメモリ領域の内容を整列(ソート)する == C言語で、配列やメモリ領域の内容を整列(ソート)するには、stdlib.hのqsort関数を使用する。<br> <br> qsort関数は、baseが指すオブジェクトの配列(要素数がnmemb個、各要素の大きさがsizeである配列)を、compareが指す比較関数にしたがって整列する関数である。<br> ちなみに、qsort関数の名前はクイックソートに由来するが、内部でクイックソートアルゴリズムを使用してる保障はない。(処理系定義)<br> <source lang="c"> #include <stdlib.h> void qsort (void *base, size_t nmemb, size_t size, int (*compare\)(const void *, const void *)); </source> <br> qsort関数の引数は以下の通りである。<br> * base : 整列したい配列 * nmemb : 配列の要素数 * size : 配列の個々の要素のサイズ * compar : 比較関数 <br> qsort関数を使用するには、事前にプログラマが比較関数を実装する必要がある。比較関数は、以下のルールに基づいて実装する必要がある。<br> * 第1引数が第2引数より小さい場合 : 0より小さい値を返す * 第1引数が第2引数と一致する場合 : 0を返す * 第1引数が第2引数よりも大きい場合 : 0より大きい値を返す <br> 以下の例では、qsort関数を使用して、int型の配列を昇順に整列している。<br> <source lang="c"> #include <stdio.h> #include <stdlib.h> int compare(const int *val1, const int *val2); int main(void) { int ary[] = {9, 8, 7, 6, 5, 4, 3, 2, 1}; int n = sizeof(ary) / sizeof(ary[0]); /* 配列の内容を表示 */ printf("整列前: "); for ( int i = 0; i < n; i++ ) { printf("%d", ary[i]); } /* qsort 関数を使用して昇順に並び替える */ qsort(ary, n, sizeof(int), (int (*)(const void *, const void *))compare); /* 配列の内容を表示 */ printf("\n整列後: "); for ( int i = 0; i < n; i++ ) { printf("%d", ary[i]); } printf("\n"); return EXIT_SUCCESS; } /* 比較関数 */ int compare(const int *val1, const int *val2) { if ( *val1 < *val2 ) { return -1; } else if ( *val1 == * val2 ) { return 0; } else { return 1; } } </source> <br><br> __FORCETOC__ [[カテゴリ:C]]
C言語の基礎 - 配列・メモリ領域
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse