C言語入門(15) そもそもメモリーって一体何なのか
Posted: 2012年10月30日いままでポインターについて書いてきましたが
メモリーって一体何なのか
メモリー
様々な言い方はありますがメインメモリー
こんなやつ
カテゴリー: プログラム, 入門 | タグ: C言語, 入門 | コメント無し »
いままでポインターについて書いてきましたが
メモリーって一体何なのか
様々な言い方はありますがメインメモリー
こんなやつ
前回は何も書きませんでしたが、今回も続きものです。
続きということでおらさい
前回と前々回は、
を行いました。
では、さっさと見て行きましょう!!
前回の続きということでおらさい
前回は、
を行いました。
では、さっさと見て行きましょう!!
いままでは、ポインターとは何かやポインタの宣言の仕方を書きましたが
今回は、ポインターの使用方法を書きます。
ポインターは難しいとよく聞きますし、
私自身もポインターを理解しているかいないかで、良いプログラムが書けるかの差になってくると思っています。
理解すればCプログラマーの土台ができたと言っても過言ではありません。
コンピュータのシステムで説明すると「ショットカットファイル」です。
1MbyteのWordファイルが存在するとします。
コピーしてそのファイルを編集した場合、変更されるファイルは、コピーしたファイルで
コピー元は変更されません。
また、1Mbyte ☓ 2の記憶容量が使用されます。
しかし、コピーではなくショットカットファイルを作成した場合
変更されるファイルは、ショットカットファイルが指し示すファイルです。
また、1Mbyte + 数Kbyteの記憶容量が使用されます。
コピー | ショートカット | |
---|---|---|
データサイズ | 元のデータ☓コピー数 | 元のデータ+ショットカットファイルサイズ☓ショットカットファイル数 |
編集 | 元のデータは変更されない | 元のデータは変更される |
処理時間 | 元データのサイズが大きくなるほど時間がかかる | 元のデータのサイズは関係なく作成できる |
状況によって普段使い分けていると思います。
これをコピーは元データと同様の変数、ショートカットは、ポインター変数に置き換えて考えてみましょう
「C言語入門(9) 配列って?」では特に記述しませんでしたが
配列は、固定サイズしかありません。
int aryTemp[5]; // int aryTemp2[sizeof(aryTemp)]; ERROR // sizeofはサイズ取得関数
他の言語では、配列のサイズが固定ではない場合もあります。
C言語では、なぜ配列サイズが固定なのか(”ここからは、私自身が勝手に思っていることで間違えている可能性があります。”)
機械語に近い言語のため、処理スピードを考えてかつ、メモリーを使いすぎないようにしたためだと思われます。
固定長の配列のみしか作成できなければ、実行されるたびに領域を確保するのではなく
起動時に領域を確保することもできます。(実際はどのようになっているか把握していません)
変数がメモリーに確保される場合は、「スタック」と言った領域に確保されます。
他の領域には、「コード」「データ」「ヒープ」が存在しています。
動的に領域を確保する場合には、「ヒープ」を使用します。
サイズが決まっていない、データは、「ヒープ」を用いることで「スタック」のメモリーを削減しようと考えたかと思います。
C言語には、固定長と、可変長の配列が存在しています。
そのため、実際には、ほとんど可変長配列を使用することになります。
可変長配列は、固定長と異なり、領域を確保し、解放する処理をプログラマーが意識する必要があります。
この処理には以下の障害が伴うため、注意が必要です。
注意が必要と記述しましたが、これを守っているソフトウェアはそんなにありません。
そのため、この処理をコンピュータが行う言語「Java等」が作成されました。
C言語で書く場合は、忘れてはいけないことです。
可変長配列は、メモリーに関わってくる話のため
ここでは解説せずにのちのち解説をしていきたいと思います。
配列って言われても、なんのことだかさっぱりかもしれません。
配列で検索をすると、プログラミングに関する話題がほとんどで
あまり使わない言葉ですが〜
配列は、変数を複数定義したものです。
int a,b,c,d,e;
5個ならまだ適当に変数名を割り当てられますが
100,200になると記述するだけで無駄な時間を過ごすことになります。
そんな時には、配列という記述を用いることで簡単に定義することが可能です。
// 型 変数名[変数個数]; int ary[5];
ただ、関係のない変数をまとめるために使用すると
設定された値の意味がわからなくなり不具合の元になるため
やめたほうがいいでしょう
int nYear, nSex, nEmpNumber; int naryEmp[3]; // 0 year 1 sex 2 empnumber
この場合は、コメントで補足しても不具合の元になると思われます。
最適な配列の使い方はどのような方法があるでしょうか?
ループ処理を中断したいときにはどうすればよいか
例えば、配列のデータを検索する場合
bool bFound = FALSE; for (int nAryIndex = 0; nAryIndex < sizeof(aryData); nAryIndex++) { if (aryData[nAryIndex] == searchData) { // 見つかった bFound = TRUE; } }
データが見つかった場合、それ以上ループを続ける必要は無く
無駄に処理をすることになります。
10000データの配列で5回目のループでデータが見つかった場合 9995回無駄になります。
とてもエコじゃない!!
この場合のエコなプログラムをどのように書けばいいか
パスが決まっているファイルを開くプログラムでよく書いてしまうバグを紹介します。
パスが決まっているファイルとは、
Windowsのファイル(cmd.exe等)や、設定ファイル(???.ini等)
#include <stdio.h> int main(int argc, char *argv[]) { char *pstrFilePath = ".setting.ini"; std::ifstream istream(pstrFilePath, std::ios::in); if (istream.fail() == true) { // ファイルのオープンに失敗 return -1; } // 読み込み処理 istream.close(); return 0; }
特定の条件で処理を行いときにはどうすればよいか
例えば、入力された数値で割り算を行うプログラムを作成する場合
z = x / y;
xとyを入力してもらうときは
xは何でも問題がないが、yは0の場合エラーになるため
yが0の場合は、処理をしないようにする必要があります。
このような場合どのようなプログラムを書けばいいか