6/18(木)〜6/23(火) の学習ログです(主にC言語)
こんにちは、安藤です。
いつもありがとうございます。
私の学習ログを残しています。
2020.6.18(木)
●マクロ機能
*不変の値の取り扱い
・初めから終わりまで不変の値実行中は変化しない値を定数と呼ぶ。
・数値に名前をつける
C言語には、数値に名前をつける方法が用意されている。それが、#define擬似命令。#define 名前 数値
#define擬似命令では、文の終わりに;をつけてはいけない。
この文はプログラムの先頭に置くのが一般的。
名前には変数と同じ文字が使えるが、大文字のアルファベットが一般的。
・文字列に名前をつける
#define擬似命令では、数値だけでなく、文字列にも名前をつけられる。
*その他の方法による定数
・const定数
const定数とは、値を変更できない変数のこと。
変数を宣言するとき、その先頭でconstを指定すると、その変数は宣言時に代入された初期値を変更することができなくなる。
const定数は、定数として使う限りは#defineとほとんど同じ。
一般的には、定数を宣言する時には#defineを使用することがほとんどだが、特定の関数の中だけで使用する定数を宣言したい時などには便利。
・定数を配列の要素数にする
C言語では、const定数を配列の要素数にできないけど、C++やC99では可能になっている。なお、#define擬似命令ならどちらでも可能。
・constの使い道
constは、他に関数の引数の型として使われることもある。
これは、配列を渡す時に、その値を変更させないため。
・enum(エナム)定数
C言語には、#defineやconstの他に、enum定数がある。
enum { 名前, 名前, 名前};
enum定数では、数値を指定する必要はなく(指定することもできる)、名前だけで自動的に数値がつけられるので、大量の定数を宣言する場合に便利。
自動的に数値がつけられるのでは、定数として利用できないようにも思えるが、enum定数は、主にフラグ定数として使用される。
enumは整数値しか使えない。文字列も使えない。
実数値を扱う場合には、#defineかconst定数にするしかない。
※最後の,(カンマ)
enumの名前の後につける,は、正式には最後の名前にはつけないが、実際にはつけてもほとんどの場合には問題なく動作する。ただし、組み込み向けコンパイラなどでは動かないこともあるようだ。
・数値指定enum
enum定数では、数値を省略できるが、必要であれば指定することもできる。
数値を省略した場合、1番先頭の名前を0として、以後は1ずつ増やした値がつけられる。どこかで数値を指定した場合、そこは指定した数値、以後は1ずつ増やした値になる。
<読書>
・これからのテレワーク 著者:片桐あい
・フルライフ 著者:石川善樹
・「仕事ができる」とはどういうことか? 著:楠木建、山口周
・大きな嘘の木の下で 著:田中修治
・うまくやる 熊野森人 著・エンジェル投資家とは何か
・大前研一 2020年の世界
2020.6.19(金)
◎C言語(web記事「苦しんで覚えるC言語」)
●マクロ機能
*簡易的な関数の実現
・#define擬似命令のこうどな機能
#define擬似命令による定数は、単なる置き換えによって実現されているが、これを利用すると特殊な処理を行わせることも可能。
関数も置き換えることができる。
乱用すると、プログラムがわかりにくくなるけど、この機能は知っておく必要がある。
・マクロという簡易関数
#define擬似命令で簡単に関数を作ることが可能。
名前の後に()で文字を指定すると、以後の置き換える内容で同じアルファベットの部分を置き換えることができる。
この機能は簡易的な関数の変わりに使われており、マクロと呼ばれている。
マクロの使い方は普通の関数と全く同じだが、仕組みは大きく異なる。
関数の場合、その実態は1箇所にあり、必要な時に呼び出されて使われる。
マクロでは、使用している場所のプログラムそれ自体が置き換わり、呼び出しなどの作業が必要ないため若干高速になる。
しかし、マクロを使う場所全てが置き換わるので、あまり巨大なマクロを作ると、その為にプログラムのサイズが極端に大きくなることもある。
そのため、一般的には、マクロは決まりきった数式などに利用される。
・副作用の恐怖
マクロは手軽で便利だが、使い方を間違えると思わぬ現象に遭遇する。
マクロは、単なる置き換え命令でしかないため、置き換えでエラーが生じることがある。
マクロの副作用と呼ぶ。
解決方法は2つあり、1つは、呼び出し時いカッコをつけること。
もう1つは、マクロの方にカッコをつけること。
うっかり忘れると副作用が生じる。なので数式などは普通の関数を使うことが一般的。
◎今日のビジネス書の読書
・不平等と再分配の経済学 著者:トマ・ピケティ
・テクノロジー・スタートアップが未来を創る 著:鎌田富久
・WE ARE LONELY, BUT NOT ALONE. 著:佐渡島庸平
・教養としてのコンピューターサイエンス講義 著:ブライアン・カーニハン
・武器としての「」資本論 著:白井聡
・チフスのメアリー 病魔という悪の物語 著:金森修
・ネガティブ・ケイパビリティ 著:帚木蓬生
・人工知能と銀行経営 著:大久保豊ほか4名
・文系AI人材になる 著:野口竜司
2020.6.20(土)
◎C言語(web記事「苦しんで覚えるC言語」)
●動的配列
*配列を自由自在に作る
・配列の欠点
配列の最大の欠点は、要素数をプログラム中で変更できないこと。
配列を宣言する時に、要素数を定数で直接指定するしかない。
実行中にユーザーに入力してもらい、その値を利用するようなことはできない。
※変更できる環境
GCCというコンパイラでは独自の拡張により、要素数をプログラム中で変更できるようになっている。
また、C99という新しいC言語でも同様の機能が追加されている。C++ではできない。
要素数を変更できないことは、様々な目的で動作するプログラムを作るのに不便。
例えば、会社の社員の給料を管理するソフトを作る場合、社員の給料を記憶する配列は社員の人数分以上必要になる。ところが、世の中には、社員数人の会社から、数千人の会社まで様々。
もし、要素数を10個とすると、11人以上の会社では使えないし、逆に要素数を1万にすると、10人の会社では残りの9990個が無駄になる。
その無駄な分にもメモリを使用するので、巨大なメモリの無駄となる。
このように、配列の要素数は自由に変更することができないため、メモリを有効利用することが難しく、実用性に欠ける。
◎今日のビジネス関連の読書
・復活の日 著:小松左京
・ビジネスチャット時短革命 メールは時間泥棒 著:越川慎司
・「数字で考える」は武器になる 著:中尾隆一郎
・2060年未来創造の白地図 著:川口伸明
・ぜんぶ、すてれば 著:中野善壽
・ゼロからはじめる力 著:堀江貴文
・教養として知りたい日本酒 著:八木・ボン・秀峰
・勉強の哲学 来るべきバカのために 著:千葉雅也
2020.6.21(日)
●動的配列*配列を自由自在に作る
・メモリの確保配列は自由に要素数を変更できないため、不便である。そのため、自由に配列を作る、malloc(エムアロック)関数が用意されている。
malloc関数を使うには、<stdlib.h>を#includeする必要がある。
ポインタ変数=malloc(必要なメモリのバイトサイズ);
メモリを確保できなかった場合はNULLが返る。
返されるポインタ変数には、確保された配列の先頭アドレスが代入されるので、
これに[ ]演算子を使用すれば配列と同様に使うことができる。
malloc関数で指定できるのは、バイト単位のサイズなので、任意の要素数の配列を確保するには、sizeof演算子を使う。
malloc関数で確保したメモリを、ヒープと呼ぶことがある。
ヒープに確保された配列を、動的配列と呼ぶことがある。
メモリ確保に失敗するとNULLが返される。これをそのままに使用すると当然強制終了するので、malloc関数の戻り値は必ずチェックする必要がある。
わずかなメモリ確保に失敗した場合も、システム全体が深刻なメモリ不足で今にもフリーズ、という状態なので、強制終了以外の対策はない。
ヒープ…長期的に使用される大きなサイズのメモリを格納する領域。
動的配列…malloc関数などを使用してプログラムの実行中に用意された任意のサイズの配列。
malloc関数によって確保されたメモリは、プログラムが終了するまで残るが、そのメモリが不要になった場合、free関数を使って解放する。これを忘れると無駄なメモリが残り続けることになるため、malloc関数を使ったら必ずfree関数を呼び出すこと。
free関数は使い方は、free(ポインタ変数);
・終了時のfree関数free関数を呼ばなくても良い場合がある。
プログラムが終了する直前では、free関数を使わなくても、プログラム終了と同時にOSがメモリを解放する。ただ、free関数を常に呼び出す癖はつけておくこと。
・だんだん動作が遅くなる原因
長時間コンピュータを使っているうちに、だんだん動作が遅くなってきて、再起動することになる、というあれ。
実はあの現象の原因がまさに「free関数の呼び出し忘れ」。
大規模なプログラムでは、malloc関数をたくさん使うことになるので、常に正しくfree関数を呼び出すのは困難で、市販されてて世界中で使われているアプリケーションでもどこかで呼び出し忘れがきっとある。
この呼び出し忘れによってメモリが無駄になることを「メモリリーク」という。
次のプログラムは、int型の要素数10個の配列を動的に確保する。
#include <stdio.h>
#include <stdlib.h>
int main() {
int i ; int *heap;
heap = (int*)malloc(sizeof(int)*10);
if(heap == NULL)exit(0);
for(I = 0; i < 10; i++ ) {
heap[ i ] = i ;
}
printf(“%d\n”, heap[5] );
free(heap);
return 0;}
sizeof(int)によって、int型変数1つのバイト単位のサイズが求められるので、それを10倍することで、int型変数10個分のメモリを確保している。
malloc関数が返すアドレスは、void型のポインタ。この型は、どんなポインタ変数にも代入できるという型なので、本当は(int*)にキャストする必要はないのだが、C++コンパイラではキャストしないとエラーが出る。
メモリ確保に失敗した場合は、exit関数を呼び出して強制終了させる。
exit関数は、プログラムを強制終了させる関数。
exit関数を使うには、#include <stdlib.h>する必要がある。
エラーによる場合の強制終了は、abort関数を使うこともある。
確保した配列を使い終えたら、free関数で解放する。
・malloc関数の実態malloc関数は、好きなサイズの動的配列を作ることができるので、便利だが、その仕組みは、メモリにマークをつけているだけ。
これは、冷蔵庫に入っているスイーツに名前を書いておくのと同じこと。
家族みんながその名前に従い、他人のスイーツを食べなければいいが、勘違いによって誰かに食べられてしまうこともある。このくらいのこと。
malloc関数にも似たようなところがあって上手に使うのは難しい。
従って、できるだけ、普通の配列を使用して、どうしても必要ってところだけmalloc関数を使う方がいい。
◎今日のビジネス関連の読書
・ワイルドサイドをほっつき歩け ハマータウンのおっさんたち 著:ブレイディみかこ
・志村流 著:志村けん
・交渉力 著:橋下徹
2020.6.22(月)
●動的配列
*配列を自由自在に作る
・動的配列の要素数を拡大する
malloc関数によって要素数の調整ができる、動的配列を作ることができる。
けれど、これでは、「配列の要素数の変更ができない」という問題を完全に解決できたとは言えない。
そこで、要素数を変更する、realloc(リアロック)関数というものが用意されている。
新しいポインタ変数=realloc(以前のポインタ変数,必要なメモリのバイトサイズ);
以前のポインタ変数には、malloc関数で確保したメモリのアドレスを指定する。
realloc関数は、中身を維持したまま新しいサイズのメモリを確保する。
新しいポインタ変数には、拡張されたメモリのアドレスが返されるが、特別な理由がなければ以前のポインタ変数と同じ変数を指定できる。
次のプログラムは、realloc関数で動的配列の要素数を変更する。
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int *heap;
heap = (int*)malloc(sizeof(int)*10);
heap = (int*)realloc(heap,sizeof(int)*100);
free(heap);
return 0;
}
realloc関数で、要素数を10個から100個に増加している。
・呼び出し回数を減らそう
realloc関数を何回も呼び出すメモリが散らかっていく。
このような状態をフラグメンテーションと呼び、不安定になる。
はじめのmaoolc関数である程度大きめに確保しておき、realloc関数を呼び出す場合も、1回で大きめに確保するべき。
◎今日のビジネス関連の読書
・新型コロナウィルスの真実 著:岩田健太郎
・日本でいちばん大切にしたい会社7 著:坂本光司
・片づけられない自分がいますぐ変わる本 著:大嶋信頼
・明日の自分が確実に変わる10分読書 著:吉田裕子
・5Gビジネス 著:亀井卓也
・P&G「勝つために戦う」戦略 著:A・G・ラフリー
今回は以上です。
それではまた次回。