狠狠撸

狠狠撸Share a Scribd company logo
C言語講習会 第4回
ロボット技術研究会
@odenhadegaku
目次
? 今までの総復習
? ポインタ
? 構造体
? 列挙体
? 共用体
? 最後に
今までの総復習
? 変数,型
? int a; c = a + b; a++; a += b;
? 整数型÷整数型の演算は注意.必要となったら
キャスト演算子を
– double c = a / b; (a,bはint型変数)
– (double)hoge;
? 大きい値を扱うときには,オーバーフローに注
意
型 変数 代入 インクリメント
今までの総復習
? 変数,型(まだやってなかった説明)
? a = b = c = 0;
? これはa,b,cすべてに0が代入される
– どういう仕組みで代入される…?
? a = 0;という計算はaに0を代入した後に,右辺の
値を返す
? そして結合規則は右から左
? よって(a = (b = (c = 0)));
? わざわざa = 0; b = 0; c = 0;と書く必要がなくな
る
今までの総復習
? 制御構文(if文)
if(1 <= a && a <= 5){
a++;
}
else{
a--;
}
? else ifも忘れずに
? == と = の違い
真の時の処理
偽の時の処理
? 制御構文(switch文)
switch(a){
case 1:
printf(“a = 1?n”);
break;
dafault:
printf(“a != 1?n”);
break;
}
? break;でswitch文から脱出
今までの総復習
? 関数
? プロトタイプ宣言を忘れ
ずに
int add(int a, int b){
…
処理;
…
return a + b;
}
戻り値の型 関数名 引数
戻り値
今までの総復習
? 関数
? なぜプロトタイプ宣言は必要
なのか
? コンパイラは上から下にソー
スコードを読むため
? だったら,そもそもプロトタ
イプ宣言の位置に,関数の定
義を書けばプロトタイプ宣言
は必要ない
今までの総復習
? 配列
int data[20];
? 配列は0番目から(要素数-1)番目まで
? 配列の初期化の方法は
int hoge[] = {2,4,6};
型名 配列名 要素数
今までの総復習
? ビット演算
AND演算子(&)
0x2F & 0x3C
OR演算子( | )
0x2C | 0xC0
今までの総復習
? ビット演算
NOT演算子(~)
~0xEC
XOR演算子( ^ )
0x13 ^ 0xD7
今までの総復習
? ビット演算
ビットシフト演算子
(<<)
0xC4 << 2;
もちろん>>もあるよ
ポインタ
? そもそもC言語において,メモリと変数の関係性は?
? 変数を定義すると,箱が“できる”というのは間違い
? 正しくは,メモリのある領域を確保する
? 1つ1つが1バイトの大きさのコインロッカー?
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
ポインタ
? 定義した変数は下のようになる
? それぞれの変数には,変数の場所を示すアドレスがある
? このアドレスそのものを保存するための変数がポインタ
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
char a;
char f[4];
int b;
char c;
ポインタ
? char型への変数のアドレスを指すポインタ変数pの宣言
char* p; もしくは char *p;
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
char a;
char f[4];
int b;
char c;
型名 + *(アスタリスク)
ポインタ
? ある変数のアドレスを取得するには「&」を使う.
? 例えば,下の例では「&a」とすることで変数aのアドレ
スである1002を返す
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
char a;
char f[4];
int b;
char c;
ポインタ
? つまり「p = &a;」とすることでポインタpに変
数aのアドレスを代入できる
? この場合pには1002が代入される
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
char a;
char f[4];
int b;
char c;
ポインタ
? 先程の「&」と逆に,あるアドレスが指してい
るメモリの内容を参照するには「*」を使う
? ポインタ宣言時,掛け算の「*」とは意味が違う!
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
char a;
char f[4];
int b;
char c;
ポインタ
? つまり,「char b=*p」とすればbにはaの内容が代入さ
れ,「*p=4」とすれば,pが持っているアドレスのメモ
リを参照し(変数a),内容を4に書き換える動作をする
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
char a;
char f[4];
int b;
char c;
ポインタ
? 以上の話をまとめる
? 右のソースコードを書い
て実際に先ほどの説明が
正しいかを確かめる
? 実行すると,変数aの値が
3から4に書き換えられて
いることが分かる
ポインタ
? じゃあポインタは何に使
うの?
? 説明が難しい
? 使い方の1つとして,関数
の引数に使う
? 例えば右のような関数を
作り,a,bの値を引数とし
て入れ,関数で値を変更
したところでa,bそのもの
の値は変わらない
? a,bの値そのものが関数の引
数にコピーされるだけ
? a,bとp,qのアドレスは違う
ポインタ
? ここで,関数の引数にポ
インタの考えを使う.つ
まりアドレスを渡せば同
じ場所を指せる
? 関数は戻り値を1つしか返
せない.しかしポインタ
を使えば複数の変数を返
すことができる.
ポインタ[演習]
? 複数の変数を返す先ほどの性質を使ってみる.
? ある2つのint型整数の和と差の両方を返す関数を作ってみ
る
ポインタ[応用]
? ポインタと配列には関係がある
? そもそも配列でchar f[4];と宣言した時,fそのものは何?
? fは配列の名前でしょ
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
char a;
char f[4];
int b;
char c;
ポインタ[応用]
? 配列を定義すると,指定した要素分連番でメモリを確保
する
? fそのものは先頭のアドレス(ここでは1007)を格納してい
る
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
char a;
char f[4];
int b;
char c;
ポインタ[応用]
? よってf[2]のように配列にアクセスするとき,*(f+2)とし
てもよいことがわかる.
? また,配列fは「int *q = f;」のように配列の名前はその
ままポインタに代入できる.
1000番地
1001番地
1002番地
1003番地
1004番地
1005番地
1006番地
1007番地
1008番地
1009番地
1010番地
1010番地
1011番地
1012番地
1013番地
1014番地
1015番地
1016番地
1017番地
1018番地
1019番地
1020番地
1020番地
1021番地
1022番地
1023番地
1024番地
1025番地
1026番地
1027番地
1028番地
1029番地
1030番地
char a;
char f[4];
int b;
char c;
おまけ
? はじめの方のポインタの宣言の仕方で「int *p;」と
「int* p;」の2種類の宣言の仕方を紹介した
? アスタリスクの位置の違いだけ
? 変数を1つだけ宣言するときには違いはない
? 2つのint型へのポインタの変数を宣言したい
? int* p1,p2;
? コレは間違い!(p2はただのint型の変数)
? 「int *p1,*p2;」が正しい宣言の仕方
? なんで型の方ではなく変数の方にアスタリスクをつける
習慣をつけた方が無難?
おまけ
? void型の変数は作れないが,void型へのポインタの変数
は作れる
? 汎用ポインタと呼ばれる
? あらゆる型へのポインタを代入できるすごいやつ
? void*の変数を実際に使うときにはキャストをして取り出
す
? コンパイラの型チェックが効かなくなるので,良い子の
みんなは使わないようにしよう
構造体
? 複数の変数をまとめて扱
いたい場合がある
? 身長,体重,名前をまとめ
て「人」型のようなものを
作るなど
? 配列で用意する?わかりに
くそう そもそも型
が???
? 構造体という便利なもの
があり,コレを使うと
様々な型の変数をまとめ
て取り扱える
? 構造体の定義
struct Person{
double height;
double weight;
char name[10];
};
? 上の例はdouble型の
height,weight,char型の配
列nameをまとめて扱って
いる
構造体の型名
構造体
? 前の例では,Person型の
構造体を作ったことにな
る
? このように定義した
Person型の変数を宣言す
るには
struct Person hoge;
? とすればよい
構造体
? 先ほど定義したPerson型の変数hogeにはdouble型の変数
heightがあったが,これにアクセスするには
hoge.height = 171.65;
? のようにドット( . )を用いる
? こうすることで変数hogeの中にある変数heightは171.65
になった.
構造体
? 前のスライドで,構造体によってPerson型など,自分の
型を作ることができた.
? しかし,構造体の変数をいちいち
struct Person hoge;
? と定義しなければならないのは冗長
? structとかいうのが邪魔
? どうせなら
Person hoge;
? のように定義してみたい
構造体
? ここで次の演算子を
typedef (A) (B);
? typedef演算子と呼ばれる
この演算子は,型名Bを型
名Aとして扱うという意味
がある
typedef int poyo;
? とすると,poyo a;はint a;
という意味になる
? この演算子を使って,構造
体ごとtypedefすることが
できる
typedef struct Person{
double height;
double weight;
char name[10];
} Person;
? これでPerson hoge;として
構造体型を使用できる
? オレンジ色のPerson部分は
省略可
構造体
? つまり,
typedef struct{
double height;
double weight;
char name[10];
} Person;
? と書けば,Person型が使えるようになると覚えればよい
構造体
? 余裕のある人は「typedef」バージョンも
考えてみよう
ポインタと構造体
? 構造体を関数の引数にとる
と,サイズが大きくなりコ
ピーする際にコストがかか
る
– 詳しくは値渡しと参照渡し
? ポインタで構造体を渡して
あげれば,アドレスを渡す
だけなのでコストが掛から
ない!
? 構造体において,
? 「(*h).a」と「h->a」
? は同じ意味
列挙体
? 以前,定数を定義する方法
として,#defineやconstを
紹介した
? 状態を区別するための定数
のような,定数の数値自体
に意味が無い定数を作成し
たいときに一々番号をふる
のは面倒
– 右の場合,LEFT,RIGHTに意
味があるのであって,数値
に特に意味は無い
#define LEFT 0
#define RIGHT 1
#define UP 2
#define DOWN 3
列挙体
? こういう時に,列挙体
(enum)を使うとまとまり
のある定数を簡単に書け
る
? 一番上の定数から勝手に
0,1,2…と割り振られる
– 数値を代入することもでき,
右でRIGHT=3とした場合は,
LEFT=0,RIGHT=3,UP=4,
DOWN = 5となる
– 列挙体は整数値のみ
enum{
LEFT,
RIGHT,
UP,
DOWN
};
ビットフィールド[応用]
? あまり見かけないが,構
造体にはビットフィール
ドというものがある
– というか初めて知った
? 構造体の中の変数に続け
てコロン「:」をつける
? コロンの右にある数値は,
その変数が何bitの領域を
確保するかを教える
– var0なら1bit,var1なら4bit
ビットフィールド[応用]
? 内部では,次のようにメモ
リが使われている
? 結果的には全体で8bit,1バ
イトしか占有していない
unsigned char(8bit)
var0(1bit) var1(4bit) var2(3bit)
ビットフィールド[応用]
? printfで変数を表してみると,
– var0は0or1のみ
– var1は0から15まで
– var2は0から7まで
? しか表現できないことが分
かる
– unsigned intなので符号なし
? 変数の範囲を限定できるの
で,不用意なデータの代入
で起こるエラーを未然に防
げる
共用体[応用]
? C言語には共用体(union)と
いうものがある
– 使ったこと無い…
? 定義の仕方は構造体を参照
– 構造体とほぼ同じ
– structがunionになっただけ
? 構造体との違いは,それぞ
れの変数が1つのメモリを
共有していること
– 具体的には次で説明
共用体[応用]
? 右の例でいくと,char型の
配列chに値を代入した時の
メモリの配置は次のように
なる
? 0x64387203
ch[3]
100
ch[2]
56
ch[1]
114
ch[0]
3
共用体[応用]
? ここで,int型の変数nを出
力すると,
0x64387203
-> 1681420803
– intは4byte(32bit)だから
? が出力され,char型の変数
ch1を出力すると,
0x64387203
->3
– charは1byte(8bit)だから
共用体[応用]
? 結果は次のようになる
共用体[応用]
? つまり,すべての変数が同じ
メモリを見ていることになる
? この構造体のサイズは,1番
大きい変数(ここではint)と同
じになる
64387203
ch[4] (32bit)
int(32bit)
char(8bit)
最後に
? C言語講習会は4回あったが,この4回でC言語を
すらすら書けるようになるのは不可能
? 一番早く習得するには,とりあえず色々とプロ
グラムを書いてみること
– F3RCもC言語を覚える良いきっかけになると思う
– 素数判定など,自分の興味あるプログラムを作るの
も良い
最後に
? C言語ができると何が作れる???
? たとえばゲーム
– Dxlibとか使うと,C言語の文法で画像やらなんやらを扱え,
ゲームが作れるようになる
– あとはゲーム特有のプログラミング技術を部長(@OMA_st)など
に教えてもらおう
? たとえば画像処理
– OpenCVを使えば,顔認識や物体?人物検知など,色々と面白い
プログラムができる
最後に
? なにか作りたいものがあるわけじゃないけど,とりあえ
ずC言語に慣れておきたい?
? ならばAOJかProject Euler
– AOJ: http://judge.u-aizu.ac.jp/onlinejudge/
– Project Euler: https://projecteuler.net/
– PEはより数学寄りの内容を扱っている
– 素数とか出るし東工大生向け?
– 競技プログラミングについて興味あるならよすぽ(@yosupot)に
聞こう
最後に
? 講習は以上です お疲れ様でした

More Related Content

颁言语讲习会4