狠狠撸
Submit Search
颁言语讲习会4
?
6 likes
?
2,246 views
O
odenhadengaku
Follow
未経験者のためのC言語講習会 資料/ C language for inexperienced people
Read less
Read more
1 of 49
Download now
Downloaded 23 times
More Related Content
颁言语讲习会4
1.
C言語講習会 第4回 ロボット技術研究会 @odenhadegaku
2.
目次 ? 今までの総復習 ? ポインタ ?
構造体 ? 列挙体 ? 共用体 ? 最後に
3.
今までの総復習 ? 変数,型 ? int
a; c = a + b; a++; a += b; ? 整数型÷整数型の演算は注意.必要となったら キャスト演算子を – double c = a / b; (a,bはint型変数) – (double)hoge; ? 大きい値を扱うときには,オーバーフローに注 意 型 変数 代入 インクリメント
4.
今までの総復習 ? 変数,型(まだやってなかった説明) ? a
= b = c = 0; ? これはa,b,cすべてに0が代入される – どういう仕組みで代入される…? ? a = 0;という計算はaに0を代入した後に,右辺の 値を返す ? そして結合規則は右から左 ? よって(a = (b = (c = 0))); ? わざわざa = 0; b = 0; c = 0;と書く必要がなくな る
5.
今までの総復習 ? 制御構文(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文から脱出
6.
今までの総復習 ? 関数 ? プロトタイプ宣言を忘れ ずに int
add(int a, int b){ … 処理; … return a + b; } 戻り値の型 関数名 引数 戻り値
7.
今までの総復習 ? 関数 ? なぜプロトタイプ宣言は必要 なのか ?
コンパイラは上から下にソー スコードを読むため ? だったら,そもそもプロトタ イプ宣言の位置に,関数の定 義を書けばプロトタイプ宣言 は必要ない
8.
今までの総復習 ? 配列 int data[20]; ?
配列は0番目から(要素数-1)番目まで ? 配列の初期化の方法は int hoge[] = {2,4,6}; 型名 配列名 要素数
9.
今までの総復習 ? ビット演算 AND演算子(&) 0x2F &
0x3C OR演算子( | ) 0x2C | 0xC0
10.
今までの総復習 ? ビット演算 NOT演算子(~) ~0xEC XOR演算子( ^
) 0x13 ^ 0xD7
11.
今までの総復習 ? ビット演算 ビットシフト演算子 (<<) 0xC4 <<
2; もちろん>>もあるよ
12.
ポインタ ? そもそも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番地
13.
ポインタ ? 定義した変数は下のようになる ? それぞれの変数には,変数の場所を示すアドレスがある ?
このアドレスそのものを保存するための変数がポインタ 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;
14.
ポインタ ? 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; 型名 + *(アスタリスク)
15.
ポインタ ? ある変数のアドレスを取得するには「&」を使う. ? 例えば,下の例では「&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;
16.
ポインタ ? つまり「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;
17.
ポインタ ? 先程の「&」と逆に,あるアドレスが指してい るメモリの内容を参照するには「*」を使う ? ポインタ宣言時,掛け算の「*」とは意味が違う! 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;
18.
ポインタ ? つまり,「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;
19.
ポインタ ? 以上の話をまとめる ? 右のソースコードを書い て実際に先ほどの説明が 正しいかを確かめる ?
実行すると,変数aの値が 3から4に書き換えられて いることが分かる
20.
ポインタ ? じゃあポインタは何に使 うの? ? 説明が難しい ?
使い方の1つとして,関数 の引数に使う ? 例えば右のような関数を 作り,a,bの値を引数とし て入れ,関数で値を変更 したところでa,bそのもの の値は変わらない ? a,bの値そのものが関数の引 数にコピーされるだけ ? a,bとp,qのアドレスは違う
21.
ポインタ ? ここで,関数の引数にポ インタの考えを使う.つ まりアドレスを渡せば同 じ場所を指せる ? 関数は戻り値を1つしか返 せない.しかしポインタ を使えば複数の変数を返 すことができる.
22.
ポインタ[演習] ? 複数の変数を返す先ほどの性質を使ってみる. ? ある2つのint型整数の和と差の両方を返す関数を作ってみ る
23.
ポインタ[応用] ? ポインタと配列には関係がある ? そもそも配列で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;
24.
ポインタ[応用] ? 配列を定義すると,指定した要素分連番でメモリを確保 する ? 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;
25.
ポインタ[応用] ? よって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;
26.
おまけ ? はじめの方のポインタの宣言の仕方で「int *p;」と 「int*
p;」の2種類の宣言の仕方を紹介した ? アスタリスクの位置の違いだけ ? 変数を1つだけ宣言するときには違いはない ? 2つのint型へのポインタの変数を宣言したい ? int* p1,p2; ? コレは間違い!(p2はただのint型の変数) ? 「int *p1,*p2;」が正しい宣言の仕方 ? なんで型の方ではなく変数の方にアスタリスクをつける 習慣をつけた方が無難?
27.
おまけ ? void型の変数は作れないが,void型へのポインタの変数 は作れる ? 汎用ポインタと呼ばれる ?
あらゆる型へのポインタを代入できるすごいやつ ? void*の変数を実際に使うときにはキャストをして取り出 す ? コンパイラの型チェックが効かなくなるので,良い子の みんなは使わないようにしよう
28.
構造体 ? 複数の変数をまとめて扱 いたい場合がある ? 身長,体重,名前をまとめ て「人」型のようなものを 作るなど ?
配列で用意する?わかりに くそう そもそも型 が??? ? 構造体という便利なもの があり,コレを使うと 様々な型の変数をまとめ て取り扱える ? 構造体の定義 struct Person{ double height; double weight; char name[10]; }; ? 上の例はdouble型の height,weight,char型の配 列nameをまとめて扱って いる 構造体の型名
29.
構造体 ? 前の例では,Person型の 構造体を作ったことにな る ? このように定義した Person型の変数を宣言す るには struct
Person hoge; ? とすればよい
30.
構造体 ? 先ほど定義したPerson型の変数hogeにはdouble型の変数 heightがあったが,これにアクセスするには hoge.height =
171.65; ? のようにドット( . )を用いる ? こうすることで変数hogeの中にある変数heightは171.65 になった.
31.
構造体 ? 前のスライドで,構造体によってPerson型など,自分の 型を作ることができた. ? しかし,構造体の変数をいちいち struct
Person hoge; ? と定義しなければならないのは冗長 ? structとかいうのが邪魔 ? どうせなら Person hoge; ? のように定義してみたい
32.
構造体 ? ここで次の演算子を 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部分は 省略可
33.
構造体 ? つまり, typedef struct{ double
height; double weight; char name[10]; } Person; ? と書けば,Person型が使えるようになると覚えればよい
34.
構造体 ? 余裕のある人は「typedef」バージョンも 考えてみよう
35.
ポインタと構造体 ? 構造体を関数の引数にとる と,サイズが大きくなりコ ピーする際にコストがかか る – 詳しくは値渡しと参照渡し ?
ポインタで構造体を渡して あげれば,アドレスを渡す だけなのでコストが掛から ない! ? 構造体において, ? 「(*h).a」と「h->a」 ? は同じ意味
36.
列挙体 ? 以前,定数を定義する方法 として,#defineやconstを 紹介した ? 状態を区別するための定数 のような,定数の数値自体 に意味が無い定数を作成し たいときに一々番号をふる のは面倒 –
右の場合,LEFT,RIGHTに意 味があるのであって,数値 に特に意味は無い #define LEFT 0 #define RIGHT 1 #define UP 2 #define DOWN 3
37.
列挙体 ? こういう時に,列挙体 (enum)を使うとまとまり のある定数を簡単に書け る ? 一番上の定数から勝手に 0,1,2…と割り振られる –
数値を代入することもでき, 右でRIGHT=3とした場合は, LEFT=0,RIGHT=3,UP=4, DOWN = 5となる – 列挙体は整数値のみ enum{ LEFT, RIGHT, UP, DOWN };
38.
ビットフィールド[応用] ? あまり見かけないが,構 造体にはビットフィール ドというものがある – というか初めて知った ?
構造体の中の変数に続け てコロン「:」をつける ? コロンの右にある数値は, その変数が何bitの領域を 確保するかを教える – var0なら1bit,var1なら4bit
39.
ビットフィールド[応用] ? 内部では,次のようにメモ リが使われている ? 結果的には全体で8bit,1バ イトしか占有していない unsigned
char(8bit) var0(1bit) var1(4bit) var2(3bit)
40.
ビットフィールド[応用] ? printfで変数を表してみると, – var0は0or1のみ –
var1は0から15まで – var2は0から7まで ? しか表現できないことが分 かる – unsigned intなので符号なし ? 変数の範囲を限定できるの で,不用意なデータの代入 で起こるエラーを未然に防 げる
41.
共用体[応用] ? C言語には共用体(union)と いうものがある – 使ったこと無い… ?
定義の仕方は構造体を参照 – 構造体とほぼ同じ – structがunionになっただけ ? 構造体との違いは,それぞ れの変数が1つのメモリを 共有していること – 具体的には次で説明
42.
共用体[応用] ? 右の例でいくと,char型の 配列chに値を代入した時の メモリの配置は次のように なる ? 0x64387203 ch[3] 100 ch[2] 56 ch[1] 114 ch[0] 3
43.
共用体[応用] ? ここで,int型の変数nを出 力すると, 0x64387203 -> 1681420803 –
intは4byte(32bit)だから ? が出力され,char型の変数 ch1を出力すると, 0x64387203 ->3 – charは1byte(8bit)だから
44.
共用体[応用] ? 結果は次のようになる
45.
共用体[応用] ? つまり,すべての変数が同じ メモリを見ていることになる ? この構造体のサイズは,1番 大きい変数(ここではint)と同 じになる 64387203 ch[4]
(32bit) int(32bit) char(8bit)
46.
最後に ? C言語講習会は4回あったが,この4回でC言語を すらすら書けるようになるのは不可能 ? 一番早く習得するには,とりあえず色々とプロ グラムを書いてみること –
F3RCもC言語を覚える良いきっかけになると思う – 素数判定など,自分の興味あるプログラムを作るの も良い
47.
最後に ? C言語ができると何が作れる??? ? たとえばゲーム –
Dxlibとか使うと,C言語の文法で画像やらなんやらを扱え, ゲームが作れるようになる – あとはゲーム特有のプログラミング技術を部長(@OMA_st)など に教えてもらおう ? たとえば画像処理 – OpenCVを使えば,顔認識や物体?人物検知など,色々と面白い プログラムができる
48.
最後に ? なにか作りたいものがあるわけじゃないけど,とりあえ ずC言語に慣れておきたい? ? ならばAOJかProject
Euler – AOJ: http://judge.u-aizu.ac.jp/onlinejudge/ – Project Euler: https://projecteuler.net/ – PEはより数学寄りの内容を扱っている – 素数とか出るし東工大生向け? – 競技プログラミングについて興味あるならよすぽ(@yosupot)に 聞こう
49.
最後に ? 講習は以上です お疲れ様でした
Download