ファイル

Posted コメントするカテゴリー: C

ファイルの種類は大きく、テキストファイルとバイナリファイルがある。

テキストファイルは、主に文字データを取り扱う。
バイナリファイルは、主に音声や画像データを取り扱う。

ファイル処理の基本は、ファイルポインタを宣言して、ファイルの読み書きの場所を決定してから処理を行う。

FILE *fp; //ポインタとして宣言する

ファイルを扱うときは次の順序で行う。
①ファイルを開く
②読み書きを行う
③ファイルを閉じる

ファイルを開く場合は次のように書く。

FILE *fp;
fp = fopen("a.txt", "r");

三つめの引数はオープンモードで、C言語では次のようになります。

モード動作ファイルがあるときファイルがないとき
"r"読み出し専用正常エラー(NULL返却)
"w"書き込み専用サイズを 0 にする(上書き)新規作成
"a"追加書き込み専用最後に追加する新規作成
"r+"読み込みと書き込み正常エラー(NULL返却)
"w+"書き込みと読み込みサイズを 0 にする(上書き)新規作成
"a+"読み込みと追加書き込み最後に追加する新規作成

ファイルのオープンに成功すると、ファイルポインタを返す。
どのモードで開くかにより、前のファイルの扱いや、ファイルポインタが最初に示す位置は異なる。
オープンに失敗すると、fopen関数はNULLを返すので、NULLかどうかを判定して次の処理を決定すると良い。

ファイルを閉じるにはfclose()関数を使う。

fclose(fp);

ファイルの入出力

Posted コメントするカテゴリー: C

ファイルにはテキストファイルとバイナリファイルという種類がある。
テキストファイルは人間が読めるもので、バイナリファイルは(一般的には)解読ができない。

C言語はファイル名を直接読み込むわけではなくファイルポインタと呼ばれるものでファイルを置き換えてアクセスする。

ファイルポインタはファイルのどの部分を読み書きするか。という情報も含んでいる。

■ファイルポインタを使ったファイルの読み書きの順番

以下のような順番でファイルを操作する

①ファイルポインタの宣言
②対象のファイルを開く
③ファイルポインタを得る
④ファイルポインタを通して読み書きする
⑤操作が終わり、ファイルを閉じる

テキストファイルとバイナリファイルでは、ファイル操作時の関数の種類や引数が違うので、注意が必要。

C言語では、キーボードから入力されたデータを扱うことがある。この時に入力される値を読み込む部分を「入力部分」と呼ぶ。
キーボードから入力される値と、ファイルから読み込む値も同様に考えられる。
キーボード入力やファイルから読み込むために使うファイルを標準入出力ファイルという。
プログラムの実行開始と同時に開かれていて、いつでも使うことができる。

main関数

Posted コメントするカテゴリー: C

main関数はプログラム開始点(エントリポイント)となる特殊な関数。

以下にmain関数の書き方の例を書く。

//引数と返り値を省略
main ()
{

}

//引数を省略、返り値はvoid
void main()
{

}

//引数を省略、返り値はint
int main()
{
	return 0;
}

//引数と戻り値(int)を指定(これが基本パターンになる)
int main(int argc, char *argv[])
{
	return 0;
}

コマンドライン引数の取得
コマンドラインから引数をつけてプログラムを実行する。
その際、main関数の引数にはプログラム自身のファイル名とコマンドライン引数の情報が入る

引数         格納する情報
argc         配列argvの大きさ(コマンドライン引数の数+1)
argv[0]      プログラムファイルのパスの文字列へのポインタ
argv[1]      1番目のコマンドライン引数の文字列へのポインタ
argv[2]      2番目のコマンドライン引数の文字列へのポインタ

使用例は次のような形になる

aaaa.exe val1 val2 val3

引数argv[0]には「aaaa.exe」が入る。
argv[1]には「val1\n」、argv[2]には「val2\n」、argv[3]には「val3\n」、がそれぞれ入る

引数の受け渡し(値渡しと参照渡し)

Posted コメントするカテゴリー: C

関数を使う場合、呼び出し側と定義側の両方で引数を指定する。
呼び出し側を「実引数」といい、定義側を「仮引数」と呼ぶ。

■値渡しと参照渡し
引数を書く場合に、実引数と仮引数をまったく別もの(違うアドレス)として扱う場合は値渡しを行う。

値渡しの例

#include <stdio.h>

void addnum(int, int); //プロトタイプ宣言

void main()
{
	int a = 2, b = 3;
	int n;
	n = addnum(a, b); //関数の呼び出し(値渡し)
	printf("%d\n", n); //結果「2」となる
}

void addnum(int x, int y)
{
	int temp;
	temp = x;
	x = y;
	y = temp;
}

対して、実引数と仮引数を同じもの(同一アドレス)として扱う場合は参照渡しを行う。

参照渡しの例

#include <stdio.h>

void addnum(int *, int *); //プロトタイプ宣言

void main()
{
	int a = 2, b = 3;
	int n;
	addnum(&a, &b); //関数の呼び出し
	printf("%d\n", n);
}

void addnum(int *x, int *y)
{
	int temp;
	temp = *x;
	*x = *y;
	*y = temp; //全て参照として処理している
	
	//結果「1970678749」になる
}

プロトタイプ

Posted コメントするカテゴリー: C

■関数のプロトタイプを宣言する

これまでは「関数の定義」→「関数の呼び出し」の順番でコーディングしていた。
これを逆に行うとコンパイルエラーになる。

コンパイルエラーにならないように関数を使いたい場合は、プロトタイプという関数のひな型を呼び出し前に宣言しておく。

プロトタイプ宣言は関数の仕様にあたる部分だけを抜き出したもの。

#include <stdio.h>

int addnum(int, int); //プロトタイプ宣言

void main()
{
	int n;
	n = addnum(2, 3); //関数の呼び出し
	printf("%d\n", n);
}

int addnum(int a, int b)
{
	int x;
	x = a + b;
	return x;
}

ブログ内の「関数の定義」の例では、関数を書く順番でエラーになった書き方が、プロトタイプを宣言することによってエラーではなくなった。

変数のスコープ

Posted コメントするカテゴリー: C

関数の中で宣言した変数のことをローカル変数という。
ローカル変数を参照できる範囲は、定義した関数の中に限られる。

このような変数の有効範囲のことをスコープという。

#include <stdio.h>

void functionA(void)
{
	int y;
	return y;
}

void main()
{
	int x;
	x = 3;
	y = 4; //この時点で、変数が参照できずにエラーになる
	
}

プログラム全体で参照できる変数のことをグローバル変数といい、
どの関数の中からも参照ができる。

#include <stdio.h>

int z;

void functionA(void)
{
	int y;
	z = 2; //代入はするが、このプログラム内では関数が呼ばれないので、値の変化はなし
	return y;
}

void main()
{
	int x;
	x = 3;
	z = 5; //グローバル変数への代入
	
	//y = 4; //この時点で、変数が参照できずにエラーになる
	
}

※上記プログラムは、最終的に結果を出力しないので、なにもおきない。

関数の呼び出し

Posted コメントするカテゴリー: C

定義した関数を呼び出すには、次のように書く。

#include <stdio.h>

void dispnum(int a)
{
	printf("%d\n", a);
}

void main()
{
	dispnum(5);
	dispnum(10);
	dispnum(15);
}

戻り値を利用してなにかを行う。

#include <stdio.h>

int addnum(int a, int b)
{
	int x;
	x = a + b;
	return x;
}

void main()
{
	int n;
	n = addnum(5, 56);
	
	printf("%d\n", n); //結果「61」と表示される
}

関数の定義

Posted コメントするカテゴリー: C

関数は一連の処理をまとめたもの。
関数には処理の材料となる値のことを引数(パラメータ)をいい、処理の結果の値のことを戻り値(返り値)

次の例は2つの引数を加算し、結果を返す関数の定義

int addnum(int a, int b)
{
	int x;
	x = a + b;
	return x;
}

結果を返さない関数は次のように定義する
関数の先頭で「void」と定義することにより、結果を返さないことを示す

void dispnum(int a)
{
	printf("引数は%d\n", a);
	return;
}

引数を必要としない関数を定義する

void novalue(void)
{
	printf("not value !!\n");
}

C言語に標準で搭載されている関数は標準ライブラリ関数という
printf()やstrcpy()のことをさし、これらは定義しなくてもすぐに使うことができる

実際に動作させてみた時、注意する点は「void dispnum」と「void novalue」については「int main」の前に記述しておかないと未定義の関数とみなされ、エラーになる。

#include <stdio.h>

void dispnum(int a)
{
    printf("引数は%d\n", a);
    return;
}

void novalue(void)
{
    printf("not value !!\n");
}

int main(void)
{
	int ans;
	ans = addnum(50, 3);
	printf("%d\n", ans);
	
	dispnum(ans);
	
	novalue();
	
	return 0;
}

int addnum(int a, int b)
{
    int x;
    x = a + b;
    return x;
}

メモリの確保および操作関数

Posted コメントするカテゴリー: C

動的なメモリ確保

変数や配列を宣言すると自動的にメモリ上に領域が確保される。
プログラムが多くのデータを扱う場合、メモリを一度に用意しきれない場合があるので、無理に大きすぎるメモリ領域を一気に確保しようとするとエラーになってしまう。

この場合は動的にメモリ領域を確保する方法を使う。

動的にメモリ領域を確保するには、下記のC言語の標準ライブラリの呼び出しをする

#include <memory.h>
#include <malloc.h>
#include <stdlib.h>
//確保したメモリの先頭アドレスを入れるポインタを宣言
short *buf;

//「(short *)」の部分でmallocの戻り値に対して、型のキャストをする
buf = (short *)malloc(sizeof(short) * 2000);

(メモ)
「malloc」関数は、ヒープメモリからsizeバイトのブロックを割り当てる。
この関数を使うことにより、必要な場所で必要なだけメモリを確保することができる。

 

  • ■メモリの利用

malloc関数で確保したメモリは使用後に必ずfree関数で解放する。

//確保した後、通常の配列と同じように使える
buf[2] = 40;
  • ■メモリの解放

使い終わったら、メモリを必ず解放する

free(buf);
  • ■メモリ確保関係の関数

malloc関数の代わりにcalloc関数を使う書き方もできる。

buf = (char *)calloc(sizeof(char) * 20);

(メモ)
「calloc」関数は、メモリを確保し、要素をすべて0に初期化する

realloc関数を使う書き方もできる。

buf = (char *)realloc(buf, sizeof(char)*15);

(メモ)
「realloc」関数は、一度確保したメモリを違うサイズで確保し直す

  • ■メモリ操作関数

メモリを操作する関数はmemset、memcpyなどがある(←ごく一部の例)

//メモリの内容を全て同じ値に設定する
memset(buf, 0, 5);
//↑の例だと、配列の要素5個に対して、全て「0」を代入する動きをする

memcpy(dst, src, 5);
//↑の例、srcというコピー元のメモリ領域の先頭アドレスから5バイト分、dstのアドレスへ代入する
  • 例(書籍そのままを動かしてみる)
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>

int main(void)
{
    char *b;
    char a[4] = {20, 40, 30, 100};
    b = (char *)malloc(sizeof(char) * 200);
    
    if (!b) {
        return;
    }
    
    memcpy(b, a, sizeof(char) * 4);
    printf("%d %d %d %d \n", b[0], b[1], b[2], b[3]);
    free(b);

    //結果「20 40 30 100」と表示される
}

ポインタと配列

Posted コメントするカテゴリー: C

配列の名前そのものは、配列の最初の要素を指し示すポインタの役割をする。

//aはa[0]へのポインタを表す
int a[4];

配列の最初要素以降を呼び出すには、ポインタを加算していく。
ポインタには整数の加算と減算のみ可能。

int *p = a+2; //前から(配列の)2個目の値を指し示す
int *q = p-1; //後ろから(配列の)1個目の値を指し示す

配列の型によって、ポインタの進み方は異なる。

long a[4];
long *p = a+1; //4バイトづつ進む

char c[4];
char *q = c+1; //1バイトづつ進む

配列aがある場合、a自身はa[0]へのポインタなので*aは格納場所ある値=a[0]となる。
同時にa[1] =* (a+1)、a[2] =* (a+2)、と書くことも可能

NULLポインタ

Posted コメントするカテゴリー: C

ポインタを利用するときは、必ずその値が指し示すアドレスに値がある必要がある。

int a;
int *p;
a = *p; //ポインタがなにもないアドレスを指し示している為エラー

プログラム内で、どこも指し示していないことを明示する場合に使う。
NULLポインタはどの型のポインタにも格納できる。

int *p = NULL;

ポインタpが有効かどうかを調べるには、論理演算を使って調べることができる。

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

int main(void)
{
	
	char s[] = "test aaa";
	char c = 'd'; //ダブルクォートで囲むとエラーになる
	char *p = NULL;
	
	printf("文字列 %s の中に文字 %c ", s, c);
	
	p = strchr(s, c);
	
	if (!p) {
		printf("なし\n");
	} else {
		printf("あり\n");
	}
	
	//出力結果は「なし」になる。
	
}

strchrの関数は以下の動きをする
strの中からchrを検索して最初に発見した文字以降のアドレスを返す。文字を発見できなかった場合はNULL(\0)を返す。
尚、一般的には検索する文字はint型にcastする。

ポインタ

Posted コメントするカテゴリー: C

変数などが格納されている位置を値とする変数をポインタという。
ポインタにも型がある。

(例)char型のポインタ変数pを宣言するには次のように書く

char *p;

char* p;

//↑半角スペースの位置が違うけれど、どちらも間違いではない

ポインタへのアドレスの代入

char a;
char *p;
p = &a;

ポインタが指す値の参照

char a = 3;
char *p;
p = &a;

//値を参照してbに代入しているので「3」が代入される
char b = *p;

参考プログラム

#include <stdio.h>

int main(void)
{
	char x = 4;
	char y;
	char *p = &x;
	y = *p;
	printf("%d \n", y); //結果「4」が表示される

}

アドレス

Posted コメントするカテゴリー: C

変数や配列はコンピュータのメモリ上にある。
変数や配列はメモリ上に記録されていると言える。

メモリにはアドレスという連続した番号がついている。
その番号をもとに、どこになにが入っているのかを管理できるようになっている。

プログラムの変数に対し、変数に「&」記号をつけると、その変数の位置(アドレス)を返す。

(例)
&a = 0xE001
&b = 0xE003

参考プログラム

#include <stdio.h>

int main(void)
{
	char a;
	short b;
	
	printf("aのアドレス=%x、bのアドレス=%x \n", &a, &b);
	
	//実行結果は以下のように出る
	//aのアドレス=18ff5f、bのアドレス=18ff5c
}

多次元配列

Posted コメントするカテゴリー: C

配列の中の値に配列を入れて使う場合、多次元配列を使う。

多次元配列は1次元、2次元、3次元、、、とシステムのメモリが許す限り増やしていける。
4次元以上になると、実用の範囲から遠くなる。

#include <stdio.h>

int main(void)
{
	//1次元配列
	int a[3];
	
	//2次元配列
	int a[2][3];
	
	//3次元配列
	int a[2][2][3];
	
	//多次元配列への初期化と同時に値を代入
	int a[2][3] = {
		{10, 20, 30},
		{40, 50, 60}
	};
	
	//代入
	a[0][2] = 0;
	
	//結果表示
	printf("%d\n", a[1][2]); //結果「60」となる
	
	
}

多次元配列への値の代入は以下のようにする

配列を使った文字列操作関数について

Posted コメントするカテゴリー: C

C言語に標準搭載されている文字列操作関数を検証してみる。

まず、文字列操作関数を使う場合には、これまでプログラムの先頭に必ず書いていた「#include 」という記述に加え、次のような記述をする。

#include <string.h>

文字列操作関数をいくつか試してみる。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
   
int main(void)
{
    //配列と変数を宣言
    char s[4] = "ABC";
    int len;
      
    //■文字数を取得する
    len = strlen(s);
  
    printf("文字列の長さは%fである\n", len); //結果「文字列の長さは0.000000である」
    printf("文字列の長さは%dである\n", len); //結果「文字列の長さは3である」
      
    //■文字列コピー
    char ss[6];
    strcpy(ss, "world");
    printf("文字列は%dです\n", ss); //結果「文字列は1245010です」と出てしまう。。。
    
    //■文字列連結
    char d[6] = "AAA";
    char e[]  = "de";
    
    printf("\n\n%s\n\n", strcat(d, e));
    
    //■文字列比較
    char g[] = "AAA";
    char h[] = "ABBD";
    
    int cc = strcmp(g, h);
    printf("\n\n%d\n\n", cc); //結果「-1」と表示される
    
    //■数値などを文字列に変換する
    char ss[40];
    sprintf(ss, "%f", 143.5);
    printf("変換した結果、%dです\n\n", ss); //結果「変換した結果、1638164です」と表示される(これは正しいのか)
    
    //■文字列を数値に変換する
    char sss[] = "340";
    int nnn = atoi(sss);
    printf("変換した結果、%dです\n\n", nnn); //結果「変換した結果、340です」 と表示される
    
    
    
    
    
    
}



strcpyした直後の値が「文字列は1245010です」と出てしまう現象がわからない。なぜだ。

↓。自己解決しました。printf内での出力指定方法が「%d」だった為です。
%sにすることで文字列として出力することを検証した。

    printf("文字列は%sです\n", ss); //結果「文字列はworldです」と出た

型に迷ってしまう場合は、一旦こちら(http://propanmode.net/blog/?p=208)を確認すること。
↑の記事はもっと加筆する。

文字列変換系関数の検証

数値などを文字列に変換する関数。
sprintf()

文字列を数値に変化する関数。実行するには「#include 」の読み込みが必要。←実際には記述しなくてもatoi関数は動作した。
atoi()

配列

Posted コメントするカテゴリー: C

配列は複数の同じ型の変数を1つにまとめたもの。

下記のように宣言して使う。

#include <stdio.h>
 
int main(void)
{
	//宣言する場合
	int a[4];

	//初期化と同時に値を代入する場合
	int a[4] = {1,2,3,4};

	//配列の宣言のほうの添字を省く場合、自動的に配列の数が決まる
	int a[] = {1,2,3,4};

	//それぞれの配列に個別に値を代入する方法
	int b[4];
	b[0] = 1;
	b[1] = 2;
	b[2] = 3;
	b[3] = 4;

	//配列の添字の範囲外の数字を使って配列に台に代入するとエラーになる
	//(はずだったが手元の環境ではエラーにならず、、、)
	b[9] = 4;
}

配列と文字列操作
文字列を格納する為には配列を使う(文字列配列)。
配列のひとつひとつに文字が入っているイメージとなる。

#include <stdio.h>
 
int main(void)
{
	//宣言
	char s[] = "ABCD";

	//次のように記述しても同じ意味になる(\0はNULL文字列を表す)
	char s[5] = {'A', 'B', 'C', 'D', '\0'};
	
	
	//配列の中のひとつひとつが文字列なので、指定文字だけを制御することも可能
	char s[4] = "ABCD";
	s[2] = 'Z';
	
	printf("%s", s); //ABZDと表示される
	
}

練習

#include <stdio.h>
 
int main(void)
{
	//宣言
	int i = 0;
	char s[] = "ABC";
	char b[4];

	printf("%sを逆にする\n", s);
	
	while (s[i] != '\0') {
		b[i] = s[2-i];
		i++;
	}
	b[3] = '\0'; //\0はNULL文字列
	printf("%s\n", b);
}

switch文

Posted コメントするカテゴリー: C

複数の条件を判断し、その条件に応じた処理をするには、switch文を使う。
switch文はcaseと呼ぶ条件から処理を分岐し、どの条件にも当てはまらない場合はdefaultの処理に進む。
各条件の最後にはbreak文を記述して選択した処理のみを実行する。

#include <stdio.h>

int main(void)
{
	char a;
	
	printf("番号を入力\n");
	a = getchar();
	
	switch(a){
		
	case '1':
		printf("おぉ!\n");
		break;
	
	case '2':
		printf("おおぉ!\n");
		break;
	
	case '3':
		printf("おおおぉ!\n");
		break;
	
	case '4':
		printf("おおおおぉ!\n");
		break;
	
	default:
		printf("ぬぬ!\n");
		
	}


}

while文

Posted コメントするカテゴリー: C

ある条件が成り立っている場合のみ、ループをする処理を書く。

#include <stdio.h>

int main(void)
{
	int i = 10;
	while (i >= 0) {
		printf("iは今%dです。\n", i);
		i--;
	}
}

上の例で言うと、「i >= 0」の条件が成り立っている間は、{}の中の処理が走ることになる。

for文との違いはカウンタがあるかないかが大きな違いとなる。
繰り返す回数がわからない場合に使うことが多い。

条件の真偽に関わらず、必ず一回処理を実行してから判定を行うループは「do while文」といい、次のように書く。

#include <stdio.h>

int main(void)
{
	int b = 10;
	do {
		printf("bは今%dです。\n", b);
		b--;
	} while (b >= 0);
}

ループを途中で中断するには、「break」を使い、処理を終わらせることができる。
次の例はループ途中の5回目の処理で終わらせる場合の書き方。

#include <stdio.h>

int main(void)
{
	int i = 10;
	
	while (i >= 0) {
		if (i == 5) {
			break;
		}
		printf("iは今%dです。\n", i);
		i--;
	}
}

ループ処理の途中で、その回の処理を中断し、次の回の処理の最初から実行させる方法は「continue」を使う。

#include <stdio.h>

int main(void)
{
	int i = 10;
	
	while (i >= 0) {
		
		printf("iは今%dです。(1つめの出力)\n", i);
		if (i == 5) {
			i--;
			continue;
		}
		
		printf("iは今%dです。(2つめの出力)\n", i);
		i--;
	}
}

for 文

Posted コメントするカテゴリー: C

同じことを指定の条件下で繰り返し実行する場合に使う

include <stdio.h>

int main(void) {
    
    int i;
    for (i=0; i<10; i++) {
        printf("iは今、%d回目です\n", i);

    }

}

ループは2重にループさせることができる。(2重ループ)

#include <stdio.h>

int main(void) {
    
    int i;
    int j;
    for (i=0; i<10; i++) {
        printf("iは今、%d回目です\n", i);
        for (j=0; j <=3; j++) {
            printf("jは今、%d回目です\n", j);
        }
    }
}

制御文 連続したif文

Posted コメントするカテゴリー: C

複数の条件を判別したい場合には、if文を組み合わせて判別できる。

下記の例は、条件の1番目が成立するか2番目が成立するか、それとも全てに当てはまらないか。の判別をすることができる。

#include <stdio.h>

int main(void)
{
	int a = 5;
	
	if (a%2 == 0) {
		printf("%dは2で割り切れます\n", a);
	} else if(a%3 == 0) {
		printf("%dは3で割り切れます\n", a);
	} else {
		printf("%dは2でも3でも割り切れません\n", a);
	}

}

制御文 if

Posted コメントするカテゴリー: C

条件によって処理を振り分ける。
条件は比較演算子や論理演算しを使って条件式を指定する。

下記はint型の変数aの中身が偶数か奇数かを判別して結果を出力する。

#include <stdio.h>

int main(void)
{
	int a = 5;
	
	if (a%2 == 0) {
		printf("%dは偶数\n", a);
	} else {
		printf("%dは奇数\n", a);
	}
}

演算の優先度

Posted コメントするカテゴリー: C

演算子にはそれぞれ優先度が設定されている。

()や->などの記号は優先的に処理されるが、もしも式の中で同じ順位の演算子が並んでいる場合は、右から処理するのか、左から処理するのかという順序も言語の仕様として決まっている。

優先順位     演算子
1            () [] . ->  ++(後置) --(後置)
2            ! ~ ++(前置) --(前置) + - &(ポインタ)  *(ポインタ)  sizeof
3            キャスト演算子
4            * / %
5            +  - 
6            <<   >> 
7            <  <=  >  >=
8            ==  !=
9            &(ビット積)
10           ~
11           |
12           &&
13           ||
14           ? : (三項演算子)
15           = += -= *= /= %= &= |= ~= <<= >>=
16           , (カンマ)

型の変換

Posted コメントするカテゴリー: C

整数どおしで計算をすると、結果は整数になる。

3 / 2 = 1

正確に小数点まで出力する場合は、実数表記にして、計算する。

3.0 / 2.0 = 1.5

整数の計算と、実数の計算で、結果が異なることを確認。

#include <stdio.h>
int main()
{
	printf("3 ÷ 2 = %d \n", 3/2);
	printf("3 ÷ 2 = %f \n", 3.0/2.0);
	printf("3 ÷ 2 = %f \n", 3.0/2);
	printf("3 ÷ 2 = %f \n", 3/2.0);
}

整数どうしの演算では、一番範囲の広い型に変換される。
例えば下記の結果は

short s = 536;
char c = 12;
int a = s + c;

答えは548となり、charの型は-128~127として扱われるが、short型として計算される。

■異なる制度の型どうしの代入

unsigned char c = 1000; //オーバーフローし、上位2ビットが処理されない為、1000にはならない。
unsigned char c = -3; //符号なしの変数に符号付きの値をいれても、符号が解釈されない。

ビット と バイト

Posted コメントするカテゴリー: C

■ビットとは
ビットとは「1」か「0」の値とする、情報の最小単位を言う。

■バイトとは
ビットが8個集まったもの(8バイト)を1バイトと言う。

バイトの単位は2の10乗ごとに単位が繰り上がる。

単位        意味
KB          1KB=1024バイト
MB          1MB=1024KB
GB          1GB=1024MB
TB          1TB=1024GB

n進数について

Posted コメントするカテゴリー: C

コンピュータの世界では、2進数や16進数という、10以外の数値で位が繰り上がる数字の数え方をする。

10進数と比較して、2進数と16進数の位は次のようになる。

2進数      10進数      16進数
0          0           0
1          1           1
10         2           2
11         3           3
100        4           4
101        5           5
110        6           6
111        7           7
1000       8           8
1001       9           9
1010       10          A
1011       11          B
1100       12          C
1101       13          D
1110       14          E
1111       15          F
10000      16          G

プログラムの中で数値を16進数で表記するには、数字の前に「0x」をつける。
printfの書式では、「%x」として表す。

論理演算子

Posted コメントするカテゴリー: C

複数の条件を組み合わせて、より複雑な条件を表すときに使う。

演算子     働き
&&         かつ
||         または
!          ではない

条件が2つある場合、それぞれの条件を同時に満たす場合を判断するには「&&」を使います。
また、それぞれの条件の関係性をはっきりさせたい場合は「()」かっこでくくります。

(例)aの値が40以上で、なおかつ、100未満の場合
(40 <= a) && (a < 100)

比較演算子

Posted コメントするカテゴリー: C

変数や数などを比較する演算子のことを言う。
条件式などで、処理を変える場合に使う。
比較した条件が成立した場合は「真」および「true」といい、
成立しない場合は「偽」および「false」という

演算子  働き
==      等しい
<       小なり
>       大なり
<=      以下
>=      以上
!=      等しくない

条件式はそれぞれ比較した後の値を持っていると考える。
条件が真の場合は「1」、偽の場合は「0」という値を持っている。

サンプルプログラムとして以下のようなプログラムを作成。

#include <stdio.h>

int main(){

	int a = 1;
	int b = 2;

	printf("a<b    %d\n", a<b);     //比較式(小なり)
	printf("a>b    %d\n", a>b);     //比較式(大なり)
	printf("a==b   %d\n", a == b);  //比較式
	printf("a=b    %d\n", (a = b)); //代入式

}

インクリメント・デクリメント

Posted コメントするカテゴリー: C

インクリメントは加算演算子と呼び次のように記載。
動作としては元にあった変数に対して、プラス1を行う。

a++;

デクリメントは減算演算子と呼び、次のように記載

動作としては元にあった変数に対して、マイナス1を行う。

a--;

次のプログラムを作成し、実行するとコンソール上には「2321」と表示される。

#include <stdio.h>
int main(){
	int a = 1;
	a++;
	printf("%d\n", a);
	a++;
	printf("%d\n", a);
	a--;
	printf("%d\n", a);
	a--;
	printf("%d\n", a);
}

a++と書く場合と++aと書く場合の違い
++aと書く場合は前置という。反対にa++と書く場合は後置という。

#include <stdio.h>
 
int main(){

    //後置の動き
    int b, a = 1;
    b = a++;
    printf("%d\n", b); //結果は1

    //前置の動き
    int b, a = 1;
    b = ++a;
    printf("%d\n", b); //結果は2
 
}