0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【プログラミング言語】命令型言語・手続き型言語を理解する Part2

Last updated at Posted at 2024-11-19

手続き

命令型言語では、複雑なシステムを部品化(モジュール化)し、その部品化されたプログラム単位を手続きと呼ぶ。(アセンブリ言語でいうサブルーチン

手続き定義のEBNF

<手続き定義> ::= <返り値の型名><手続き名>(<仮引数>)<手続き本体> 
sample.c
int square(int x) {  // xが仮引数
  return x * x;
}

値渡しとポインタ渡し(値共有)と参照渡し(変数共有)

変数は、大きく分類して「値型」「ポインタ型・参照型」がある。

  • 値型変数 : 変数は値(データ)そのものを保持する
  • ポインタ型・参照型 : 値(データやオブジェクト)のアドレス値・参照値を保持して、値をポイント・参照する

変数の渡し方には「値渡し」「ポインタ渡し」「参照渡し」がある。

・値渡しの特徴
変数が保持している値をコピーして渡す。値型変数であれば値のコピー、アドレス型・参照型変数であればアドレス値・参照値のコピーを渡す。
実引数と仮引数は別々の変数。仮引数に再代入しても実引数に影響しない。
→関数に引数のコピーを渡す方法であり、関数内で引数の変更をしても、呼び出し元のデータに影響を与えたくない場合に使用する。

sample.py
def increment(value):
    value = value + 1

x = 15
increment(x)
print(x)  # 15(変更されていない)

a = increment(x)
print(a)  # 16

・ポインタ渡しの特徴
ポインタ型・参照型変数が保持しているアドレス値・参照値を渡す。変数が保持している値(アドレス値・参照値)を渡すので値渡しの一種である。「参照の値渡し」である。
実引数と仮引数は別々の変数。仮引数に再代入しても実引数に影響しない。
ポイント・参照先の値(データやオブジェクト)はコピーせずに共有する。
ポイント・参照先の値の内容を変更すると呼び出し元の値に影響する。
→関数内でポイント・参照先の値を変更し、その変更が呼び出し元のデータに反映されることを望む場合に使用する。また大きなデータを渡す場合にも必要となる。
C言語の配列は自動的にポインタ渡しとなる。PHPの配列は値渡しで配列のコピーが渡る。
C言語の構造体は値型で構造体のコピーが渡る。

sample.py
def increment_array(arr, index):
    arr[index] = arr[index] + 1

numbers = [1, 2, 3]
increment_array(numbers, 1)
print(numbers)  # 出力: [1, 3, 3](更新されている)

・参照渡しの特徴
変数への参照を渡す。
実引数と仮引数は同一の変数。仮引数に再代入すると実引数に代入される。
→値型変数の値のコピーせずに共有したい場合に使用する。戻り値が複数ある場合に引数に値を返したいときに使用する。

値渡しは値(データ)のコピーを渡し、ポインタ渡しや参照渡しは値(データやオブジェクト)を共有し、参照渡しは変数を共有する。

sample.c
void increment(int a, int *b) {  // アドレスを仮引数bで受ける
    a = 10;
    *b = 10;                     // ポインタbの参照先を10に変更
}
int main() {
    int x = 5;
    int y = 5;
    increment(x, &y);            // アドレス自体(&y)を値渡しする
    printf("%d %d\n", x, y) ;    // 5 10
}

ここで一つ思い出したいのが、scanf("%d", &x);である。ユーザーからの入力を受け取る際に書いていたものだが、これはアドレス渡しに依るものである。ここで意味していることは、xのアドレスをscanf()の仮引数に渡し、xの右辺値をポインタ経由で書き換えることである。

スコープと存続範囲

変数の存続範囲とは、変数に対してメモリ領域を割り当てている期間のこと。
スコープ=存続範囲ではない。以下に、その例を与える。

sample.c
void main() {
    int *p;
    {
        int x = 6;
        p = &x;
    }                    // xのスコープはここまでだが存続範囲は続く
  //printf("%d\n", x);   // スコープ外なのでエラー
    printf("%d\n", *p);  // 6
    *p = 15;             // 値の書き換えも可能
    printf("%d\n", *p);  // 15
}

ここでxのスコープは複文({}で囲まれた文)の期間に等しいが、xのメモリ領域はprintf("%d\n", *p); // 6より、まだ存続していることがわかる。したがって、スコープ=存続範囲ではないといえる。

メモリ

実行時スタック

スタックの振る舞いの例として以下に図を掲載する。スタックにはpushでレコード(関数の呼び出しごとに必要な情報を格納するメモリ領域)を収納し、popで上から順にレコードを取り出し、実行する。

計算機言語 jpeg

メモリ領域の構成

以下に、C言語におけるメモリ領域を図で示す。

計算機言語2 jpeg

ヒープは動的にメモリを確保するための領域であり、malloc()free()を通じて自由に操作可能である。ここでmalloc()について注意点を述べる。

mallocによる動的メモリ確保

例えば、array[8]のint型をメモリで確保するとき、(4バイト)*832バイトが必要となる。しかし、malloc(8)では8バイトの領域しか確保されていない。したがって、malloc(sizeof(int) * 8)とするのである。
sizeof(int)4バイトを示す。

0
0
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?