質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

4825閲覧

「C言語」ヘッダーに書いたstatic int 変数がそのファイルの外からでもアクセス出来てしまう。

退会済みユーザー

退会済みユーザー

総合スコア0

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2021/05/03 06:48

提示コードですがなぜstaticグローバル変数はそのファイルのみしか使えないのにその外でも利用できるのでしょうか?

引用 [ グローバル変数にstatic修飾子を付けると、記述されたファイル内のみでの使用に制限されます。宣言、定義はソースファイルで行います。ヘッダーファイルでstatic修飾子を付けて宣言することはできません。 ]

とありますがヘッダーファイルでも宣言出来てしまうのですが...

参考サイト: https://www.sejuku.net/blog/24205#:~:text=%E3%83%AD%E3%83%BC%E3%82%AB%E3%83%AB%E5%A4%89%E6%95%B0%E3%81%A8%E3%81%AF%E9%96%A2%E6%95%B0,%E3%81%A7%E3%81%8D%E3%82%8B%E5%A4%89%E6%95%B0%E3%81%AE%E3%81%93%E3%81%A8%E3%81%A7%E3%81%99%E3%80%82

c

1#include "stdio.h" 2#include "test.h"//インクルード 3 4 5 6 7int main() 8{ 9 st = 4; 10 11 12 return 0; 13}

c

1//ヘッダーファイル 2static int st; 3 4void test();

c

1//ソースファイル 2#include "test.h" 3 4void test() 5{ 6 st = 5; 7}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/05/03 06:53

参考にしているサイトが悪いし、これまで何度も回答で説明いただいていたように、#includeプリプロセッサ命令でインクルードしているファイルが、その位置でそのファイルに展開されていることを考えれば、理由が分かるはず。
dodox86

2021/05/03 06:54

> そのファイルの外からでもアクセス出来てしまう。 できていません。確認せよ。
episteme

2021/05/03 06:59

> ヘッダーファイルでstatic修飾子を付けて宣言することはできません。 ガセネタっぽい...
guest

回答2

0

C

1#include "test.h" 2 3void test() 4{ 5 st = 5; 6}

というのは、早い話#include "test.h"のところにtest.hの内容が挿入されるだけなので

C

1//ヘッダーファイル 2static int st; 3 4void test(); 5 6void test() 7{ 8 st = 5; 9}

と同じことになります。別のCファイルでも#include "test.h"すれば、そこに

//ヘッダーファイル static int st; void test();

が挿入されるということです。

投稿2021/05/03 06:53

itagagaki

総合スコア8402

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

ヘッダファイルにstatic変数の定義を書けば、そのヘッダファイルをインクルードしてるファイルごとにその変数が定義されます。
しかも、staticであるため、そのファイル数分の変数が定義されることになります

ヘッダーファイルでstatic修飾子を付けて宣言することはできません。

できないのではなく、しても意味がないためしてはいけない、という意味ですね

投稿2021/05/03 06:52

編集2021/05/03 06:54
y_waiwai

総合スコア88042

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/05/03 06:59

> できないのではなく、しても意味がないためしてはいけない 定数を作る時にstatic constとすることはありえなくはないです。
退会済みユーザー

退会済みユーザー

2021/05/03 07:17

インクルードしたファイルごとにstatic int 変数が作られるとうい意味での利点ですね。?
y_waiwai

2021/05/03 07:19

どういう利点があると思いますか? それぞれのファイルごとに独立した変数なので、相互に関わりは全く無いです
退会済みユーザー

退会済みユーザー

2021/05/03 07:20

なるほど。毎回書く必要ないという意味で利点だと思ったのですが違うのですねわかりました。
y_waiwai

2021/05/03 07:29

100個のソースファイルにそのヘッダがインクルードされたら、100個の独立した変数が出来上がるってことになります それがたとえstatic constであろうが事情は同じです。 まあ、PCのようにメモリがじゃぶじゃぶ使える環境なら、いいっちゃーいいんでしょうけど。
dodox86

2021/05/03 07:31

#includeするごとに勝手に同じ型、名前のファイルスコープのstatic変数が宣言されてしまうのに、害悪ではなく利点と思えてしまう不思議。
maisumakun

2021/05/03 07:32 編集

> それがたとえstatic constであろうが事情は同じです。 ポインタを取るような使い方をしなければ、const変数の領域は最適化で消し飛ばすことが可能です。 (C++の場合C++17以上にinlineというのがあって、ヘッダファイルで宣言・定義しても「実体はたかだか1つ」ということを保証してくれます)
pepperleaf

2021/05/03 07:43

> const変数の領域は最適化で消し飛ばす コンパイラ依存なような、、ただ、大抵は消し飛ばされるでしょうね。 inlineは、かなり以前から、見た気がしますが、コンパイラ依存だったのでしょうか?
dodox86

2021/05/03 07:55

少し話が込み入ってきたように思いますが、ついているタグと質問件名、コードによると当質問者氏は「C言語」での話をしているようです。ですが、他の質問ではC++の話をしていたりして、どこまで本人が厳密に意識しているかは定かではありません。
y_waiwai

2021/05/03 11:50

まあ、Cコンパイラの中には、ファイル間の最適化をしてくれるようなものもあったりするので、static constで最適化するのも中にはあるとは思いますが、大多数の組み込み用Cコンパイラの世界では、そういうことはしてくれない、という認識をしております
pepperleaf

2021/05/04 00:46

既に脱線してる気もしますが、、 const 宣言で値しか参照しない場合、コンパイル後のコードから変数は消えるのでは? (コンパイル時に型チェックされるから、それなりの価値はある)
dodox86

2021/05/04 01:30

> const 宣言で値しか参照しない場合、コンパイル後のコードから変数は消えるのでは? Cコンパイラ次第、その値の参照の仕方次第、なのではないでしょうか。「消えるかもしれない/消えないかもしれない」の議論を進めても仕方が無い気がします。 static const v1=1234 を別のファイルで2つ定義したとき、最適化しても実際に消えない例: ここから>>> $ cat m.c #include <stdio.h> static const int v1 = 1234; const int *v1p(void); int main() { printf("thisfile.v1\t%p, val=%d\n", &v1, v1); printf("anotherfile.v1\t%p, val=%d\n", v1p(), *v1p()); return 0; } $ cat v1p.c static const int v1 = 1234; const int *v1p() { return &v1; } $ gcc -O3 -Wall m.c v1p.c $ ./a.out thisfile.v1 0x7f227fe00788, val=1234 anotherfile.v1 0x7f227fe0078c, val=1234 $ <<<ここまで
pepperleaf

2021/05/04 01:39

dodox86さん、 コンパイラ次第なのは分かりますが、、アドレス取ったら、まず無理でしょう。
dodox86

2021/05/04 01:50 編集

> コンパイラ次第なのは分かりますが、、アドレス取ったら、まず無理でしょう。 ですので「その値の参照の仕方次第、なのではないでしょうか。」と書きました。また、これも個人の意見で処理系の実装次第だと思いますが、static int v1の実体の解決をコンパイラ、リンカーに委ねると、ファイルスコープのstaticであったとしても、同じ名前と値のconst int v1;を最終的に消し去る(同一のメモリ位置を参照させる)ことも可能ではある気がします。
y_waiwai

2021/05/04 01:53

まあ、処理系依存の機能を盲目的に正としてしまうのはいかがなものかと。 対応してないからとエラーが出るようなものならともかく、対応してない環境、方法で、不具合が出る可能性があるものに関しては、「間違い」と(私は)します。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問