過程が大事

学んだことを適当にアウトプットします

Mikan OSを自作してみる #11

今回やった内容

サンプルコードを書き、コメントアウトで解説を加える

(コードその1)
データ型、文字列

# include <stdio.h> // 標準入出力を行うためのヘッダーファイルを取り込む
/*
データ型
int(整数)  %d
fload(実数:小数点を含む) $f
char(1文字) %c

文字列はchar型の配列で最後の文字は「\0」となっている
char s[] = "abc";
char t[4] = "abc";

printf(t[1]) 
出力:b
 
*/

int main(void) {

    int x  = 10;
    float y = 10.6; 
    char c = 'A'; // ' 'で囲まないといけない
    
    printf("hello world!\n");

    printf("x = %d, y = %f, c =  %c\n", x, y, c);
    return 0;
    
}

(シェル)

// gccコマンドを使ってコンパイルし、実行ファイルhelloを作成する  
$ gcc hello hello.c   
$ ./hello
hello world!
x = 10, y = 10.600000, c =  A

(コードその2)
条件分岐

# include <stdio.h> // 標準入出力を行うためのヘッダーファイルを取り込む

/*
条件分岐(if , else if, else)
*/

int main(void) {

    int score = 55;
    
    if (score >= 60) {
        printf("Pass!\n");
    } else if (score >= 50) {
        printf("challenge again!\n");
    } else {
        printf("Out!\n");
    }
    return 0;
}

(シェル)

$ ./hello.c
challenge again!

(コードその3)
for ループ

# include <stdio.h> // 標準入出力を行うためのヘッダーファイルを取り込む

/*
ループ (for)
continue; 一回スキップ
break; ループを抜ける
*/

int main(void) {
    int m;
    for (m = 0; m < 10; m++) {
        if (m == 3) {
            continue; // mが3の時printを行わない
        }
        printf("m: %d\n" , m);
    }
    return 0;
}

(シェル)

$./hello.c
m: 0
m: 1
m: 2
m: 4
m: 5
m: 6
m: 7
m: 8
m: 9

(コードその4)
プロトタイプ宣言

# include <stdio.h> // 標準入出力を行うためのヘッダーファイルを取り込む

/*
関数

プロトタイプ宣言:先に float getMax(float a, float b); とプログラムの最初に関数名だけ定義すること
プロトタイプ宣言された関数はmainより後ろでも関数の実行内容を決めることができる
*/

float getMax(float a , float b) {
    if (a > b) {
        return a;
    } else {
        return b;
    }
}

// 引数も返り値もない場合はvoidにする
void say_Hi(void){
    printf("hi!\n");
}

// main()はC言語で最初に実行される関数でmain()は整数の返り値を持ち、正常に処理が終了すると0が返される
int main(void){
    float result;
    result = getMax(2.5 , 5.5);
    printf("%f\n", result);

         say_Hi();

         return 0;
}

(シェル)

./hello
5.500000
hi!

(コードその5)   三項演算子

# include <stdio.h> // 標準入出力を行うためのヘッダーファイルを取り込む

/*
三項演算子
if () {

} else {

}

これを1行にすると
返り値 = (条件) ? A : B;
*/

float getMax(float a , float b) {
/*  if (a > b) {
        return a;
    } else {
        return b;
    }
*/
    return (a > b) ? a : b;
}
void say_Hi(void){
    printf("hi!\n");
}

int main(void){
    float result;
    result = getMax(2.5 , 5.5);
    printf("%f\n", result);
    
    say_Hi();
    return 0;
}

実行結果は同じ

(コードその6)
変数

# include <stdio.h> // 標準入出力を行うためのヘッダーファイルを取り込む

/*
変数について
static 変数 : staticは静的変数のことで定義された変数はプログラム終了まで値を保持する。
*/

void f(void) {
    static int a = 0; // 静的変数
    a ++;
    printf("a:%d\n", a);
}


int main(void){
    
    f();
    f();
    f();
    
    return 0;
}

(シェル)

~/Desktop/c_lessons $./a.out    
a:1
a:2
a:3

(コードその7)
ポインタ

# include <stdio.h> // 標準入出力を行うためのヘッダーファイルを取り込む

/*
ポインタ:アドレスを格納するための変数
宣言:int a
値:*a
アドレス:a

ポインタを使うことでメモリの節約になる
(例)ポインタを使用しない場合は、変数のコピーをすることになりその変数分の領域を消費するが、ポインタを使うことでアドレスは4Biteとバイト数が少ないため使用領域を少なくすることができる。
メモリ(記憶領域)

&:アドレス演算子
* :間接演算子
*/

int main(void){
    
    int a;
    a = 10;
    
    int* pa;  // ポインタ変数の定義
    pa = &a; // paにaのアドレスを代入
    printf("*pa:%d\n", *pa); // アドレスを使ってアドレスが指し示す値(アドレスの中身)を表示
    printf("pa:%p\n", pa);
    
    return 0;
}

(シェル)

~/Desktop/c_lessons $./a.out    
*pa:10
pa:0x16bd1f7b8

(コードその8)
ポインタの値渡し・参照渡し

# include <stdio.h> // 標準入出力を行うためのヘッダーファイルを取り込む

/*
ポインタ

値渡し:値をそのまま渡す(コピーする)
参照渡し:アドレスを渡す
*/

void swap(int *pa, int * pb) {
// 戻り値は1つしか返せないがポインタを使用することで入れ替えを実現できる
    int tmp;
    tmp = *pa;
    *pa = *pb;
    *pb = tmp;
}

int main(void){
    
    int a = 10;
    int b = 5;
    printf("before | a:%d,b:%d\n", a,b);
    swap(&a, &b); // aとbのアドレスを入れ替える
    printf("after | a:%d, b:%d\n", a, b);
    
    return 0;
}

(シェル)

~/Desktop/c_lessons $./a.out    
before | a:10,b:5
after | a:5, b:10