[CS 50]スキーム

14177 ワード

コンパイル手順


コンパイルフェーズには、前処理、コンパイル、アセンブリ、ループカットの4つのフェーズが含まれます.

プリコンパイル


コンパイルの全過程の最初のステップでは、Cは#で始まるコードで、前のプロセッサが実際のコンパイル前に何かを実行することを示す役割を果たす.たとえば、ソースコード#include <stdio.h>が、前プロセッサに他のファイルの内容が含まれていることを通知すると、前プロセッサはstdioする.hファイルの内容を含むCソース形式のファイルが再生成され、#includeの部分に含まれる.

コンパイル


プリプロセッサがソースコードを生成すると、コンパイラはソースコードをアセンブリ言語にコンパイルします.

くみたて


アセンブリ言語に変換されたコードをオブジェクトコードに変換するには.CPUが理解できるように、0と1からなるコマンド語で変換します.これらのタスクはアセンブリという名前のプログラムによって実行されます.オブジェクトコードに変換するファイルが1つしかない場合は、コンパイルフェーズはこれで終了します.そうしないと、リンクフェーズに進みます.

リンク(Link)


プログラムが複数のファイルで構成されている場合は、アセンブリステップの後にオブジェクトファイルにマージするためのリンクステップが必要です.Linkerは、複数のオブジェクトコードファイルを1つの実行可能なオブジェクトコードファイルにマージします.

デバッグ


デバッグモード(CS 50 IDEのdebug 50)を使用して、ソースコードで問題をチェックしたいポイントを選択し、ブレークポイントを設定して「debug 50ファイル名」にコンパイルすると、変数の値をチェックしたり、コードを行単位で実行したりできます.デバッグを終了するには、CTRL+Cを押します.

メモリ


Cには複数のデータ型があり、データ型ごとにメモリサイズが異なる.
  • ブール:1バイト
  • 文字:1バイト
  • int:4バイト
  • float:4バイト
  • long:8バイト
  • 倍:8バイト
  • string : ?バイト(文字列の長さに依存)
  • 整列


    配列は、同じデータ型の値をメモリに連続的に格納し、変数として管理する概念です.
    #include <cs50.h>
    #include <stdio.h>
    
    int main(void)
    {
        // Scores
        int scores[3];
        scores[0] = 72;
        scores[1] = 73;
        scores[2] = 33;
    
        // Print average
        printf("Average: %i\n", (scores[0] + scores[1] + scores[2]) / 3);
    }
    int score[3];は、「score」という3つのintデータ型サイズを有する配列を生成することを意味する.配列のインデックスはゼロから始まります.

    動的宣言とストレージアレイ


    配列のサイズ(length)をユーザに直接入力し、配列のサイズに従ってループし、各インデックスの値(array[])をユーザに動的に入力して記憶する.次にaverageという関数をそれぞれ宣言して平均値を求めます.
    #include <cs50.h>
    #include <stdio.h>
    
    float average(int length, int array[]);
    
    int main(void)
    {
        // 사용자로부터 점수의 갯수 입력
        int n = get_int("Scores:  ");
    
        // 점수 배열 선언 및 사용자로부터 값 입력
        int scores[n];
        for (int i = 0; i < n; i++)
        {
            scores[i] = get_int("Score %i: ", i + 1);
        }
    
        // 평균 출력
        printf("Average: %.1f\n", average(n, scores));
    }
    
    //평균을 계산하는 함수
    float average(int length, int array[])
    {
        int sum = 0;
        for (int i = 0; i < length; i++)
        {
            sum += array[i];
        }
        return (float) sum / (float) length;
    }
    

    文字列と配列


    stringタイプのデータはcharタイプのデータの配列です.したがって、string s = "HI!";のようにstringタイプのsが生成されると、図に示すようにメモリに格納される.

    文字列の終わりに空の終わり文字が追加されます.空の終端が必要なのは、stringタイプがメモリに格納するバイトのサイズを決定していないため、文字列の長さもサイズを変更します.したがって、文字列の最後の位置に終端文字として表示され、コンピュータに値を格納するデータのサイズを通知することができる.
    stringタイプの配列を作成し、複数の文字列を格納する場合は、メモリに次の内容が格納されます.

    グローバル変数


    変数を宣言するときに割り当てられる値が固定値(定数)の場合、その値を宣言するときにconstを前にして、コード変更なしのグローバル変数を指定できます.この場合、グローバル変数に貼り付ける名前はすべて大文字でマークされます.
    #include <cs50.h>
    #include <stdio.h>
    
    const int N = 3;
    
    int main(void)
    {
        // 점수 배열 선언 및 값 저장
        int scores[N];
        scores[0] = 72;
        scores[1] = 73;
        scores[2] = 33;
    
        // 평균 점수 출력
        printf("Average: %i\n", (scores[0] + scores[1] + scores[2]) / N);
    }

    コマンドラインパラメータ


    パラメータ値argcを定義し、argv[0]voidではなくargv[0]の場合
    #include <cs50.h>
    #include <stdio.h>
    
    int main(int argc, string argv[])
    {
        if (argc == 2)
        {
            printf("hello, %s\n", argv[1]);
        }
        else
        {
            printf("hello, world\n");
        }
    }
    argcは、主関数が受信する入力の個数であり、argv[]は入力を含む配列である.argv[0]は、基本的にプログラムの名前で格納される.そこで、上記プログラムを「arg.c」コンパイルとして保存した後、./argcを実行し、argcのパラメータ値を1としてhello, worldを出力する.
    逆に、./argc Davidで実行すると、argcが2のプログラム名+David値が追加されます.したがって、hello, Davidが出力される.