ブログ「サイバー少年」

ブログ「サイバー少年」へようこそ!
小学六年生ごろからプログラミングを趣味にしている高校生のブログです。
勉強したことについての記事などを書いています。フリーソフトも制作、公開しています。
(当ブログについて詳しくは「ブログ概要紹介」を参照)

サイバー少年が作ったフリーソフトは「サイバー少年の作品展示場」へ

久しぶりにC言語を書いてみた! ~ ポインタ加算の罠 ~

最近、C言語の学習をしていませんでしたので、C言語のプログラムを書いてみました。

正確に言うとC言語ではなくVC++言語です…。

今回はmalloc関数を使ってみました。

mallocProgram(275).txt Yahoo!ボックス
http://yahoo.jp/box/2mKXt7

手軽に見られることを重視して、圧縮なしのテキストファイルで公開しています。

ダウンロード時も、保存せずに「開く」で十分です。

ぜひ見てください。


このプログラムは単純に0から99まで出力するものですが、内部でやっていることが複雑ですね。


1. mallocで4(intのサイズ) * 100バイトのヒープ領域を確保して、戻り値をポインタ変数に格納

2. ポインタ変数[0]からポインタ変数[99]に0~99を格納

3. ポインタ変数[0]からポインタ変数[99]を1行ずつ出力



要するにヒープ領域に配列を作っているわけです。

本来なら4ではなくてsizeof(int)と書くのが正しい作法かな。


こういうプログラムをC言語で書きましたとさ。
めでたしめでたし。


…って、終わるのが早い!

もう一つのテーマを話します。





配列にアクセスするときの構文“p[i]”は“*(p + i)”の糖衣構文です。

まぁ、納得できますね。

私も、これをどこかで聞いたことがあるので、糖衣構文なしでアクセスしてみようと思ったんですよ。

それで書いてみたのですが、エラーになってしまいました。

私は大きな間違いをしていました。


*(p + i)
ではなく、*(p + i * 4)と書いてしまっていたのです。

4は配列の1要素のサイズのことです。


…要するに、これは
int*型とint型の足し算になったときに、自動的にintのほうをポインタのサイズに合わせてくれていた
ということですね。

それに尽きます。

私はそんなことをしてくれているとは知らなかったのです…。

この場合も*(p + i)は内部では*(p + i * 4)として計算されていたんですね。

つまり、私はそれを無視して、実質的な*(p + (i * 4) * 4)を書いていたことになります。

大事なことは先に言って欲しいですね。


あと、間違えた原因の一つに、C#のポインタではそうはならないということがあります。

C#ではp++の場合ならサイズ分が加算されますが、p + iはサイズを無視します。

確かそのはずです。
C言語とは仕様が違うんですね~。


と言う訳で、*(int*)((int)p + i * 4)とすれば良かったんですね。

そうしましょうか。(ヤケクソ…)


いや~、便利っちゃあ便利ですけど、困ります…。

tag:

コメント

コメントの投稿

トラックバック

トラックバック URL
http://cyberboy6.blog.fc2.com/tb.php/275-8546794c
この記事にトラックバックする(FC2ブログユーザー)

当ブログをご利用(閲覧等)になる場合は必ず「当ブログの利用規定」をお守りください。