グローバル変数

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
初心者

グローバル変数

#1

投稿記事 by 初心者 » 15年前

#include <stdio.h>

void se(void);

int i;

int main(void)
{
   
   printf("%d\n",i);

   se();
printf("%d\n",i);

return 0;
}

void se(void)
{
   int i;
i=i+i;
   printf("%d\n",i);
}
グローバル変数があまりしてないんですが。
例えば上の例でグローバル変数iを定義してse関数内でiを定義しています。
se関数内のiとグローバル変数のiは同じですか?異なるのですか?

通り

Re:グローバル変数

#2

投稿記事 by 通り » 15年前

やはりこれだけ派手にpreタグを使うように表示されてても見ない人はみないね

たかぎ

Re:グローバル変数

#3

投稿記事 by たかぎ » 15年前

> se関数内のiとグローバル変数のiは同じですか?異なるのですか?

型と名前は同じ。
アドレスと有効範囲と生存期間は異なる。

初心者

Re:グローバル変数

#4

投稿記事 by 初心者 » 15年前

型と名前は同じってことは違うって解釈していいのかな?

例えば
グローバル変数としてiを定義して
ローカル関数内で同じ名前のiを定義したとしたら
ローカル関数内ではグローバル変数iは同じ名前だから使えないって
ことですか?
ここが良く分からないんです。

Naohiro19

Re:グローバル変数

#5

投稿記事 by Naohiro19 » 15年前

main関数から呼ばれたiは0なので「0」と表示される。
se関数を呼び出すとiはローカル変数を宣言しただけなので不定値+1が表示されます。
結果、iの値は不定値+1です。

初心者

Re:グローバル変数

#6

投稿記事 by 初心者 » 15年前

ありがとうございます。

区別されるのは分かりましたが、
グローバル変数でiを定義して
ロール関数で同じiを定義したとしたら
ローカル関数でグローバル変数で定義したiは使えるんですか?
ここをお願いします。

non

Re:グローバル変数

#7

投稿記事 by non » 15年前

Cでは、隠蔽されるので使えません。

たかぎ

Re:グローバル変数

#8

投稿記事 by たかぎ » 15年前

> ローカル関数でグローバル変数で定義したiは使えるんですか?

使えるかどうかでいえば使えます。
どう使えるかは、環境とどう使いたいのかによります。
規約に沿って情報を補足していただければ、もっと具体的な回答ができるかもしれません。

non

Re:グローバル変数

#9

投稿記事 by non » 15年前

あらら、環境によっては使えるのですか?
知らなかった。

Naohiro19

Re:グローバル変数

#10

投稿記事 by Naohiro19 » 15年前

コンパイルして実行するとランタイムエラーが発生します。

出力ウィンドウは以下のとおりになります。
warning C4700: 値が割り当てられていないローカルな変数 'i' に対して参照が行われました。

se関数のint i;を消して実行すると以下のようになります。
0
0
0

softya

Re:グローバル変数

#11

投稿記事 by softya » 15年前

>あらら、環境によっては使えるのですか?

C++でスコープ解決演算子でのグローバル参照なら出来ると思いますが、たかぎさんそういう意味ですよね?
違ったらごめんなさい。

hoge

Re:グローバル変数

#12

投稿記事 by hoge » 15年前

> C++でスコープ解決演算子でのグローバル参照なら出来ると思いますが、たかぎさんそういう意味ですよね?
> 違ったらごめんなさい。

ブロック内でextern宣言するんだと思う。

たかぎ

Re:グローバル変数

#13

投稿記事 by たかぎ » 15年前

さっき指摘し忘れましたが、ローカル関数というのは何でしょうか?
GCC拡張で使える
void foo(void)
{
  void bar(void)
  {
  }
  bar();
}
のようなものでしょうか?
あるいは、C++で、
void foo()
{
  static local
  {
    static void bar()
    {
    }
  };
  local::bar();
}
のようなものでしょうか?
「ロール関数」はローカル関数の打ち間違いですよね?

どちらにしても、グローバル変数をローカル関数内で同名の変数を定義したとしても、使えるといえば使えます。

softyaさんやhogeさんの方法でもよいですし、他の方法もあります。
iという名前で参照したいのか、オブジェクトを参照できればよいのかによっても話が変わってきます。

softya

Re:グローバル変数

#14

投稿記事 by softya » 15年前

>ブロック内で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ヶ月。初心者)
 ・ライブラリを使っている場合は何を使っているか

non

Re:グローバル変数

#15

投稿記事 by non » 15年前

>ブロック内で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:グローバル変数

#16

投稿記事 by たかぎ » 15年前

なかなか情報を補足してくれないようですが、大して急いでいないようなので、以後は質問者さんを置き去りにして話を進めます。

すでに出ている方法(::iとする、ブロック内でextern宣言する)以外にも次のようなものが考えられます。
まずは名前を参照するための方法です。

- 関数内の i は、複合文の中で定義する。
- 関数内で i を定義する前に、非局所オブジェクトの i を使う
- インラインアセンブラを使う
- (ほとんど屁理屈ですが)i を定義したローカル関数とは別のローカル関数で非局所オブジェクトの i を参照する

次にオブジェクトを参照するための方法です。

- リンカスクリプトその他の方法で、非局所オブジェクト i にエイリアスを設定する
- C++であれば、int& j = i; のように参照を作っておく
- ポインタを介してアクセスする
- 他のオブジェクトのアドレスから、i のアドレスを求める(未定義ですが、処理系によっては可能)
- i を、アドレスが特定できる特定のセクションに配置する
- i にグローバルレジスタを割付け、関数内ではレジスタを参照する処理系定義の方法を使う

といったところでしょうか?

non

Re:グローバル変数

#17

投稿記事 by non » 15年前

たかぎさん。イメージが湧きません。
もうしわけありませんが、サンプルを載せてもらえませんか?
自分なりに作ってみました。

- 関数内の 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:グローバル変数

#18

投稿記事 by たかぎ » 15年前

nonさん
最初の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:グローバル変数

#19

投稿記事 by たかぎ » 15年前

ちょっと補足

> - 関数内の i は、複合文の中で定義する。

については、C限定でも次のように書けます。
#include <stdio.h>
int i = 1;
int main(void)
{
  {
    int i = 2;
    printf("%d\n", i);
  }
  printf("%d\n", i);
}
つまり、関数内で定義した i を使いたい範囲だけブロックで囲んでやれば、それ以外では普通に関数外の i にアクセスできます。

non

Re:グローバル変数

#20

投稿記事 by non » 15年前

これって、BCCではエラーになりますけど、BCCが悪いのですか?
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:グローバル変数

#21

投稿記事 by 初級者 » 15年前

fooの中でfとgの中身を書くことはできません。
後者はそれぞれの宣言をしているだけなので、エラーは出ません。

たかぎ

Re:グローバル変数

#22

投稿記事 by たかぎ » 15年前

nonさん
> これって、BCCではエラーになりますけど、BCCが悪いのですか?

前述したようにGCCの独自拡張ですので、普通のCコンパイラではコンパイルできません。
GCCでもC++では使えないはずです。

手軽にGCCを使うなら、
http://files.7d9.org/mingw32-core-4_4_1 ... 091113.zip
を使ってみてください。
解凍してバッチを実行するだけで使えます。

「ローカル関数」というのが、Cではこれ以外には思い当たらないのです。

non

Re:グローバル変数

#23

投稿記事 by non » 15年前

たかぎさん
GCCの独自拡張ですか、なるほど。
紹介していただいたのをダウンロードし、GCCでは、うまく行きました。

関数の中に関数の本体を書くことに何かいいことがあるのでしょうか?
利点がわかりません。

たかぎ

Re:グローバル変数

#24

投稿記事 by たかぎ » 15年前

> 関数の中に関数の本体を書くことに何かいいことがあるのでしょうか?

関数の中で使う下請関数を入れ子にすることで、ある意味 "private" な関数を作ることができます。
具体的に分かりやすい例を挙げると、qsortやbsearchに渡す比較関数を入れ子関数にすれば、下請関数(ここでは比較関数)をファイル有効範囲に出さなくても済みます。
ただ、入れ子関数は、便利にしすぎたこともあって、使い方次第ではオーバーヘッドやその他の弊害も出ます。

本当に入れ子関数が欲しいのは、どちらかといえばC++のほうです。
アルゴリズム関数の述語にするのに使いたいのですが、GCCでもC++では入れ子関数が使えません。
ローカルクラスとしてファンクタを作ってもエラーになってしまうので、どうしようもありませんね。

non

Re:グローバル変数

#25

投稿記事 by non » 15年前

そいえば、昔昔のそのまた昔、PascalやModela-2を使ったとき手続きや関数を入れ子にできた
記憶を思い出しました。昔の言語にはそういう考えがあったのでしょう。
C++なら確かにprivateにすることに意味がありそうなのに、C++で使えなくなったのは面白いですね。
クラスの考えが出てきたときに、消滅しちゃたんでしょうね。

たかぎ

Re:グローバル変数

#26

投稿記事 by たかぎ » 15年前

> クラスの考えが出てきたときに、消滅しちゃたんでしょうね。

そうでもありません。
C++0xではラムダ式が使えるようになりましたので、これが入れ子関数に取って代わるのかな、と考えています。

non

Re:グローバル変数

#27

投稿記事 by non » 15年前

>C++0x
初めて知りました。また、新しい標準が出るのですね。
ラムダ式・・・・?少し記事を読みましたが・・・???
まぁ、その前にC++を使いこなせるようにならないとですね。

組木紙織

Re:グローバル変数

#28

投稿記事 by 組木紙織 » 15年前

前半の流れは詳しく読んでませんが、(興味があるので詳しく読みますが、)


>C++0x
nonさんが知らないなんて少し驚いてます。
これに関してはいくつかこの掲示板でもつついたことがあったと思います。(多分、私が)

>ラムダ式
関数型言語界隈ではよくつかわれている概念らしいんですけどね。
日本語では無名関数でしたっけ、boostでライブラリを実装していたとおもいます。(私は使ったことがありませんが)
最新のVSでも実装していたとおもいます。(これはどこかのblogに載ってたような記憶が。)




#2009年中に完成させるつもりで0xとつけたという話を聞いたことがあるのですが、本当に2009年中にでるんでしょうかね。

たかぎ

Re:グローバル変数

#29

投稿記事 by たかぎ » 15年前

> boostでライブラリを実装していたとおもいます。

Boost C++ Librariesのものよりずっと使い勝手がよさそうです。
Visual C++ 2010のほか、GCC 4.5.xでも使えるはずです。

> #2009年中に完成させるつもりで0xとつけたという話を聞いたことがあるのですが、本当に2009年中にでるんでしょうかね。

今年中に出ないことは確定していますが、C++0xという仮称はそのまま使うようです。

non

Re:グローバル変数

#30

投稿記事 by non » 15年前

>>C++0x
>nonさんが知らないなんて少し驚いてます。

私、みなさんが思っている以上に、骨董品ですから・・・

閉鎖

“C言語何でも質問掲示板” へ戻る