C言語の変数とデータ型

### 変数の宣言
int a, b;
a = 10;
a = 20 + 30; // a=50
b = a; // b=50
b = a + 100; // b=150
b = b + 200; // b=350;
※const変数は値を参照できるが変更はできない

### データ型
char(1byte): -128〜127
unsigned char(1byte): 0〜255
int(4byte): -2147483648〜2147483648
unsigned int(4byte): 0〜4294967295
short int(2byte): -32768〜32767
unsigned short int(2byte): 0〜65535
long int(4byte): -214783648〜214783647
unsigned long int(4byte): 0〜4294967295
float(4byte): 10^-37〜10^38
double(8byte): 10^-307〜10^308
long double: doubleと同じかそれより大きい
※バイトはメモリ内に確保されるメモリサイズ
※unsignedはマイナスの符号なしのデータ表現
※signed, unsigned, short, longが先行する場合はintを省略できる
※初級ではint, char, doubleがよく使用される

int main(void){
	printf("%d\n", sizeof(char));
	printf("%d\n", sizeof(int));
	return 0;
}

$ ./dev
1
4

### データ型の性格
– char型は1byteだが、int型は4byte, char型の配列を文字列型と称することがある
– double, floatなどの浮動小数点の値をint型に入れようとすると、小数点以下が切り離される ※四捨五入はなし

### 整数値のオーバーフロー
2147483647に、1をプラスすると、オーバーフローして、-2147483648になる。

int main(void){
	int a;
	a = 2147483647;
	a = a + 3;
	printf("%d\n", a);
	return 0;
}

### floatとdoubleの使い分け
浮動小数点数は通常double型が使われる。sin, cos, tanなどは全てdouble型を返す
floatは、大量のfloat型データを使用する際など、メモリ領域を節約したい時に有効

### 配列
int dt[10];
dt[10] = 100; // 不正、dt[10]はdt[0]〜dt[9]

### 多次元配列
int a[2][3]; // 二次元配列、配列長3の配列を2組用意した構成
int b[5][6][7]; // 三次元配列
※二次元配列以外を使うのは稀

int main(void){
	int dt[3][5];

	dt[0][0] = 11;
	dt[1][3] = 55;
	dt[2][4] = 66;

	printf("%d\n", dt[0][0]);
	printf("%d\n", dt[1][3]);
	printf("%d\n", dt[2][4]);
	return 0;
}

多次元配列や行列には慣れないといけませんね。

C言語基礎4

### 整数定数
数値や文字列を直接表現したものを定数(リテラル)と言う。
– 整数定数
 L 8進定数 0~8
 L 10進定数 0~9
 L 16進定数 0〜9, A~F ex.0x1a, 0XAB03
 L unsigned型定数 uまたはU ex.12800U
 L long型定数 lまたはL ex.0L

### 浮動小数点型定数
小数点形式と指数形式がある。デフォルトはdoubleで、接尾語を付けることでfloat型やlong double型になる。
– 整数定数
 L 小数点形式 double型 12.345
 L 指数形式 eまたはE 3.456E2(=345.6), 6.78e-3(=0.00678)
 L float型 fまたはFを末尾に付ける 12.34F
 L long, double型 lまたはLを付ける 100.23L 5.67e-21

int main(void){
	int n8, n10, n16;
	double f1, f2;

	n8 = 0100;
	n10 = 100;
	n16 = 0x100;
	f1 = 1.234;
	f2 = 5.678e2;

	printf("n8=%d\n", n8);
	printf("n10=%d\n", n10);
	printf("n16=%d\n", n16);
	printf("f1=%f\n", f1);
	printf("f2=%f\n", f2);
	return 0;
}

### 文字定数と文字列リテラル
文字定数はそれぞれの文字が持っている文字コードを表現するもの
int c;
c = ‘A’;
c = 65 ….Aに対応する文字コード

二重引用符合で囲ったものを文字列リテラルと言う
“ABCDEF”
“C language”

### その他の定数機能
¥a : alert
¥b : back space
¥f : form feed(改ページ)
¥n : new line
¥r : carriage return(復帰)
¥t : horizontal tab(水平タブ)
¥v : vertical tab(垂直タブ)
¥’ : 文字定数対策
¥” : 文字列定数対策
¥? : 三連文字対策
¥ooo : 8進数 octal
¥xhh : 16進数 hexadecimal

単一文字コードで用いる時は’¥n’と囲むが、文字列リテラルに埋め込む時は、”AAAA¥tBBBB¥n”とそのまま書く
”’ … エラー
‘¥” … 正常

### 記号定数
任意のデータを意味ある名前で扱うようにするための記号定数
e.g.
#define MAXDATA 3715

### const付定数
宣言の時に値を設定し、それ以降は値の変更ができない
e.g.
const int a = 10;

8進数が2進数の3乗で、電子回路の処理上、都合がいいのはわかるが、8進数をプログラム処理場で使うイメージがわかないな。

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言語が偉大なので、慣れるまで構えてしまいます。