C言語において
int a = 1; // 動的グローバル変数
static int b = 2; //静的グローバル変数
funcA(){
int c = 3; // 動的ローカル変数
static int d = 4; //静的グローバル変数
・
・
・
}
上記のように各種変数を初期化したとします。
"c"のような動的ローカル変数であれば、funcA()が呼ばれたときに毎回初期化されますよね?
では
・"d"のような静的ローカル変数は、初めてfuncA()が呼ばれたときに初期化されるのですか?
・"a","b"のyほうなグローバル変数は、どのタイミングで初期化されるのですか?
以上2点について伺いたいと思います。
ちなみに、組み込み機器むけのソフトウェアを想定しています。
No.2
- 回答日時:
>・"d"のような静的ローカル変数は、初めてfuncA()が呼ばれたときに初期化されるのですか?
そう思って良いでしょう。実際のタイミングはmain()実行の直前と思いますが、同じ事です。
>・"a","b"のyほうなグローバル変数は、どのタイミングで初期化されるのですか?
これもmain()実行の直前です。
ちなみに、グローバル変数に、静的・動的の区別はなく強いて言えばすべて静的です。そうするとstaticキーワードの意味が余るので、名前の有効活用の意味で関数やグローバル変数に付けられたstaticキーワードは別の意味を持ちます。「グローバルだけど他のファイルで定義された関数からはアクセスできない」という意味です。ローカル変数の動的・静的とは関係ありませんので、本来は別のキーワードを使えば混乱がなかったと思いますが、予約語を増やしたくなかったんでしょう。
No.3
- 回答日時:
>int a = 1; // 動的グローバル変数
>static int b = 2; //静的グローバル変数
関数外で宣言された変数はstaticと解釈されますので、
上記の記述に差はありません。
ちなみに、動的グローバル変数という言葉は聞いた事がありません。
staticと解釈された関数や変数はプログラムが実行される際に、
メモリにその領域が確保されます。
一方、dynamicと解釈された関数や変数は、
呼ばれたときにメモリに領域が確保されます。
ご提示いただいた変数でいうと、
a、b、dはプログラムが開始されたときに領域確保+初期化され、
cは関数開始時に領域確保+初期化されるはずです。
No.1の方がおっしゃるように、一度試されるとよいでしょう。
No.4
- 回答日時:
> >int a = 1; // 動的グローバル変数
> >static int b = 2; //静的グローバル変数
> 関数外で宣言された変数はstaticと解釈されますので、
> 上記の記述に差はありません。
そんなことはないです。明確な違いがあります。
下記のサンプルコードで試してみてください。
// temp.c
#include <stdio.h>
int a = 1;
static int b = 2;
void func(void);
int main(void)
{
func();
return 0;
}
// temp-2.c
#include <stdio.h>
extern int a;
extern int b;
void func(void)
{
printf("a=%d\n", a);
printf("b=%d\n", b);
}
func()において、どこか別のファイルで定義した変数a, bの内容を
出力しようとしています。
変数aは正しく認識できますが、変数bはtemp.cの外からは見えません。
リンク時に「外部シンボル未解決」というエラーが出ます。
No.5
- 回答日時:
> dはプログラムが開始されたときに領域確保+初期化され、
これも正しくないですね。
dはあくまでも関数内のローカル変数ですから、
当該関数の実行時に領域確保と初期化を行ないます。
仮に、当該プログラムが一度も当該関数を実行しないとすると、
dのための領域は当該プログラムの実行中確保されません。
staticが付いているから、一度領域を確保すると、
当該プログラムの実行中ずっとその内容を保持している、というだけです。
No.6
- 回答日時:
組み込み向けですよね。
どのコンパイラか分からないので一般論ですが、通常はデータセクションに最初から埋め込まれています。
データセクションはROM領域に乗るのが普通なので、何らかの方法でRAMにコピーして使います。大抵はブートコードでコピーするはずです。
どのタイミングといわれれば、コンパイル時かブート時ということでいいんじゃないでしょうか。
No.7
- 回答日時:
★アドバイス
組み込み系は詳しくありませんので一般論で回答しておきます。注意。
・次のリンクの
『セクションとか.textとか』
『初期化してない変数とか.bssセクションとか 』
を読んでみて下さい。
http://www.ertl.jp/~takayuki/readings/info/→『「infoを読め」と言われたら...』
さらに詳しく知りたい場合は『BSS セクション』で検索してみましょう。
>"c"のような動的ローカル変数であれば、funcA()が呼ばれたときに毎回初期化されますよね?
↑
自動変数だね。
毎回初期化されます。
>"d"のような静的ローカル変数は、初めてfuncA()が呼ばれたときに初期化されるのですか?
↑
これは『a』『b』と同じくスタートアップ・ルーチンで初期化されます。
スタートアップ・ルーチンはmain()関数が呼ばれる前の処理です。
プログラムが起動した最初の1回しか初期化されません。
>"a","b"のyほうなグローバル変数は、どのタイミングで初期化されるのですか?
↑
これも『d』と同様にスタートアップ・ルーチンで初期化されます。
・最後にもう一つ次のリンクを読んでみて下さい。
http://www.ertl.jp/~takayuki/readings/c/no10.html→『初めてのC言語 - 第10回 三度目のスタートアップ』
No.8
- 回答日時:
a, b, dはいずれも静的記憶域期間を持ちます。
初期化は通常スタートアップで行います。ちなみに、aは外部結合、bは内部結合、dは無結合になります。
cは自動記憶域期間を持ちますので、funcAが呼び出され、その宣言部分に実行パスが差し掛かるたびに初期化されます。
これに関しては、組込みであろうがなかろうが関係ありません。ただし、main関数云々の話はフリースタンディング環境では通用しません。
この回答への補足
>みなさま
丁寧なご回答ありがとうございます。
"c"の自動ローカル変数に関しては、関数呼び出し時に初期化でOKのようですが
"a","b","d"に関しては意見が分かれるようですね。
まとめると
1."a","b","d"ともコンパイル時にメモリに領域が確保されると同時に初期化される。
2."a","b","d"ともスタートアップルーチン時にメモリに領域が確保されると同時に初期化される。
3."a","b"はスタートアップルーチン時、"d"は該当関数が呼ばれた時にメモリに領域が確保されると同時に初期化される。
の3種類の意見に分類できそうですが、これは環境によって初期化の方法が違うのでしょうか?
私の場合は、Winマシンでcygwinというコンパイラでコンパイルし
組み込み機器のROMにファームを焼き
機器の電源ONと同時にブートローダによってファームをROMからRAMに移す
といった処理をしています。
ちなみに機器のOSはLinuxです。
No.9
- 回答日時:
★アドバイス
>1."a","b","d"ともコンパイル時にメモリに領域が確保されると同時に初期化される。
コンパイル時ではありません。
実行されたときに初期化されます。
>2."a","b","d"ともスタートアップルーチン時にメモリに領域が確保されると同時に初期化される。
これです。
BSSセクションをすべてゼロで初期化。
その後に指定された『値』1とか2などで初期化。
この順です。
>3."a","b"はスタートアップルーチン時、"d"は該当関数が呼ばれた時にメモリに領域が確保されると同時に初期化される。
これは間違いです。
No.10
- 回答日時:
a, b, dのメモリ領域はコンパイル時に割付けられます。
より厳密に言えば、具体的なアドレスが決定するのはリンク時です。静的記憶域期間を持つ初期値付きオブジェクトは、一般的には、.dataセクションに配置され、スタートアップでROM→RAMに転送されます。ただし、今回の場合は、.textセクションのプログラムと一緒にブート時に転送されることになると思います。
ゼロクリアされるのは.bssセクション(つまり初期値無しオブジェクト)だけです。
dに関しての誤解は、C++における定数式以外の初期化子との混同ではないかと思います。例えば、
void func()
{
double y = std::sqrt(3.0);
...
}
のyは、funcが呼び出され、最初にyの宣言位置に実行パスが差し掛かったときに初期化されます。それ以前はゼロクリアされることになります。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語初心者 ポインタについて、お助けください、、 2 2023/03/15 23:50
- その他(プログラミング・Web制作) pythonのグローバル変数 2 2022/11/25 18:02
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分 1 2022/07/19 17:03
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 malloc関数を使ってください!お願いします! 最 1 2022/07/21 09:28
- C言語・C++・C# 至急お願いします。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分母 3 2022/07/19 17:09
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- C言語・C++・C# 競技プログラミングに関する質問です。 3 2022/04/03 19:51
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
<unistd.h>をVisualStudioでつ...
-
アプリケーションのDLLファイル...
-
C言語をコンパイルするとコンピ...
-
math.hに含まれる関数が使えない
-
不明なプラグマ・・・?
-
libsshのコンパイルエラー
-
Eclipseで使えるコンパイラ、リ...
-
実行ファイルが作成環境以外のP...
-
Visual Basic.NETの処理速度は6...
-
Linux(g++)とAIX(XL C++)の挙動...
-
C#で char型とstring型の比較で...
-
cygwinのgccで正常にコンパイル...
-
実行後にコンパイルに失敗しま...
-
ビープ音が鳴りません・・・
-
c言語です コンパイルした時に...
-
#If True Then の # って何??
-
define文のパラメータを実行時...
-
Verilog_HDLでのdefineとifdef
-
ヘッダーファイル『windows.h』...
-
VBで作成したOCXでバージョンが...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
<unistd.h>をVisualStudioでつ...
-
アプリケーションのDLLファイル...
-
C言語をコンパイルするとコンピ...
-
実行後にコンパイルに失敗しま...
-
math.hに含まれる関数が使えない
-
ビープ音が鳴りません・・・
-
c言語です コンパイルした時に...
-
<math.h>ヘッダを入力している...
-
C#で char型とstring型の比較で...
-
共有ライブラリの内容確認について
-
すべてのリビルド: 0 正常、 0 ...
-
[COBOL] ソースの復帰
-
64ビットのlinuxで32ビットメモ...
-
VS2010環境で2点ほど質問
-
gcc バージョン違いによるコン...
-
ヘッダーファイル『windows.h』...
-
C言語で作ったらWindowsでもMac...
-
自作DLLの中身を暗号化
-
MVSマシンで0C7でABENDしたので...
-
Verilog_HDLでのdefineとifdef
おすすめ情報