メモリ、16進数、ポインタ、値渡し、参照渡し

2024.05.02

16進数

16進数は画像やファイルを扱うときに使用される。HEX(hexadecimal number)と呼ばれる。0からFまでの記号を使う。

プログラミングではメモリのバイト数を16進数で数えることが多い。データを4ビット単位で扱いたい場合に便利。

01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C, 0D, 0E, 0F, 10, 11, 12

ちなみに10, 11, 12の部分は10進数と混合しやすい為、16進数では"0 ✖️ 10"と表示される。

1番大きい数字 -> FF
16 * F + 1 * F
16 * 15 + 1 * 15
240 + 15
255

128 64 32 16 8 4 2 1
  ・  ・  ・  ・ ・・・・

138               10進数
10001010     2進数
8A                16進数


1桁の16進数は4ビットの2進数に対応する。2進数を以下のように4ビットずつ計算する

1000    1010
 ↓           ↓
   8          8 + 2 -> 10は16進数でA
          ↓
   8A   


ポインタ

ある値のアドレス、アドレスの位置。変数やデータのメモリ上の位置(アドレス)を格納するための特殊な変数のこと。

 →   アドレス演算子。被演算子のアドレス、&nとすることで変数nのアドレスを取得する。
* →    間接参照演算子。&nとするとアドレスが示すメモリの値にアクセスする。
#include <stdio.h>

int main(void)
{
  int n = 50;             // 変数nを用意
  int *p = &n;     // &nでアドレスを取得し*pに代入
  printf("%p\n", p);   // 変数を出力
  printf("%i\n", *p); // 変数が格納されているアドレスを出力 
}

以下出力結果
0x7ffd686c99ec
50

動的メモリ割り当て

malloc・・・メモリ割り当てを行う関数。数値を入力としてオペレーティングシステムに何バイトのメモリを見つけるか決定する。メモリ割り当てに失敗した場合NULLを返す。

free・・・メモリの解放を行う関数。mallocが与えたメモリの塊を使い終わった後に行う。

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   // メモリ割り当て
   int *ptr; // *ptrとすることで値ではなく、int型の値へのポインタ(アドレス)が格納されることを宣言。
 ptr = malloc(sizeof(int));  // int型のサイズ分のメモリを割り当てる。一般的にint型は4バイトなのでmalloc(4);と同じ意味になる。
 if (ptr == NULL)
   {
      printf("メモリ割り当て失敗\n");
   }
   *ptr = 11;     // 値11が格納されているメモリのアドレスをptrに格納
   
   printf("メモリに格納された値%d\n", *ptr);
   printf("メモリに格納された値のアドレス%p\n", ptr);

   free(ptr);
   printf("メモリの解放\n");
}

以下出力結果
メモリに格納された値11
メモリに格納された値のアドレス0x558f5e0fd2a0
メモリの解放

mallocとfreeは組み合わせて使用する。そうでないとエラーの原因になる。

値渡し・・・関数に引数として渡された値がそのまま関数内でコピーされます。関数内で引数の値を変更しても、呼び出し元の変数には影響しない。

#include <stdio.h>

// 値渡しの関数
void increment(int x) {
    x++; // xを1増やす
    printf("Inside function: %d\n", x);
}

int main() {
    int num = 5;
    printf("Before function: %d\n", num);
    increment(num); // 関数呼び出し
    printf("After function: %d\n", num);
    return 0;
}

出力
Before function: 5
Inside function: 6
After function: 5

参照渡し・・・関数に引数として渡された変数のアドレスが渡される。そのアドレスを通じて変更を行う。

#include <stdio.h>

// 参照渡しの関数
void increment(int *x) {
    (*x)++; // xを1増やす
    printf("Inside function: %i\n", *x);
}

int main() {
    int num = 5;
    printf("Before function: %d\n", num);
    increment(&num); // 関数呼び出し
    printf("After function: %d\n", num);
    return 0;
}

出力
Before function: 5
Inside function: 6
After function: 6

コンピュータのメモリ内でのプログラム実行時の動作

コンピュータのメモリ内で起こっていること
————————————-
machine code
globals
heap




stack
————————————-

machine code・・・コンピュータが直接実行するバイナリコード。プログラムがメモリにロードされると、マシンコードが実行される。

globals・・・グローバル変数や静的変数など、プログラムのどこからでもアクセス可能な領域。プログラムの開始時にこの領域が確保され、プログラムの終了まで存在する。

heap・・・動的に確保されたメモリ領域で、mallocnew などの関数によって割り当てられる。プログラム実行中にメモリの割り当てと解放が行われるため、動的なデータ構造が格納される。

stack・・・関数の呼び出しと戻りに関連した情報(ローカル変数、関数の引数など)が格納される領域。関数が呼び出されるたびに新しいスタックフレームが作成され、関数の実行が終了するとスタックフレームが削除される。

heapとstackの部分でメモリ不足になり、異常終了やクラッシュを引き起こす。