*

C言語 バッファオーバーランまで ポインタ考察編

公開日: : 最終更新日:2014/08/22 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」でも良いのかなど細かい
疑問は残ってますが、コンパイルさんがダメって言っているので機械的に覚えてしまいます。。。

理解できてる人にとっては当たり前の内容ですが、基本的な所からやっていきます。

次回

C言語 バッファオーバーフローまで 関数の引数ポインタ

関連記事

jQuery 水平スクロール&cssでカスタム可能なスクロールバーなプラグイン

水平スクロール&cssでカスタム可能なスクロールバーなプラグイン jQueryを使ったプラグインは

記事を読む

Macで ローカルサーバー構築 Postfix基本編

Macで ローカルサーバー環境を構築するまで Apache起動編 ネットでの情報は必要最低限しか載

記事を読む

Macで ローカルサーバー構築 PHP設定編

Macで ローカルサーバー環境を構築するまで PHP設定編 ネットでの情報は必要最低限しか載ってな

記事を読む

Androidで課金アプリ作製 エラー編(-1008:Unknown error)

Androidで課金アプリ作製 エラー編 In-app Billing v3を使用したアプリ開発で

記事を読む

Androidで課金アプリ作製 定期購読サンプルコード編

Androidで課金アプリ作製 定期購読編 In-app Billing v3を使用したアプリ開発

記事を読む

PHPでIE11ユーザーエージェント判定

IE11のユーザーエージェント判定 自作のユーザーエージェント判定クラスでIEの判定が出来てなかっ

記事を読む

jQuery draggable,resizable 要素のサイズがずれる

uiプロパティ以外で要素のサイズ取得を試みる draggableとresizableを使用し要素の

記事を読む

Androidで課金アプリ作製 サンプルコード(BILLING V3) 起動編

Androidで課金アプリ作製 サンプルコード起動編 課金アプリの制作の機会が来てしまいました。

記事を読む

PHP substr エスケープ処理で文字化け

PHP substr 文字化け mb_substrで文字コードを合わせて切り取ればOKって記事は沢

記事を読む

PHP MySQL 重複行を抽出 ロジックで高速化

PHP MySQL 重複行を抽出 ロジックで高速化 ロジックで高速化は釣りになっているかもしれませ

記事を読む

jQuery 水平スクロール&cssでカスタム可能なスクロールバーなプラグイン

水平スクロール&cssでカスタム可能なスクロールバーなプラグイン j

C言語 バッファオーバーランまで 関数の引数ポインタ

関数引数としてのポインタ 今回は関数引数としてのポインタに関して。

C言語 バッファオーバーランまで ポインタ考察編

趣旨 ただC言語を勉強してもモチベーションがあがり辛いので、 取り

Google Cloud Messaging プロジェクトナンバー API Key取得編 2014/07最新版

Google Cloud Messaging プロジェクトナンバー A

jQuery removeClass 特定のクラスを全て削除

特定のクラスを全て削除 フォームを作成した時に、入力項目に不備があっ

→もっと見る

PAGE TOP ↑