ポインタ変数 / ポインタ変数を使う標準函数

日経ソフトウエア 2019年 7 月号, pp.126-132

アドレスを引数に取る函数(scanf_s()函数)

#include <stdio.h>

int main() {
    int int_val;
    float float_val;

    printf("Enter an integer: ");
    scanf_s("%d", &int_val); // 変数のアドレスを引数として渡して、その変数に何かを書き込ませる。
    printf("%d has been entered.\r\n", int_val);

    printf("Enter a float number: ");
    scanf_s("%f", &float_val); // 変数のアドレスを引数として渡して、その変数に何かを書き込ませる。
    printf("%f has been entered.\r\n", float_val);

    return 0;
}

f:id:ti-nspire:20190725104022p:plain

複数の返値を返すのと同じことをする(_splitpath_s()函数)

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

int main(){
    // _splitpath_s()函数でパスを分解してみる。
    char full_path[] = "Z:\\sute\\neko\\sample.txt";

    // 各部を格納するための変数を複数宣言しておく。
    char drive[20];
    char directory[20];
    char file[20];
    char extension[20];

    // 引数として排列を渡しているので結局その排列の先頭の要素のアドレスを渡していることになる。
    _splitpath_s(full_path,
                 drive, 20,
                 directory, 20,
                 file, 20,
                 extension, 20);

    // 一度に複数の変数に書き込まれた。
    printf("drive: %s\r\n", drive);
    printf("directory: %s\r\n", directory);
    printf("file: %s\r\n", file);
    printf("extension: %s\r\n", extension);

    return 0;
}

f:id:ti-nspire:20190725072102p:plain

大きな値を引数として渡さずに済む(strlen()函数)

#include <stdio.h>
#include <string.h>

int main(){
    char s[] = "012345678901234567890123456789012345678901234567890123456789";

    // 排列を引数として渡しているので結局その排列の先頭の要素のアドレスだけが渡される。
    // 排列全体を渡さずに済む。
    int length = strlen(s);
    printf("文字数: %d\r\n", length);
    
    return 0;
}

f:id:ti-nspire:20190725073125p:plain

ハードウェアを直接操作する(memcpy()函数)

#include <iostream>
using namespace std;

#include <stdio.h>
#include <string.h>

int main(){
    int From[] = { 0,1,2,3,4 }; // このデータを
    const int num = sizeof(From) / sizeof(int);
    int To[num]; // ここにコピーする。

    memcpy(To, From, sizeof(From));
    
    // 本当にコピーできたかどうか確かめる。
    for (int element : To) {
        cout << element << ",";
    }
    cout << endl;
    
    return 0;
}

f:id:ti-nspire:20190725075517p:plain

アドレスを返す標準函数(malloc()函数)

#include <iostream>
using namespace std;

#include <stdio.h>
#include <string.h>

int main(){
    int a[] = { 0,10,20,30,40,50,60,70,80,90,100 }; // このデータをどこかにコピーしてみる。
    int num = sizeof(a) / sizeof(int);              // 要素数を取得しておく。
    
    // コピー先のメモリをmalloc()で動的に確保する。
    // ここではint型の値を格納するメモリをnum個分確保する。
    // malloc()は型のない単なるアドレスを返すので、
    // ここでは(int *)でint型のポインタにキャストしてからポインタ変数に格納する。
    int *pt = (int *)malloc(sizeof(int) * num);

    // 動的に確保したアドレスに排列をコピーする。
    memcpy(pt, a, sizeof(a));

    // 本当にコピーできたかどうか確かめる。
    for (int i = 0; i < num; i++) {
        printf("%d, ", *(pt + i)); // "*ポインタ変数"という構文でそのアドレスに存在しているデータが参照できる。
    }
    printf("\r\n");

        
    free(pt); // 必ず解放する。
    
    return 0;
}

f:id:ti-nspire:20190725084720p:plain

函数のアドレスを引数に取る(qsort()函数)

ただ函数名を渡せばその函数のアドレスが渡される。

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

// 比較に使う函数。
int ascend(const void *data1, const void *data2) {
    return *(int *)data1 - *(int *)data2;
}
int descend(const void* data1, const void* data2) {
    return *(int*)data2 - *(int*)data1;
}

int main(){
    int a[] = { 5,9,-8,4,300,6,-7,-5,1 };
    int num = sizeof(a) / sizeof(int);

    qsort(a, num, sizeof(int), ascend); // 引数は(排列名, 要素数, 要素サイズ, 比較に使う函数名)
    for (int i = 0; i < num; i++) {     // 本当にソートできたかどうか確かめる。
        printf("%d,", a[i]);
    }
    printf("\r\n");

    qsort(a, num, sizeof(int), descend); // 引数は(排列名, 要素数, 要素サイズ, 比較に使う函数名)
    for (int i = 0; i < num; i++) {      // 本当にソートできたかどうか確かめる。
        printf("%d,", a[i]);
    }
    printf("\r\n");

    return 0;
}

f:id:ti-nspire:20190725091354p:plain