出席票フォーム (授業内容に関するクイズもあります)
スライドPDF
スライドPDF ノート付き
【参考】プログラムの計算量、オーダー表記 O( ) の求め方のまとめ
授業で紹介した関数ポインタですが、「printfで出力すること」、つまり
#include <stdio.h>
int main(){
printf("%p\n",(void*)main);
return 0;
}
はISO C規格では厳密には許可されていません。
/vscode# gcc -pedantic main.c;
main.c: In function 'main':
main.c:3:16: warning: ISO C forbids conversion of function pointer to object pointer type [-Wpedantic]
printf("%p\n",(void*)main);
^
(-pedantic: gcc の言語拡張機能をすべて無効にするオプション。)
書式指定子%pは(void*)をとりますが、ISO Cでは関数へのポインタから(void*)へのキャストは許可されないためです。
苦肉の策はバイト毎に表示すること:
https://stackoverflow.com/questions/2741683/how-to-format-a-function-pointer
#include <stdio.h>int main() {
int (*funcptr)() = main;
unsigned char *p = (unsigned char *)&funcptr;
size_t i; for (i = 0; i < sizeof funcptr; i++)
{
printf("%02x ", p[i]);
}
putchar('\n'); return 0;
}
このコードは
# gcc -pedantic main.c;./a.out;
fa 06 20 ec 88 7f 00 00
と動作します。
ではなぜそもそも
> ISO C forbids conversion of function pointer to object pointer type
とされているのか。探せた限りではここの議論が詳しいです:
言ってしまえば、
オブジェクトのアドレスと関数のアドレスの長さが異なるアーキテクチャをサポートするために、ISO C規格は変換を定義していない。
例:MS-DOSでは
sizeof(void *) > sizeof(void(*)())
が起こりえる。
さらに言えば、オブジェクトのメモリ空間と関数のメモリ空間が分かれているアーキテクチャでは、たとえアドレス長が同じだとしても意味をなさないので、変換を定義できない。
計算量が最悪となる条件は、ソートアルゴリズムごとで違うことがあります。例えば、バブルソートの場合はデータが逆順に整列済みの場合ですが、クイックソートの場合は最初の分割時に左右のどちらかに極端にデータが寄る場合です。
おすすめ:ソートアルゴリズムの可視化&音声化動画