C言語基礎3

1972年にベル研究所のDennis M. Ritchieが設計
UnixもC言語で書かれている
C++、JavaなどはC言語をモデルに設計されている
ANSI(American National Standards Institute)が標準化してANSI/ISO 9899という規格を作った
日本では、JIS X 3010-1993に翻訳した(JIS C)

コンパイラで機械語に変換する。これをオブジェクトモジュールと言う
複数のオブジェクトモジュールを一つにまとめることをlinkと言う linkを行うのはリンカと言うソフトウェア
プログラムを実行させるには、コンパイルしてリンク処理を実行する必要がある。

test1.c -> test1.obj ↓
test1.c -> test2.obj -> link -> test1.exe

### Unixでの操作
gcc smp1.c // a.outが作成される
gcc -o smp1 smp1.c // -oスイッチでファイル名を指定

unixでは、パス設定がされていない場合、カレントディレクトリのファイルをそのまま実行することはできないが、”./”を付与すれば実行することができる。
カレントディレクトリのパスは以下のようにする
$ PATH=$PATH:$HOME/cwork

品質を高めるためには、errorだけでなく、warningも修正した方が望ましい

### 最初のC

#include <stdio.h>
/*
第一歩
*/
int main(void){
	printf("Helicopter money\n");
	return 0;
}

*.hのファイルをヘッダファイルと呼ぶ
stdio.hは入出力時に必要
int main()は、main関数が返す値が整数値であることを指定 main(void)のvoidは、main()に渡されるデータがないことを指定している
文にはセミコロン(;)を付ける
printf()は標準ライブラリ関数
return 0は、正常終了の時はOSに0を、異常終了の時は1異常を返すのが慣例になっている

#include 
/*
インデント
*/
int main(void){
	int i, sum, mul;

	sum = 0;
	mul = 1;
	for(i=1; i<=5; i++){
		sum = sum + i;
		mul = mul * i;
	}
	printf("sum=%d mul=%d\n", sum, mul);
	return 0;
}

$ ./dev
sum=15 mul=120

### データ出力

int main(void){
	int a;
	double b;

	a = 100;
	b = 12.34567;

	printf("a=%d\n", a);
	printf("a=%f\n", b);
	return 0;
}

### コメント
/* コメント */

### 識別子
- 英文字または_で始まらなければならない
- 長さに制限はないが、31文字(C99は63文字)が識別対象になる
- 予約語を識別子に使うことはできない。例: for
- 大文字と小文字は区別される

### 予約語
auto, double, int, struct, break, else, long, switch, case, enum, register, typedef, char, extern, return, union, const, float, short, unsigned, continue, for, signed, void, default, goto, sizeof, volatile, do, if, static, while

※C99追加
inline, restrict, _Bool, _Complex, _Imaginary

スクリプト言語と比べて、変数代入時の型指定のところがまだとっつきにくいです。

C言語のポインタとメモリ空間2

### メモリの節約
long型は8つのアドレス空間を取るが、ポインタは4つ分のアドレス空間しか取らないため、アドレス空間の節約になる
アドレス(&a)を渡すことを参照渡しという

void f(long *pa){
	*pa += 100;
	printf("%ld\n", *pa);
}


int main(void){

	long a = 1000;
	f(&a);
	return 0;
}

配列でアドレス空間が巨大な場合などは有効

void swap(int *pa, int *pb){
	int tmp;
	tmp = *pa;
	*pa = *pb;
	*pb = tmp; 
}

int main(void){

	int a = 5;
	int b = 10;
	swap(&a, &b);
	printf("a:%d, b:%d\n", a, b);
	return 0;
}

C言語のポインタとメモリ空間1

ポインタとはメモリのアドレスを使って操作をすること
&: アドレス演算子
*: アドレスを示す(間接演算子)
宣言時も*を使う

int main(void){
	int a;
	a = 10;

	int *pa; // *でポインタの宣言
	pa = &a; // &aでaのアドレスを入れる
	printf("%d\n", *pa); //paに入っているアドレスの値を呼び出す

	return 0;
}

$ ./dev
10

なんだこれは? 要は「*」でポインタを宣言した後に、「&」でアドレスを入れて、「*」でアドレスを呼び出してるってことか。
char型でも同じようchar型のポインタを割り当ててできるが、どう活用するかようわからん。

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

	char *ps;
	ps = &s[3];
	printf("%c\n", *ps);

	return 0;
}

C言語基礎2

### 関数
関数: 複数の処理
返り値の型 関数名(引数){
処理;
return
}
C言語は、最初にmain()関数を実行する
main内で使用する関数は、mainよりも上部に書く
プロトタイプ宣言を最上部に記述する

float getMax(float a, float b){
	if(a >= b){
		return a;
	} else {
		return b;
	}
}
void sayHi(void){
	printf("Hi\n");
}
int main(void){
	float result;
	result = getMax(2.3, 5.2);
	printf("%f\n", result);

	sayHi();
	return 0;
}

引数がない場合はvoidをつける

### 三項演算子
返り値 = (条件) ? A : B;

float getMax(float a, float b){
	return (a >= b) ? a : b;
}

### ローカル変数とグローバル変数
※グローバル変数は非推奨

int a = 0;

void f(void){
	a++;
	printf("a:%d\n", a);
}


int main(void){
	f();
	printf("[main]a:%d\n", a);
	return 0;
}

### static
型指定の前に、staticとすると、静的変数となり、値を保持する

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


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

$ ./dev
a:1
a:2
a:3

### 変数
領域を確保する
なお、variables[]={a,b,c} と書くことができる

int main(void){
        // int sales[] = {200, 405, 302};
	int sales[3];
	sales[0] = 200;
	sales[1] = 400;
	sales[2] = 300;

	printf("%d\n", sales[1]);

	return 0;
}

### 文字列
char型の配列、終端は「\0」
char s[] = {‘a’,’b’,’c’,’\0′};
char s[] = “abc”;

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

	printf("%c\n", s[1]);

	return 0;
}

配列の書き方が原始的というか、他の言語でも仕組み上は同じと考えると、面白いです。

C言語基礎1 

### 変数
変数の指定は、intは%d, floatは%f, charは%cと決まっている。

#include <stdio.h>

/*
int -> %d, 
float -> %f, 
char -> %c
*/

int main(void){

	int x = 10;
	float y = 5.2;
	char c = 'A';

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

$ ./dev
x = 10, y = 5.200000, c = A

### 演算
x++ は+1、x–は-1のこと

int main(void){

	int x = 10 % 3;
	x += 5;
	x++;

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

$ ./dev
x = 7

### if
一致の場合は”==”、不一致は”!=”

int main(void){

	int score = 50;
	if(score >= 60){
		printf("nice score\n");
	} else {
		printf("come on\n");
	}
	return 0;
}

$ ./dev
come on

### switch

int main(void){

	int rank = 2;

	switch(rank){
		case 1:
			printf("Gold!\n");
			break;
		case 2:
			printf("Silver!\n");
			break;
		case 3:
			printf("Bronze!\n");
			break;
		default:
			printf("no medal!\n");
			break;
	}
	return 0;
}

### while

int main(void){

	int m = 0;
	while(m < 10){
		printf("m: %d\n", m);
		m++;
	}
	
	return 0;
}

### for

int main(void){

	int m;
	for(m = 0; m < 10; m++){
		if (m == 3){
			continue;
		}
		if (m == 8){
			break;
		}
		printf("m: %d\n", m);
	}

	return 0;
}

$ ./dev
m: 0
m: 1
m: 2
m: 4
m: 5
m: 6
m: 7

改めてC言語を勉強するとなると、C言語が偉大なので、慣れるまで構えてしまいます。

ubuntuでcを実行する

$ cat /etc/os-release
NAME=”Ubuntu”
VERSION=”18.04.4 LTS (Bionic Beaver)”

gccはc言語用のコンパイラ
GNU Compiler Collectionの略

$ gcc –version
gcc (Ubuntu 7.5.0-3ubuntu1~18.04) 7.5.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$ sudo apt-get install build-essential

#include <stdio.h>

int main(void){
	printf("hello world!\n");
	return 0;
}

// コンパイル時に-oオプションを使うことで、実行形式ファイルの名前を指定
$ gcc -o hello hello.c
$ ls
hello hello.c
// ./実行形式ファイルパスで実行
$ ./hello
hello world!

ArduinoとRaspberry Piの違い

### Arduinoとは
AVRマイコン、入出力ポートを備えた基板
C言語風のArduino言語によってコンパイル、デバック等を行う
Arduinoを動かすプログラムをSketch(拡張子は.ino)といい、統合環境はArduino IDE
OSがインストールされていないので、プログラムを送信する必要がある
基本はArduino Uno

Github: Arduino
機能: 温度センサー、気圧センサー、赤外線センサーなどの様々なセンサーをArduinoに接続することで、その値を使って処理可

### Raspberry Piとは
OSが搭載されている
SDカードから、Raspberry Pi専用のLinuxを起動でき、そこからプログラミングができる
Raspberry Pi用のカメラも発売されている
主にPythonやbashでプログラムを書く
無線通信が出来る

### ArduinoとRaspberry Piの違い
Arduinoは、組み込みや電子回路を学びたい人向け
Raspberry Piはソフトウェアを組み合わせたい人向け

両方とも実際にやってみないとわからなそうやな。

RAMの仕組み

### SRAM
フリップフロップを使ったメモリで、SRAMと言われる。消費電力が少なく、動作速度が早い
DRAMと比べて1セルあたりの部品点数が多いため集積度を上げにくい
CPU間近にSRAMに記憶する

### DRAM
大量データの記憶にはDRAMが使用される
コンデンサに蓄えた電荷量によって1ビットを記憶する
1個のコンデンサと1個のMOSFET AD=HにしてQをオンにすると、コンデンサ電圧がデータ線Dに現れるので、電圧H、Lで判定できる
構造、動作原理がSRAMに比較して単純でセル面積も小さいため、大容量メモリに適している

EPROMとflip-flopの構造的な違いは理解しておく必要がありそうだ。

### 半導体の設計
半導体の機能目的を決定する「システム設計」、これを電子回路で実現するための「ロジック設計」、さらに実際にパーツを並べて詳細な回路を検討・設計する「回路設計」、ICチップの中で回路の配置を決定する「レイアウト設計」

集積回路設計

集積回路設計は、主にシリコンを使った半導体上に、トランジスタ、抵抗器、キャパシタといった部品を配置し、それらを金属の配線で接続する。シリコン基板は電導性があるため、個々の部品の絶縁を確保する方法(いわゆる素子分離)が必要とされる。集積回路の素子は一般の部品より非常に小さいため、トランジスタの電力消費、配線抵抗、配線における電流密度といったことに注意を払う必要がある。金属配線におけるエレクトロマイグレーションや極小素子の放電による破損なども考慮される。回路の物理配置も重要であり、性能やノイズの影響、発熱分布、ピン配置といったことと密接に関連する。
半導体製造工程の「前工程」と呼ばれる半導体ウェーハ処理工程では、シリコンウェーハ表面上にトランジスタなどを含む電子回路を高集積で形成
成膜、 パターン転写、エッチング
半導体製造工程の「後工程」と呼ばれる組立工程では、ウェーハから半導体を切り出し、所定の位置に固定・封入して検査

RAMの製造メーカー
Micron

こりゃ凄い世界や。

ROMの電子回路の仕組み

### マスクROM
メモリセルの内部回路の開放と短絡によって1, 0を記憶する
半導体製造工程には写真の感光技術が利用されるが、基板を覆うマスクパターンによってデータが記録される
データ線ADとデータ線Dが短絡しており、AD=HとなるとD=Hとなる
アドレス線を開放状態にすると、AD=HとしてもD=Lのままである H, Lに0と1を割り当てて、1ビットを記憶することができる
バイポーラトランジスタを使ったマスクROMはこの原理で動作させてることができる
実用的には消費電力の少ないMOSFETを半導体スイッチとして用いている
マスクROMはIC製造段階で情報を書き込むのでデータを変更することができない

### PROM
一度だけ書き込み可能なROMをPROMという
ヒーズをトランジスタのエミッタ端子とデータ線の間に設けて、これを溶断するかどうかによってH、Lを記憶する
PROM出荷時には全ヒューズが繋がっている
セルにLを記憶するには、電源電圧Vccを高く設定し、ヒューズが溶断されるとLが記憶される
ヒューズ以外にもダイオードを挿入し、pn接合を破壊・短絡してH, Lを表す方法もある

### EPROM
データの正気と再書き込み可能なROMをEPROMという
データの消去に紫外線を使うUV-EPROMと電圧を使うEEPROMがある
装置固有の設定データや利用者情報などの記憶、書き換え頻度の少ない用途に適している

– 書き込み方法
p型半導体基板上にn型半導体を二つ設け、これに電極ドレイン(D)とソース(S)をつける
更にドレイン・ソース間に絶縁層を設け、その上にゲート電極(G)をつける
n型半導体は自由電子が含まれた物質で自由電子の流れが電流
p型半導体は自由電子を含んでいない
ゲートに電圧を加えない状態では電流は流れない(nMOSがオフ)
ゲートに電圧を加えるとゲート、ソース間はコンデンサとして働き、正の電荷がゲート電極に蓄えられる
-> nチャンネルを作り、半導体スイッチとなる Vgs > Vthでオン、Vgs < Vthでオフ FGの帯電量によってMOSFETのオンオフを決定でき、ROMとして1ビットを記憶させることができる 一度入り込んだ負電荷は電源を切っても消えないので、半永久的にこの状態を保持できる - データ消去 UV-FPROMは紫外線をFGゲートに照射させることで内部電子のエネルギーを増大させ、FGゲートから放出させる このため、IC上部には紫外線照射窓がある EEPROMは電圧によってFGゲートの電子を放出させる FGゲートの帯電動作と逆 ゲート電圧を0とし、ドレイン電圧を高く設定するとFGゲートの電子がドレイン側に逃げ出して0となる EEPROMは電圧制御によって1ビット単位で行うことができるが、セルにMOSFETが追加されるため面積が大きくなり大容量化が難しくなる ### フラッシュメモリ メモリセルを幾つかの集合に分割し、消去をブロック単位で行うようにした セルの消去用トランジスタをなくすことでセル面積を抑え、大容量化を図っている 電源を切ってもデータが保持できるので応用は急速に広がっている マザーボードのBIOS、スマホのストレージはフラッシュメモリー UBS, SSDなどもNAND型のフラッシュメモリー フラッシュメモリはTranscend(台湾)、Silicon-Power(ドイツ)、ELECOM、I-O DATA、SanDisk、BUFFALO、GREEN HOUSEなどが生産 EPROMの仕組みは、p型半導体と、s,dのn型半導体に挟まれた絶縁体のゲートでできてるのね。 1ビットでこの仕組みが必要なのに、500GBのSSDって、どれだけpnとデータ線、アドレス線をどうやって少量化して詰め込んでるんやろうか、全く想像が付かない。CPUもそうだけど。 ICメモリの仕組みがわかったところで、アプリケーションの品質には直接は影響はないけど、興味深いところではある。

ICメモリ

記憶装置には大きく分けて外部記憶装置と内部記憶装置がある

### 外部記憶装置
外部記憶装置にはハードディスク、CD、DVDなど
-> 機械的な駆動部分が存在するため読み書き速度が遅い

### 内部記憶装置
ICメモリは小型の回路部品であり、基板内部に組み込まれる為、内部記憶装置と言われる
記憶容量では劣るが、機械駆動部が少ない為高速
CPU周りの高速処理にICメモリが使われている

### ICメモリの内部構造
大量の2値情報を記憶する
IC内部の最小記憶単位をセルと良い、通常は1ビットを記憶する 
セルは平面上に配列されており、アクセスするためにアドレス(固有の識別番号)が使われている
行アドレスと列アドレスがあり、アドレス線の電圧がH(アクティブ)になり、列アドレスが入力されると、特定のデータ線が選ばれ、セルが読み書きの対象となる
読み書きの制御信号R/WがHになると、記憶データが出力され、Lになると記憶される

### ICメモリの分類
ROM: 読み込み専用、電源を切っても内容保持 R/W制御信号は取り除かれ、出力のみ
RAM: 読み込み書き込み自由、電源を切ると内容も消える R/W信号に応じて双方向通信に対応

メモリっていうと、文字データ、画像データなどを記憶しているように思っていたが、実際には0、1の2値データを持ってるだけなのね。えらい勘違いをしていたみたいだ。