C言語関係掲示板

過去ログ

No.145.変数のアドレスを固定にしたい


No.926

変数のアドレスを固定
投稿者---組み込み見習い(2002/01/25 13:55:43)


グローバル変数が数多くあるのですが、都合があって各変数のアドレスが変わらないようにしたいです。
新しく変数を追加してコンパイル&リンクして、前からある変数のアドレスが変わっては困るわけです。
コンパイラの#pragma指令を調べてみましたが、残念ながらアドレス指定をするようなものはありませんでした。
なにかいい解決方法はないでしょうか。

自分なりに考えてみたのが↓です。
グローバル変数が1つしかなければ変わりようがないだろうと考えました。
しかし考えに見落としがありそうで不安です。
それにこれでは変数を追加するごとに全ソース再コンパイルになってしまいます。
よろしくお願いします。

/* data.h */
typedef struct {
    short dmy000;       /*000:*/
    short dmy002;       /*002:*/
    :
    short dmy0FE;       /*0FE:*/
    short acv;          /*100: 交流電圧(0.1V)       */
    short aci;          /*102: 交流電流(0.01A)      */
    short acw;          /*104: 交流電力(1W)         */
    short dmy106;       /*106:*/
    :
    short dmy1FE;       /*1FE:*/
    short dcv;          /*200: 直流電圧(0.1V)       */
    short dci;          /*202: 直流電流(0.01A)      */
    short dcw;          /*204: 直流電力(1W)         */
    :
    long  freq;         /*300: 周波数(1/16384Hz)    */
    long  acw_hour;     /*304: 積算電力量(1kWh)     */
    :
} Data;
extern Data data;

/* data.c */
#include "data.h"
Data data;



No.937

Re:変数のアドレスを固定
投稿者---shu(2002/01/25 22:43:19)


>グローバル変数が数多くあるのですが、都合があって各変数のアドレスが変わらないようにしたいです。

グローバル変数が数多くあることが問題のような気がしますが、
static 宣言すれば、プログラムの終了まで変数の場所はかわりません。

No.939

Re:変数のアドレスを固定
投稿者---組み込み見習い(2002/01/26 00:55:54)


レスありがとうございます。

> グローバル変数が数多くあることが問題のような気がしますが、
auto変数はスタックを消費するので割り込みでの消費を考慮するとほとんど使えないんです。
static宣言は変数名が英字+数字の意味不明なものに変形されてしまってマップファイルを見ても配置アドレスがわかりません。
これではデバッグに不都合なのでグローバル変数を多用しています。

> static 宣言すれば、プログラムの終了まで変数の場所はかわりません。
プログラムの終了までではなく、
  プログラミング→コンパイル&リンク→プログラミング→コンパイル&リンク…
これを何度繰り返しても変数の配置アドレスが変わらない方法を考えています。
アセンブラは訳あって使えないんです。。

わかりにくかったらごめんなさい。
助言おねがいします。

# Windowsツール作成用にDelphiも勉強しているんですが、
# これはabsoluteってキーワードで言語レベルでアドレス指定に対応してるんですね。
# てっきりアプリケーション用言語だと思ってたんで驚きました。


No.941

Re:変数のアドレスを固定
投稿者---shu(2002/01/26 09:43:17)


>プログラムの終了までではなく、
>  プログラミング→コンパイル&リンク→プログラミング→コンパイル&リンク…
>これを何度繰り返しても変数の配置アドレスが変わらない方法を考えています。
>アセンブラは訳あって使えないんです。。
>

ポインタに指定のアドレスを代入して、
そこから動的確保じゃだめでしょうか?

># Windowsツール作成用にDelphiも勉強しているんですが、
># これはabsoluteってキーワードで言語レベルでアドレス指定に対応してるんですね。
># てっきりアプリケーション用言語だと思ってたんで驚きました。

う〜〜ん、Delphiのことは良くわかりませんが、
余裕があったら勉強してみたいです。


No.944

Re:変数のアドレスを固定
投稿者---B.Smith(2002/01/26 13:21:50)


こんにちは。

メモリの位置を移動したくないのであれば、使用するメモリをまとめて確保してしまい、使用時に切り分けるようにするのが良いと思います。そういう意味で、「構造体を使用する」のは良い方法だと思いますよ。

確かに、今回はヘッダに構造体を定義しているため、メンバを追加する毎に全コンパイルが必要になります。デバッグ時のみ、全コンパイルを避けたいのであれば、あらかじめ変数をいくつか予約しておくことです。
例.
typedef struct   {
             ・
             ・
             ・
    long  Reserve1;     /* 将来のため予約 */
    long  Reserve2;     /* 将来のため予約 */
    long  Reserve3;     /* 将来のため予約 */
    long  Reserve4;     /* 将来のため予約 */
    long  Reserve5;     /* 将来のため予約 */
} Data;

変数が必要になったら、これら予約してある変数を使用することで、全コンパイルをある程度回避することはできます。変数の型は、ポインタも格納できるlongがよろしいと思います。
最終的には、使用している予約分の変数名を変更し、不必要な変数を削除した上で全部MAKEしなければなりませんが、リリースする際の全コンパイルは必要なことですから、特に問題は無いと思います。

すべての変数を、同じ型に統一できる場合は、思い切って配列にしてしまうのも、一つの手です。メモリ配置という点で、原理的には上記の構造体と同じですが、時と場合によっては、使用している変数をインデックス、あるいはポインタによりまとめて処理できる、といったメリットがあります。
ただ、メンテナンスし辛くなってしまうので、周囲にはあまり喜ばれませんけど…

デバッグが終了して、リリースするために全部MAKEしてみたら、動作がおかしかった…ということが発生する場合があります。このようなリンクの問題は、特にグローバル変数を複数のオブジェクトから参照している場合に良く起り、また発見し辛いので、例えば複数チームで一つのシステムを構築している場合のような大規模なものでない限り、デバッグ時の手間を惜しまない方が良いと思います。後の大問題を回避するためならば安い代償です。


No.952

Re:変数のアドレスを固定
投稿者---組み込み見習い(2002/01/26 23:36:39)


shuさん、B.Smithさん ありがとうございます。

>shuさん

> ポインタに指定のアドレスを代入して、
> そこから動的確保じゃだめでしょうか?
これができたらいいんですけど、malloc系では無理ですよね??

> う〜〜ん、Delphiのことは良くわかりませんが、
> 余裕があったら勉強してみたいです。
まだ始めたばかりですけど、かなりいい感じです。
今までツール作成はVC+MFCだったんですけど、Delphi+VCLを知ってしまったからにはもう戻れそうもありません。
かなりお勧めできるWindows開発環境だと思います。

>B.Smithさん
部分引用ですがご了承くださいませ。

> メモリの位置を移動したくないのであれば、…
ありがとうございます。
考え方に勘違いがないか不安だったんで安心しました。
ただ、一つ不安なことがあるのですが、標準ライブラリでもグローバル変数って使われてますよね。
インクルードするとそれらもリンクされてしまって配置がずれるといったことはないのでしょうか?リンカへの理解が足りなくて、まだこのあたりがよくわからないです。

> デバッグが終了して、…
言い訳みたいになってしまって恥ずかしいのですが。
リリース後に不具合がでた場合、その問題の出た機器だけでデバッグできるように、シリアル通信でアドレスとサイズを送るとそのアドレスの値を返すように組んであります。
その機器でしか再現しないバグとかもあるので、これはどうしても必要なんです。
なので変数はほとんどグローバル、static宣言もできないという感じです。
はずしてたらごめんなさい。


No.953

Re:変数のアドレスを固定
投稿者---B.Smith(2002/01/27 01:36:19)


標準ライブラリを使用するんですか?
その場合、アドレスは変わりますので注意してください。
例えば、isalpha、isspace、isprintのような文字分類関数は、グローバルで256文字分の領域を持っています。strtokは、内部で静的な領域を持っています。また、(使う可能性は低いかもしれませんが)ecvt、fcvt、asctime、gmtime、localtime等は、処理結果を内部の静的領域に格納し、そのポインタを呼び出し元に返しています。呼び出されれば、当然リンクされてしまうので、アドレスが変わります。
ただし、これらの内容は、お使いのライブラリに依存しますので、まず実験で確認してみてください。

標準ライブラリを使用するのであれば、アドレスが変わることを、ある程度覚悟しておいた方が良いです。使用することで問題がある場合は、自分で代替関数を用意するしかありません。しかし、システムの要求するパフォーマンスが得られる機能を設計するように注意すれば、作成すること自体は難しいことではありません。

Visual C++をやったことがあるんですよね?(あるいは今も使ってるのかもしれませんが)
インストール時にCRTソースコードのインストールを指定していれば、標準ライブラリのソースを見ることができます。標準ライブラリの代替関数を作成するための良い参考資料になると思います。

>その機器でしか再現しないバグとかもあるので、これはどうしても必要なんです。
組み込みの醍醐味ですね。
どのようなシステムを作成されているかは分かりませんが、完成すれば、貴方の作成したシステムは、実際に世の中で使用されることになります。これをプレッシャーとしてとらえずに、作ることを楽しんでください。きっと、今にも増して良いものができると思いますよ。



No.954

Re:変数のアドレスを固定
投稿者---組み込み見習い(2002/01/27 02:17:45)


懇切丁寧なレスほんとに感謝です。

> 呼び出されれば、当然リンクされてしまうので、アドレスが変わります。
そうでしたか。
たとえば、標準ヘッダを用意してそこですべての標準ライブラリヘッダをインクルードしておいたらどうかなとか思ってます。
それとも、宣言だけではなく実際に呼び出すコードがないとリンクされないのでしょうか?
今度実験してみますが、一般的にはどうなのでしょうか。
ライブラリ自作は苦になりません(むしろ好きです)が、完全にバグがない確信を得たものを用意するまでにはずいぶん時間かかりそうなので今回は無理そうです。

> 標準ライブラリのソースを見ることができます。
printf系の実装とか前から興味あったんです。
ありがとうございます。すごく楽しみです。

> 組み込みの醍醐味ですね。
はい、ハードの個体差にソフト側でどう柔軟に対処するかとかなかなか楽しいです。
ただ、一般的に綺麗と呼ばれるコードにしにくいのがあれですけど。
これもなんとかしたいといろいろ考えてたりします。


戻る


「初心者のためのポイント学習C言語」 Last modified:2002.03.06
Copyright(c) 2000-2002 TOMOJI All Rights Reserved