「C言語の基礎 - 配列・メモリ領域」の版間の差分

📢 Webサイト閉鎖と移転のお知らせ
このWebサイトは2026年9月に閉鎖いたします。
新しい記事は移転先で追加しております。(旧サイトでは記事を追加しておりません)

ページの作成:「== メモリ領域を動的に確保する == C言語で、メモリ領域を動的に確保するには、stdlib.hのmalloc関数を使用する。<br> <source lang="c"…」
 
文字列「<source lang」を「<syntaxhighlight lang」に置換
 
(同じ利用者による、間の2版が非表示)
1行目: 1行目:
== メモリ領域を動的に確保する ==
== メモリ領域を動的に確保する ==
C言語で、メモリ領域を動的に確保するには、stdlib.hのmalloc関数を使用する。<br>
C言語で、メモリ領域を動的に確保するには、stdlib.hのmalloc関数を使用する。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdlib.h>
  #include <stdlib.h>
   
   
  void *malloc(size_t size);
  void *malloc(size_t size);
  </source>
  </syntaxhighlight>
<br>
<br>
malloc関数はsizeバイト分のメモリ領域を確保して、そのメモリ領域へのポインタを返す関数である。<br>
malloc関数はsizeバイト分のメモリ領域を確保して、そのメモリ領域へのポインタを返す関数である。<br>
13行目: 13行目:
malloc関数を使用したメモリの動的確保は、多くの場合、以下のように実装する。<br>
malloc関数を使用したメモリの動的確保は、多くの場合、以下のように実装する。<br>
以下の例として、int型のデータが10個入るサイズのメモリ領域を確保している。<br>
以下の例として、int型のデータが10個入るサイズのメモリ領域を確保している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  int *ptr = nullptr;
  int *ptr = nullptr;
   
   
26行目: 26行目:
  /* メモリ領域の解放 */
  /* メモリ領域の解放 */
  free(ptr);
  free(ptr);
  </source>
  </syntaxhighlight>
<br>
<br>
以下の例では、malloc関数を使用して、メモリ領域を動的に確保している。<br>
以下の例では、malloc関数を使用して、メモリ領域を動的に確保している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <stdlib.h>
57行目: 57行目:
     return EXIT_SUCCESS;
     return EXIT_SUCCESS;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


== メモリ領域を確保して、その領域を0で初期化する ==
== メモリ領域を確保して、その領域を0で初期化する ==
C言語で、メモリ領域を動的に確保して、その領域を0で初期化するには、stdlib.hのcalloc関数を使用する。<br>
C言語で、メモリ領域を動的に確保して、その領域を0で初期化するには、stdlib.hのcalloc関数を使用する。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdlib.h>
  #include <stdlib.h>
   
   
  void *calloc(size_t nmemb, size_t size);
  void *calloc(size_t nmemb, size_t size);
  </source>
  </syntaxhighlight>
<br>
<br>
calloc関数は、sizeバイトの大きさを持つオブジェクトがnmemb個分入るメモリ領域を確保して、その領域のすべてのビットを0で初期化する関数である。<br>
calloc関数は、sizeバイトの大きさを持つオブジェクトがnmemb個分入るメモリ領域を確保して、その領域のすべてのビットを0で初期化する関数である。<br>
73行目: 73行目:
<br>
<br>
以下の例では、calloc関数を使用してメモリ領域を動的に確保している。<br>
以下の例では、calloc関数を使用してメモリ領域を動的に確保している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <stdlib.h>
104行目: 104行目:
     return EXIT_SUCCESS;
     return EXIT_SUCCESS;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


== 確保したメモリ領域のサイズを変更する ==
== 確保したメモリ領域のサイズを変更する ==
malloc関数やcalloc関数等で確保したメモリ領域のサイズを変更するには、stdlib.hのrealloc関数を使用する。<br>
malloc関数やcalloc関数等で確保したメモリ領域のサイズを変更するには、stdlib.hのrealloc関数を使用する。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdlib.h>
  #include <stdlib.h>
   
   
  void *realloc(void *ptr, size_t size);
  void *realloc(void *ptr, size_t size);
  </source>
  </syntaxhighlight>
<br>
<br>
realloc関数は、まず、ptrが指すメモリ領域を解放した後、大きさがsizeである新しいメモリ領域を確保する関数である。<br>
realloc関数は、まず、ptrが指すメモリ領域を解放した後、大きさがsizeである新しいメモリ領域を確保する関数である。<br>
120行目: 120行目:
<br>
<br>
以下の例では、realloc関数を使用して、確保したメモリ領域のサイズを変更している。<br>
以下の例では、realloc関数を使用して、確保したメモリ領域のサイズを変更している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <stdlib.h>
164行目: 164行目:
     return EXIT_SUCCESS;
     return EXIT_SUCCESS;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


170行目: 170行目:
malloc関数やcalloc関数、realloc関数で確保したメモリ領域を解放するには、stdlib.hのfree関数を使用する。<br>
malloc関数やcalloc関数、realloc関数で確保したメモリ領域を解放するには、stdlib.hのfree関数を使用する。<br>
free関数は、ptrが指すメモリ領域を解放する関数である。<br>
free関数は、ptrが指すメモリ領域を解放する関数である。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdlib.h>
  #include <stdlib.h>
   
   
  void free (void *ptr);
  void free (void *ptr);
  </source>
  </syntaxhighlight>
<br>
<br>
以下の例として、free関数を使用してメモリ領域を開放している。<br>
以下の例として、free関数を使用してメモリ領域を開放している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <stdlib.h>
198行目: 198行目:
     return EXIT_SUCCESS;
     return EXIT_SUCCESS;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


== 配列やメモリ領域の内容を初期化する ==
== 配列やメモリ領域の内容を初期化する ==
配列を初期化する場合は、以下のように配列の宣言時に初期化子を使用する。<br>
配列を初期化する場合は、以下のように配列の宣言時に初期化子を使用する。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  int a1[] = {1, 2, 3}; /* それぞれ異なる値で初期化 */
  int a1[] = {1, 2, 3}; /* それぞれ異なる値で初期化 */
  int a2[256] = {0};    /* 同一の値で初期化 */
  int a2[256] = {0};    /* 同一の値で初期化 */
  </source>
  </syntaxhighlight>
<br>
<br>
また、malloc関数等を使用して動的に確保したメモリ領域を初期化する場合や、配列を宣言時以外に初期化する場合は、<br>
また、malloc関数等を使用して動的に確保したメモリ領域を初期化する場合や、配列を宣言時以外に初期化する場合は、<br>
221行目: 221行目:
<br>
<br>
memmove関数は、memcpy関数と似ているが、領域の重なり合うオブジェクト間でコピーを行う場合でも正しく動作する。<br>
memmove関数は、memcpy関数と似ているが、領域の重なり合うオブジェクト間でコピーを行う場合でも正しく動作する。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <string.h>
  #include <string.h>
   
   
227行目: 227行目:
   
   
  void *memmove(void *s1, const void *s2, size_t n);
  void *memmove(void *s1, const void *s2, size_t n);
  </source>
  </syntaxhighlight>
<br>
<br>
以下の例では、memcpy関数を使用して、int型の配列をコピーしている。<br>
以下の例では、memcpy関数を使用して、int型の配列をコピーしている。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <stdlib.h>
253行目: 253行目:
     return EXIT_SUCCESS;
     return EXIT_SUCCESS;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


261行目: 261行目:
memcmp関数は、s1が指すオブジェクトの始めのn文字と、s2が指すオブジェクトの始めのn文字を比較する関数である。<br>
memcmp関数は、s1が指すオブジェクトの始めのn文字と、s2が指すオブジェクトの始めのn文字を比較する関数である。<br>
memcmp関数は、比較するオブジェクトが同じなら0、s1 > s2なら正の整数、s1 < s2なら負の整数を返す。<br>
memcmp関数は、比較するオブジェクトが同じなら0、s1 > s2なら正の整数、s1 < s2なら負の整数を返す。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <string.h>
  #include <string.h>
   
   
  int memcmp (const void *s1, const void *s2, size_t n);
  int memcmp (const void *s1, const void *s2, size_t n);
  </source>
  </syntaxhighlight>
<br>
<br>
以下の例では、memcmp関数を使用して、int型の配列を比較している。<br>
以下の例では、memcmp関数を使用して、int型の配列を比較している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <stdlib.h>
314行目: 314行目:
     return EXIT_SUCCESS;
     return EXIT_SUCCESS;
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
<br><br>


322行目: 322行目:
qsort関数は、baseが指すオブジェクトの配列(要素数がnmemb個、各要素の大きさがsizeである配列)を、compareが指す比較関数にしたがって整列する関数である。<br>
qsort関数は、baseが指すオブジェクトの配列(要素数がnmemb個、各要素の大きさがsizeである配列)を、compareが指す比較関数にしたがって整列する関数である。<br>
ちなみに、qsort関数の名前はクイックソートに由来するが、内部でクイックソートアルゴリズムを使用してる保障はない。(処理系定義)<br>
ちなみに、qsort関数の名前はクイックソートに由来するが、内部でクイックソートアルゴリズムを使用してる保障はない。(処理系定義)<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdlib.h>
  #include <stdlib.h>
   
   
  void qsort (void *base, size_t nmemb, size_t size, int (*compare\)(const void *, const void *));
  void qsort (void *base, size_t nmemb, size_t size, int (*compare\)(const void *, const void *));
  </source>
  </syntaxhighlight>
<br>
<br>
qsort関数の引数は以下の通りである。<br>
qsort関数の引数は以下の通りである。<br>
340行目: 340行目:
<br>
<br>
以下の例では、qsort関数を使用して、int型の配列を昇順に整列している。<br>
以下の例では、qsort関数を使用して、int型の配列を昇順に整列している。<br>
  <source lang="c">
  <syntaxhighlight lang="c">
  #include <stdio.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <stdlib.h>
388行目: 388行目:
     }
     }
  }
  }
  </source>
  </syntaxhighlight>
<br><br>
 
== 配列やメモリ領域の内容から文字を探索する ==
C言語で、配列やメモリ領域の内容から文字を探索するには、string.hのmemchr関数を使用する。<br>
<br>
memchr関数は、sが指すオブジェクトの先頭からn文字分検索して、文字cが最初に現れる位置を探索する関数である。<br>
なお、探索中はsが指すオブジェクトとcはunsigned char型として解釈される。<br>
memchr関数は、strchr関数と似ているが、'\0'があっても探索を続ける。<br>
<br>
memchr関数は、文字が見つかった場合は探し出した文字へのポインタを返し、文字が見つからなかった場合はNULLを返す。<br>
memchr関数を利用すると、メモリ領域の中で指定した文字が現れる位置を探すことができる。<br>
<syntaxhighlight lang="c">
#include <string.h>
void *memchr (const void *s, int c, size_t n);
</syntaxhighlight>
<br>
以下の例では、memchr関数を使用して、char型の配列を探索している。<br>
<syntaxhighlight lang="c">
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 256
int main(void)
{
    char s[] = {'S', 'n', 'o', 'o', 'p', 'y', '\0', 'z'};
    char *ret;
    int c;
    /* 入力 */
    puts("文字を入力してください.");
    c = getchar();
    /* s が指す配列中に c があるか? */
    if ((ret = (char *)memchr(s, c, sizeof(char) * N)) != NULL)
    {
      printf("%cは%d番目にありました.\n", c, ret - s);
    }
    else
    {
      printf("%cはありませんでした.\n", c);
    }
    return EXIT_SUCCESS;
}
</syntaxhighlight>
<br><br>
 
== 配列やメモリ領域の内容から任意の値を探索する ==
C言語で、配列やメモリ領域の内容から任意の値を探索するには、stdlib.hのbsearch関数を使用する。<br>
<br>
bsearch関数は、baseが指すオブジェクトの配列(要素数がnmemb個、各要素の大きさがsizeである配列)から、<br>
keyが指すオブジェクトに一致する要素を探索する関数である。<br>
なお、baseが指す配列は昇順に整列(ソート)されている必要がある。<br>
<syntaxhighlight lang="c">
#include <stdlib.h>
void *bsearch (const void *key, const void *base, size_t nmemb, size_t size, int (*compar)(const void *, const void *));
</syntaxhighlight>
<br>
bsearch関数の引数は、以下の通りとなる。<br>
* key: 探索キー
* base: 探索する配列
* nmemb: 配列の要素数
* size: 配列の個々の要素のサイズ
* compar: 比較関数
<br>
bsearch関数を使用するには、事前にプログラマが比較関数を実装する必要がある。また、比較関数は以下のルールに基づいて実装する。<br>
比較関数は、keyへのポインタを第1引数とし、配列要素へのポインタを第2引数として呼び出される。<br>
* 第1引数が第2引数より小さい場合 : 0より小さい値を返す
* 第1引数が第2引数と一致する場合 : 0を返す
* 第1引数が第2引数よりも大きい場合 : 0より大きい値を返す
<br>
以下の例では、bsearch関数を使用して、int型の配列を探索している。<br>
<syntaxhighlight lang="c">
#include <stdio.h>
#include <stdlib.h>
int compare(const int *val1, const int *val2);
int main(void)
{
    int ary[] = {1, 2, 3, 4, 5, 6, 7, 8};
    int key, *result;
    int n = sizeof(ary) / sizeof(ary[0]);
    /* keyを入力 */
    scanf("%d", &key);
    /* 探索 */
    result = bsearch(&key, ary, n, sizeof(int), (int (*)(const void *, const void *))compare);
    if ( result == NULL )
    {
      fprintf(stderr, "%dは見つかりませんでした.\n", key);
    }
    else
    {
      printf("%dは配列の%d番目の要素です.\n", key, (int)(result - &ary[0]));
    }
    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;
    }
}
</syntaxhighlight>
<br><br>
<br><br>


__FORCETOC__
__FORCETOC__
[[カテゴリ:C]]
[[カテゴリ:C]]