グローバル変数
Re:グローバル変数
型と名前は同じってことは違うって解釈していいのかな?
例えば
グローバル変数としてiを定義して
ローカル関数内で同じ名前のiを定義したとしたら
ローカル関数内ではグローバル変数iは同じ名前だから使えないって
ことですか?
ここが良く分からないんです。
例えば
グローバル変数としてiを定義して
ローカル関数内で同じ名前のiを定義したとしたら
ローカル関数内ではグローバル変数iは同じ名前だから使えないって
ことですか?
ここが良く分からないんです。
Re:グローバル変数
main関数から呼ばれたiは0なので「0」と表示される。
se関数を呼び出すとiはローカル変数を宣言しただけなので不定値+1が表示されます。
結果、iの値は不定値+1です。
se関数を呼び出すとiはローカル変数を宣言しただけなので不定値+1が表示されます。
結果、iの値は不定値+1です。
Re:グローバル変数
ありがとうございます。
区別されるのは分かりましたが、
グローバル変数でiを定義して
ロール関数で同じiを定義したとしたら
ローカル関数でグローバル変数で定義したiは使えるんですか?
ここをお願いします。
区別されるのは分かりましたが、
グローバル変数でiを定義して
ロール関数で同じiを定義したとしたら
ローカル関数でグローバル変数で定義したiは使えるんですか?
ここをお願いします。
Re:グローバル変数
> ローカル関数でグローバル変数で定義したiは使えるんですか?
使えるかどうかでいえば使えます。
どう使えるかは、環境とどう使いたいのかによります。
規約に沿って情報を補足していただければ、もっと具体的な回答ができるかもしれません。
使えるかどうかでいえば使えます。
どう使えるかは、環境とどう使いたいのかによります。
規約に沿って情報を補足していただければ、もっと具体的な回答ができるかもしれません。
Re:グローバル変数
コンパイルして実行するとランタイムエラーが発生します。
出力ウィンドウは以下のとおりになります。
warning C4700: 値が割り当てられていないローカルな変数 'i' に対して参照が行われました。
se関数のint i;を消して実行すると以下のようになります。
出力ウィンドウは以下のとおりになります。
warning C4700: 値が割り当てられていないローカルな変数 'i' に対して参照が行われました。
se関数のint i;を消して実行すると以下のようになります。
0 0 0
Re:グローバル変数
>あらら、環境によっては使えるのですか?
C++でスコープ解決演算子でのグローバル参照なら出来ると思いますが、たかぎさんそういう意味ですよね?
違ったらごめんなさい。
C++でスコープ解決演算子でのグローバル参照なら出来ると思いますが、たかぎさんそういう意味ですよね?
違ったらごめんなさい。
Re:グローバル変数
> C++でスコープ解決演算子でのグローバル参照なら出来ると思いますが、たかぎさんそういう意味ですよね?
> 違ったらごめんなさい。
ブロック内でextern宣言するんだと思う。
> 違ったらごめんなさい。
ブロック内でextern宣言するんだと思う。
Re:グローバル変数
さっき指摘し忘れましたが、ローカル関数というのは何でしょうか?
GCC拡張で使える
あるいは、C++で、
「ロール関数」はローカル関数の打ち間違いですよね?
どちらにしても、グローバル変数をローカル関数内で同名の変数を定義したとしても、使えるといえば使えます。
softyaさんやhogeさんの方法でもよいですし、他の方法もあります。
iという名前で参照したいのか、オブジェクトを参照できればよいのかによっても話が変わってきます。
GCC拡張で使える
void foo(void) { void bar(void) { } bar(); }のようなものでしょうか?
あるいは、C++で、
void foo() { static local { static void bar() { } }; local::bar(); }のようなものでしょうか?
「ロール関数」はローカル関数の打ち間違いですよね?
どちらにしても、グローバル変数をローカル関数内で同名の変数を定義したとしても、使えるといえば使えます。
softyaさんやhogeさんの方法でもよいですし、他の方法もあります。
iという名前で参照したいのか、オブジェクトを参照できればよいのかによっても話が変わってきます。
Re:グローバル変数
>ブロック内でextern宣言するんだと思う。
あっ、その手がありますね。
ひねりすぎました(^^ゞ
>warning C4700: 値が割り当てられていないローカルな変数 'i' に対して参照が行われました。
iに初期値が無いからです。
>se関数のint i;を消して実行すると以下のようになります。
ローカル変数とグローバル変数のスコープを理解するプログラムでは無くなってしまうので、消したら意味無いですね。
int i=1;
と記述してください。これで値が割り当てられるのでエラーではなくなります。
●とにかく規約テンプレに従って、自分の学んでいる言語や状況を明確にしてください。
そうしないと話がどんどん難しい方向へ流れていって、質問者ご本人の理解できない話になってしまう可能性が高いです。
[1] 質問文
[1.1] 自分が今行いたい事は何か
[1.2] どのように取り組んだか(プログラムコードがある場合記載)
[1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
[1.4] 今何がわからないのか、知りたいのか
[2] 環境
[2.1] OS : Windows, Linux等々
[2.2] コンパイラ名 : VC++ 2008EE, Borand C++, gcc等々
[2.3] 使用言語:C(90,99),C++,C#,VB,JAVA等々詳細にお願いします。
[3] その他
・どの程度C言語を理解しているか。言語を勉強してからの期間や自分で思う習得レベル(3ヶ月。初心者)
・ライブラリを使っている場合は何を使っているか
あっ、その手がありますね。
ひねりすぎました(^^ゞ
>warning C4700: 値が割り当てられていないローカルな変数 'i' に対して参照が行われました。
iに初期値が無いからです。
>se関数のint i;を消して実行すると以下のようになります。
ローカル変数とグローバル変数のスコープを理解するプログラムでは無くなってしまうので、消したら意味無いですね。
int i=1;
と記述してください。これで値が割り当てられるのでエラーではなくなります。
●とにかく規約テンプレに従って、自分の学んでいる言語や状況を明確にしてください。
そうしないと話がどんどん難しい方向へ流れていって、質問者ご本人の理解できない話になってしまう可能性が高いです。
[1] 質問文
[1.1] 自分が今行いたい事は何か
[1.2] どのように取り組んだか(プログラムコードがある場合記載)
[1.3] どのようなエラーやトラブルで困っているか(エラーメッセージが解る場合は記載)
[1.4] 今何がわからないのか、知りたいのか
[2] 環境
[2.1] OS : Windows, Linux等々
[2.2] コンパイラ名 : VC++ 2008EE, Borand C++, gcc等々
[2.3] 使用言語:C(90,99),C++,C#,VB,JAVA等々詳細にお願いします。
[3] その他
・どの程度C言語を理解しているか。言語を勉強してからの期間や自分で思う習得レベル(3ヶ月。初心者)
・ライブラリを使っている場合は何を使っているか
Re:グローバル変数
>ブロック内でextern宣言するんだと思う。
あーこういうことですか?使ったことがないので、思いつきませんでした。
あーこういうことですか?使ったことがないので、思いつきませんでした。
#include <stdio.h> int i=1; int main(void) { int i=2; { extern int i; printf("%d\n",i); } printf("%d\n",i); return 0; }
Re:グローバル変数
なかなか情報を補足してくれないようですが、大して急いでいないようなので、以後は質問者さんを置き去りにして話を進めます。
すでに出ている方法(::iとする、ブロック内でextern宣言する)以外にも次のようなものが考えられます。
まずは名前を参照するための方法です。
- 関数内の i は、複合文の中で定義する。
- 関数内で i を定義する前に、非局所オブジェクトの i を使う
- インラインアセンブラを使う
- (ほとんど屁理屈ですが)i を定義したローカル関数とは別のローカル関数で非局所オブジェクトの i を参照する
次にオブジェクトを参照するための方法です。
- リンカスクリプトその他の方法で、非局所オブジェクト i にエイリアスを設定する
- C++であれば、int& j = i; のように参照を作っておく
- ポインタを介してアクセスする
- 他のオブジェクトのアドレスから、i のアドレスを求める(未定義ですが、処理系によっては可能)
- i を、アドレスが特定できる特定のセクションに配置する
- i にグローバルレジスタを割付け、関数内ではレジスタを参照する処理系定義の方法を使う
といったところでしょうか?
すでに出ている方法(::iとする、ブロック内でextern宣言する)以外にも次のようなものが考えられます。
まずは名前を参照するための方法です。
- 関数内の i は、複合文の中で定義する。
- 関数内で i を定義する前に、非局所オブジェクトの i を使う
- インラインアセンブラを使う
- (ほとんど屁理屈ですが)i を定義したローカル関数とは別のローカル関数で非局所オブジェクトの i を参照する
次にオブジェクトを参照するための方法です。
- リンカスクリプトその他の方法で、非局所オブジェクト i にエイリアスを設定する
- C++であれば、int& j = i; のように参照を作っておく
- ポインタを介してアクセスする
- 他のオブジェクトのアドレスから、i のアドレスを求める(未定義ですが、処理系によっては可能)
- i を、アドレスが特定できる特定のセクションに配置する
- i にグローバルレジスタを割付け、関数内ではレジスタを参照する処理系定義の方法を使う
といったところでしょうか?
Re:グローバル変数
たかぎさん。イメージが湧きません。
もうしわけありませんが、サンプルを載せてもらえませんか?
自分なりに作ってみました。
- 関数内の i は、複合文の中で定義する。
ブロック内でローカル変数を定義したら、そのブロックの外の範囲は
グローバル変数が選択されているという意味でしょうか?
Cだと限定すると、こんな感じですか。
インラインアセンブラは、使ったことがありませんのでパス。
- (ほとんど屁理屈ですが)i を定義したローカル関数とは別のローカル関数で非局所オブジェクトの i を参照
これ、わからないです。ローカル関数?
サンプル下さい。
オブジェクト参照はまた、今度。
もうしわけありませんが、サンプルを載せてもらえませんか?
自分なりに作ってみました。
- 関数内の i は、複合文の中で定義する。
ブロック内でローカル変数を定義したら、そのブロックの外の範囲は
グローバル変数が選択されているという意味でしょうか?
#include <stdio.h> int i=1; int main(void) { printf("%d\n",i); { int i=2; printf("%d\n",i); } return 0; }- 関数内で i を定義する前に、非局所オブジェクトの i を使う
Cだと限定すると、こんな感じですか。
#include <stdio.h> int i=1; int main(void) { int a=i; int i=2; printf("%d\n",i); printf("%d\n",a); return 0; }- インラインアセンブラを使う
インラインアセンブラは、使ったことがありませんのでパス。
- (ほとんど屁理屈ですが)i を定義したローカル関数とは別のローカル関数で非局所オブジェクトの i を参照
これ、わからないです。ローカル関数?
サンプル下さい。
オブジェクト参照はまた、今度。
Re:グローバル変数
nonさん
最初の2つは書かれている通りです。
インラインアセンブラの場合、asm("... i ..."); のように、多くの場合、名前で参照可能です。
ただし、_i のように、若干シンボルが加工される可能性はあります。
また、C++の場合には、マングリングが行われる可能性もあります。
> - (ほとんど屁理屈ですが)i を定義したローカル関数とは別のローカル関数で非局所オブジェクトの i を参照
> これ、わからないです。ローカル関数?
> サンプル下さい。
同じローカル関数とは書いていないので、屁理屈をいえば、こういうのもありです。
最初の2つは書かれている通りです。
インラインアセンブラの場合、asm("... i ..."); のように、多くの場合、名前で参照可能です。
ただし、_i のように、若干シンボルが加工される可能性はあります。
また、C++の場合には、マングリングが行われる可能性もあります。
> - (ほとんど屁理屈ですが)i を定義したローカル関数とは別のローカル関数で非局所オブジェクトの i を参照
> これ、わからないです。ローカル関数?
> サンプル下さい。
int i = 123;; void foo() { void f() { int i = 456; printf("%d\", i); } void g() { printf("%d\n", i); } f(); g(); }のようなケースです。ローカル関数(入れ子関数)f で i を定義していますが、別のローカル関数 g では関数外の i を参照できます。
同じローカル関数とは書いていないので、屁理屈をいえば、こういうのもありです。
Re:グローバル変数
ちょっと補足
> - 関数内の i は、複合文の中で定義する。
については、C限定でも次のように書けます。
> - 関数内の i は、複合文の中で定義する。
については、C限定でも次のように書けます。
#include <stdio.h> int i = 1; int main(void) { { int i = 2; printf("%d\n", i); } printf("%d\n", i); }つまり、関数内で定義した i を使いたい範囲だけブロックで囲んでやれば、それ以外では普通に関数外の i にアクセスできます。
Re:グローバル変数
これって、BCCではエラーになりますけど、BCCが悪いのですか?
GCCは職場のパソコンにしか入ってないので、試してません。
>> - 関数内の i は、複合文の中で定義する。
>については、C限定でも次のように書けます。
これは理解できてます。
GCCは職場のパソコンにしか入ってないので、試してません。
int i = 123;; void foo() { void f() { int i = 456; printf("%d\", i); } void g() { printf("%d\n", i); } f(); g(); }ちなみに、これならうまく動きます。
int i = 123;; void foo() { void f(); void g(); f(); g(); } void f() { int i = 456; printf("%d\", i); } void g() { printf("%d\n", i); }>ちょっと補足
>> - 関数内の i は、複合文の中で定義する。
>については、C限定でも次のように書けます。
これは理解できてます。
Re:グローバル変数
nonさん
> これって、BCCではエラーになりますけど、BCCが悪いのですか?
前述したようにGCCの独自拡張ですので、普通のCコンパイラではコンパイルできません。
GCCでもC++では使えないはずです。
手軽にGCCを使うなら、
http://files.7d9.org/mingw32-core-4_4_1 ... 091113.zip
を使ってみてください。
解凍してバッチを実行するだけで使えます。
「ローカル関数」というのが、Cではこれ以外には思い当たらないのです。
> これって、BCCではエラーになりますけど、BCCが悪いのですか?
前述したようにGCCの独自拡張ですので、普通のCコンパイラではコンパイルできません。
GCCでもC++では使えないはずです。
手軽にGCCを使うなら、
http://files.7d9.org/mingw32-core-4_4_1 ... 091113.zip
を使ってみてください。
解凍してバッチを実行するだけで使えます。
「ローカル関数」というのが、Cではこれ以外には思い当たらないのです。
Re:グローバル変数
たかぎさん
GCCの独自拡張ですか、なるほど。
紹介していただいたのをダウンロードし、GCCでは、うまく行きました。
関数の中に関数の本体を書くことに何かいいことがあるのでしょうか?
利点がわかりません。
GCCの独自拡張ですか、なるほど。
紹介していただいたのをダウンロードし、GCCでは、うまく行きました。
関数の中に関数の本体を書くことに何かいいことがあるのでしょうか?
利点がわかりません。
Re:グローバル変数
> 関数の中に関数の本体を書くことに何かいいことがあるのでしょうか?
関数の中で使う下請関数を入れ子にすることで、ある意味 "private" な関数を作ることができます。
具体的に分かりやすい例を挙げると、qsortやbsearchに渡す比較関数を入れ子関数にすれば、下請関数(ここでは比較関数)をファイル有効範囲に出さなくても済みます。
ただ、入れ子関数は、便利にしすぎたこともあって、使い方次第ではオーバーヘッドやその他の弊害も出ます。
本当に入れ子関数が欲しいのは、どちらかといえばC++のほうです。
アルゴリズム関数の述語にするのに使いたいのですが、GCCでもC++では入れ子関数が使えません。
ローカルクラスとしてファンクタを作ってもエラーになってしまうので、どうしようもありませんね。
関数の中で使う下請関数を入れ子にすることで、ある意味 "private" な関数を作ることができます。
具体的に分かりやすい例を挙げると、qsortやbsearchに渡す比較関数を入れ子関数にすれば、下請関数(ここでは比較関数)をファイル有効範囲に出さなくても済みます。
ただ、入れ子関数は、便利にしすぎたこともあって、使い方次第ではオーバーヘッドやその他の弊害も出ます。
本当に入れ子関数が欲しいのは、どちらかといえばC++のほうです。
アルゴリズム関数の述語にするのに使いたいのですが、GCCでもC++では入れ子関数が使えません。
ローカルクラスとしてファンクタを作ってもエラーになってしまうので、どうしようもありませんね。
Re:グローバル変数
そいえば、昔昔のそのまた昔、PascalやModela-2を使ったとき手続きや関数を入れ子にできた
記憶を思い出しました。昔の言語にはそういう考えがあったのでしょう。
C++なら確かにprivateにすることに意味がありそうなのに、C++で使えなくなったのは面白いですね。
クラスの考えが出てきたときに、消滅しちゃたんでしょうね。
記憶を思い出しました。昔の言語にはそういう考えがあったのでしょう。
C++なら確かにprivateにすることに意味がありそうなのに、C++で使えなくなったのは面白いですね。
クラスの考えが出てきたときに、消滅しちゃたんでしょうね。
Re:グローバル変数
> クラスの考えが出てきたときに、消滅しちゃたんでしょうね。
そうでもありません。
C++0xではラムダ式が使えるようになりましたので、これが入れ子関数に取って代わるのかな、と考えています。
そうでもありません。
C++0xではラムダ式が使えるようになりましたので、これが入れ子関数に取って代わるのかな、と考えています。
Re:グローバル変数
>C++0x
初めて知りました。また、新しい標準が出るのですね。
ラムダ式・・・・?少し記事を読みましたが・・・???
まぁ、その前にC++を使いこなせるようにならないとですね。
初めて知りました。また、新しい標準が出るのですね。
ラムダ式・・・・?少し記事を読みましたが・・・???
まぁ、その前にC++を使いこなせるようにならないとですね。
Re:グローバル変数
前半の流れは詳しく読んでませんが、(興味があるので詳しく読みますが、)
>C++0x
nonさんが知らないなんて少し驚いてます。
これに関してはいくつかこの掲示板でもつついたことがあったと思います。(多分、私が)
>ラムダ式
関数型言語界隈ではよくつかわれている概念らしいんですけどね。
日本語では無名関数でしたっけ、boostでライブラリを実装していたとおもいます。(私は使ったことがありませんが)
最新のVSでも実装していたとおもいます。(これはどこかのblogに載ってたような記憶が。)
#2009年中に完成させるつもりで0xとつけたという話を聞いたことがあるのですが、本当に2009年中にでるんでしょうかね。
>C++0x
nonさんが知らないなんて少し驚いてます。
これに関してはいくつかこの掲示板でもつついたことがあったと思います。(多分、私が)
>ラムダ式
関数型言語界隈ではよくつかわれている概念らしいんですけどね。
日本語では無名関数でしたっけ、boostでライブラリを実装していたとおもいます。(私は使ったことがありませんが)
最新のVSでも実装していたとおもいます。(これはどこかのblogに載ってたような記憶が。)
#2009年中に完成させるつもりで0xとつけたという話を聞いたことがあるのですが、本当に2009年中にでるんでしょうかね。
Re:グローバル変数
> boostでライブラリを実装していたとおもいます。
Boost C++ Librariesのものよりずっと使い勝手がよさそうです。
Visual C++ 2010のほか、GCC 4.5.xでも使えるはずです。
> #2009年中に完成させるつもりで0xとつけたという話を聞いたことがあるのですが、本当に2009年中にでるんでしょうかね。
今年中に出ないことは確定していますが、C++0xという仮称はそのまま使うようです。
Boost C++ Librariesのものよりずっと使い勝手がよさそうです。
Visual C++ 2010のほか、GCC 4.5.xでも使えるはずです。
> #2009年中に完成させるつもりで0xとつけたという話を聞いたことがあるのですが、本当に2009年中にでるんでしょうかね。
今年中に出ないことは確定していますが、C++0xという仮称はそのまま使うようです。