C言語 バッファオーバーランまで ポインタ考察編
趣旨
ただC言語を勉強してもモチベーションがあがり辛いので、
取り合えずバッファオーバーランを目標にし勉強していきたいと思います。
最低限の知識からのスタートになので、
手っ取り早くやりたい方はこちらが参考になります。
バッファオーバーラン~その1・こうして起こる~
シリーズ
・C言語 バッファオーバーフローまで ポインタ考察編
・C言語 バッファオーバーフローまで 関数の引数ポインタ
動作環境
windows7 x86?
cygwin 1.7.16?
予備知識
・cygwinを利用してます。
Windows に Cygwin バージョン 1.7 をインストール
gcc,gdbコマンドが利用できる環境、Cが扱えるならOK
ポインタに関しての考察
C言語は過去に何度も挑戦してくじけてます。
何故かは大抵の人がぶつかるポインタの壁があるからです。。。
大抵の参考サイトではキャラクタ(1文字)と配列(文字列)の挙動が違うのに、
いつの間にか話が進んで何故?って事になってしまってました。
もしかしたら見逃してるだけかもしれませんが。。。?
その挙動の違いの説明が無いために混乱を生んでしまっているような気がします?
ある程度理解していて、つまづいた人用に書かれているので、初めから覚えようとする場合には読まないほうが良いです。
さらなる混乱の原因になりかねません。なります。そして後悔します。
以下具体例
整数型(int)
基本的なおさらい
int a = 1; int *pa; // ポインタ型として宣言 pa = &a; // 「&」はアドレスを渡す // output [ 1 ] printf("%d\n", *pa); // 「*」はポインタの実態(変数aに代入した1)を参照する // output [ /[0-9]*/ ] printf("%d\n", pa); // 変数aが参照しているアドレスが表示される
※ [ /[0-9]*/ ]は数列を表してます。2548714など。以下同じ
「*」が付いたらポインタ型
「&」が付いたらその変数のアドレス
キャラクタ型(char)
char c = 'c'; char *pc; // ポインタ型として宣言 pc = &c; // 「&」はアドレスを渡す // output [ c ] printf("%c\n", *pc); // 「*」はポインタの実態(変数aに代入したc)を参照する // output [ /[0-9]*/ ] printf("%d\n", pc); // 変数aが参照しているアドレスが表示される
整数型と同じ事してます。
ただ型宣言が「int」か「char」の違いだけです。
注意すべきは1文字の時は「’」シングルクォーテーションで囲いましょう。
「”」ダブルクオーテーションにすると次に書きますが、文字列となってしまい
全く違う意味になってしまいます。
その前にコンパイルさんがエラーを起こしますが。。。
配列(文字列)
これも型はchar型なのですが、文字列を扱う場合は配列として扱われます。
「char str[];」と変数宣言を行う必要があります。
配列の大きさやメモリの確保が関わってきますが、その辺りはごろごろしているので割愛。。。
char str[] = "str"; // 文字列の最後には「\0」が自動的に付与される //char *str = "str"; // 上と同じ意味になります。 char *ps; // ポインタ型として宣言 ps = str; // 文字列の場合は配列として扱われるため、&が無くても1文字目のアドレスが渡される
ここで勘違いをしてました。今まで「&」でアドレスを渡すものだと思ってましたが、
配列の場合は初めからアドレス(文字列の1文字目)が渡されます。。。
この違いを理解せず進み、混乱を起こしてました。
はい。ここが重要です。これ以外はおまけです。
これで謎は解けたと思いましたが、出力した時の挙動がまた違うので以下にまとめました。
・%s:文字列として表示する
// output [ str ] printf("%s\n", ps); // 文字列として表示
・%d:10進数で出力する *をつけて実態を参照してみる
// output [ 115 ] printf("%d\n", *ps); // ascii文字コード[s:115]を表示
アドレスが入っているのなら、「s」が表示されると思いきや「115」って。。。
内部文字コードの関係かな?機会をみて調べたいと思います。
・%d:10進数で出力する
// output [ /[0-9]*/ ] printf("%d\n", ps); // 文字列の場合はアドレスが表示される
アドレスが入っているのだから当たり前といえばその通りですが。
・アドレス(ポインタ)を操作してみる
// 先頭の1文字のみを表示 // output [ s ] putchar(*ps); // putchar:マルチバイトを文字として表示 printf("\n"); // 1文字進めて表示 ポインタを1つ進めると同じ ps++; // output [ t ] putchar(*ps); printf("\n"); // output [ /[0-9]*/ ] printf("%d\n", ps); // 文字列の場合はアドレス(ポインタ)が表示される printf("%d\n", &str[1]); // 「&」をつけるとアドレス(ポインタ)が表示される 上と同じアドレスになる // output [ st ] printf("%s\n", ps); // ポインタを進めた場合は2文字目から表示される
正直な所、アドレスを渡しているのだからポインタ型は「int」でも良いのかなど細かい
疑問は残ってますが、コンパイルさんがダメって言っているので機械的に覚えてしまいます。。。
理解できてる人にとっては当たり前の内容ですが、基本的な所からやっていきます。
次回
関連記事
-
jQuery Googleカレンダー風スケジュール表 タイムテーブル
jQueryでスケジュール表もしくはタイムテーブルっぽいもの 仕事でスケジュール管理のシステム開発
-
Apache 500 Internal Server Error
久しぶりに自宅のローカルサーバーを動かしたら「Server error!」が出てゑっ!? 解決方法
-
Macで ローカルサーバー構築 Apache起動編
Macで ローカルサーバー環境を構築するまで Apache起動編 ネットでの情報は必要最低限しか載
-
PHPで指定日の祝日を取得する方法 GoogleAPI利用
google APIを利用して指定日が祝日かどうか取得する 技術的な内容を書く場合は載せてるコード
-
Androidで課金アプリ作製 エラー編(-1008:Unknown error)
Androidで課金アプリ作製 エラー編 In-app Billing v3を使用したアプリ開発で
-
Macで ローカルサーバー構築 ローカルネットワーク参加編
Macで ローカルサーバー環境を構築するまで Apache設定編 ネットでの情報は必要最低限しか載
-
Macで ローカルサーバー構築 PHP設定編
Macで ローカルサーバー環境を構築するまで PHP設定編 ネットでの情報は必要最低限しか載ってな
-
PHP substr エスケープ処理で文字化け
PHP substr 文字化け mb_substrで文字コードを合わせて切り取ればOKって記事は沢
-
Androidで課金アプリ作製 定期購読サンプルコード編
Androidで課金アプリ作製 定期購読編 In-app Billing v3を使用したアプリ開発
-
PHPでIE11ユーザーエージェント判定
IE11のユーザーエージェント判定 自作のユーザーエージェント判定クラスでIEの判定が出来てなかっ