宣言した変数の用量は中身の値に関わらず一定ですか?

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

宣言した変数の用量は中身の値に関わらず一定ですか?

#1

投稿記事 by カマキリ » 4年前

初歩的な質問で申し訳ないんですが

int a;
で作った変数があったとします。
このaという変数に、0という値を格納(a = 0)しようが、10000000という値を格納しようが
容量は変わらないって本当ですか?

要は、int a = 0; int b =10000000;では
aもbも、使っている容量自体は変わらないという認識でよろしいですか?

だとすれば、画像ハンドルも?
変数aにLoadGraphを使って画像のハンドルを入れようが
ただの数字が入っている変数aと、
容量は変わらないということでしょうか?

アバター
Hiragi(GKUTH)
記事: 167
登録日時: 9年前
住所: 大阪府
連絡を取る:

Re: 宣言した変数の用量は中身の値に関わらず一定ですか?

#2

投稿記事 by Hiragi(GKUTH) » 4年前

容量、といいますか、int型が宣言された時点で32bit(或は16bit)はメモリ上で「確保」されますので、その確保されたところに値を書き込む感じでしょうか、
良くある例で言うならば、変数は箱であるとよく比喩されますが、箱の中にどんな値を入れようとも箱の大きさは変わらんわけです。
メモリー内部では大きな値の分メモリセルの状態が1である(ONである)から容量が変わってるといえなくはないかもしれませんが...

画像ハンドルに関しては、int型の変数に画像そのものが入ってるわけではなく、int型の変数に入るのは画像の位置を示す情報であるということです。
だいがくせい!

カマキリ

Re: 宣言した変数の用量は中身の値に関わらず一定ですか?

#3

投稿記事 by カマキリ » 4年前

レス、ありがとうございます。
Hiragi(GKUTH) さんが書きました:変数は箱であるとよく比喩されますが、箱の中にどんな値を入れようとも箱の大きさは変わらんわけです。
そうですよね、そう勉強したはずなんですけど、、、、、
ただ、この例えを現実的に考えた場合ですが、
箱のサイズは変わらなくても、
その中に入れるものによって、重さは変わるじゃないですか?
そこんところ、変数ではどうなんかなーって思いまして。

ちなみに、変数に入れる値の限界が2147483647らしいですが
例えば、ゲーム中に
それ以上の数を代入、ないしは、インクリメントを繰り返しそれ以上の値を超えたら
問答無用でエラーになってゲームが止まるんでしょうか?

アバター
TOMY
記事: 53
登録日時: 7年前
住所: 愛知県
連絡を取る:

Re: 宣言した変数の用量は中身の値に関わらず一定ですか?

#4

投稿記事 by TOMY » 4年前

それは使用する言語によって変わると思います。
アンセーフな言語のc、c++では致命的なメモリリークをしない限り大丈夫ですが、(逆にその適当さがバグの抜きにくさの原因でもあります)割と厳しいc#やjavaではたしか強制終了させられたと思います。
phpは割とリーク、オーバーフロー系は起ころうがガン無視です。この前それを体験して泣きました。

ちなみにメモリリークとかオーバーフローをあえて行うことでwebサイトを攻撃する方法がありますし、プロアクションリプレイのようなチートツールもそれらを使ってゲームをバグらせる事でお金やHP上限をMAXにしています。
百聞は一見にしかず。うんちくだけを頭にぶち込む前に実際に実験した方がいいよ。
書籍とか経験談とか見て知識をつけるのも大事だけど。

カマキリ

Re: 宣言した変数の用量は中身の値に関わらず一定ですか?

#5

投稿記事 by カマキリ » 4年前

自分はC++です。
自分で実験するのはまだ怖いのもありまして、、。
教えてくださいまして、感謝です。

ご回答くださいましたみなさま、ありがとうございました。

アバター
TOMY
記事: 53
登録日時: 7年前
住所: 愛知県
連絡を取る:

Re: 宣言した変数の用量は中身の値に関わらず一定ですか?

#6

投稿記事 by TOMY » 4年前

昔と違っていまのOSは致命的な領域破壊を検知したら強制的にプロセスを止めるからそこまで警戒しなくてもいいと思う。むしろ一度二度経験(実験)しとけば次回から同じ症状に陥った時に原因特定が多少楽になるよ。
百聞は一見にしかず。うんちくだけを頭にぶち込む前に実際に実験した方がいいよ。
書籍とか経験談とか見て知識をつけるのも大事だけど。

アバター
みけCAT
記事: 6247
登録日時: 9年前
住所: 千葉県
連絡を取る:

Re: 宣言した変数の用量は中身の値に関わらず一定ですか?

#7

投稿記事 by みけCAT » 4年前

カマキリ さんが書きました:ちなみに、変数に入れる値の限界が2147483647らしいですが
C言語では処理系依存です。
int型の場合、規格上少なくとも-32767~32767の整数は格納できます。
TOMY さんが書きました:アンセーフな言語のc、c++では致命的なメモリリークをしない限り大丈夫ですが
C言語では、符号付き整数がオーバーフローした時の動作は未定義だったと思います。
よって、大丈夫とは限りません。
また、「致命的なメモリリークをしない限り大丈夫」というのは誤りです。
例えば、

コード:

#include <stdio.h>

int main(void) {
	volatile int a[1];
	puts("test1");fflush(stdout);
	a[1234567] = 123;
	puts("test2");fflush(stdout);
	printf("test3 %d\n", a[1234567]);fflush(stdout);
	return 0;
}
というコードをIdeoneで実行するとRuntime Errorになりました。(未定義動作である気がします)
TOMY さんが書きました:割と厳しいc#やjavaではたしか強制終了させられたと思います。
Javaではint型がオーバーフローしても強制終了にはならないと思います。

コード:

class A {
    public static void main(String[] args) {
        int a = 2147483647;
        System.out.println(a);
        a++;
        System.out.println(a);
    }
}
C#でも、実験結果では強制終了になりませんでした。

コード:

using System;

public class Test
{
	public static void Main()
	{
		int a = 2147483647;
		Console.WriteLine(a);
		a++;
		Console.WriteLine(a);
	}
}
TOMY さんが書きました:プロアクションリプレイのようなチートツールもそれらを使ってゲームをバグらせる事でお金やHP上限をMAXにしています。
プロアクションリプレイの実装は知りませんが、チートツールはそんなまわりくどいことをせず、直接メモリ上の値を書き換えると思います。
また、TASではバッファオーバーランを使って(?)任意のコード(?)を実行するものがあります。
追記:この動画はそういう原理ではないかもしれません
[nico]http://www.nicovideo.jp/watch/sm20328346[/nico]
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

YuO
記事: 941
登録日時: 9年前
住所: 東京都世田谷区

Re: 宣言した変数の用量は中身の値に関わらず一定ですか?

#8

投稿記事 by YuO » 4年前

オフトピック
みけCAT さんが書きました:
TOMY さんが書きました:割と厳しいc#やjavaではたしか強制終了させられたと思います。
C#でも、実験結果では強制終了になりませんでした。

コード:

using System;

public class Test
{
	public static void Main()
	{
		int a = 2147483647;
		Console.WriteLine(a);
		a++;
		Console.WriteLine(a);
	}
}
言語のマイナーな部分を……。

コード:

using System;

class Program
{
	private static void Main ()
	{
		try
		{
			CallUnchecked();
			Console.WriteLine("CallUnchecked succeeded.");
		}
		catch (Exception e)
		{
			Console.WriteLine("CallUnchecked raised {0}", e.GetType().Name);
		}
		try
		{
			CallChecked();
			Console.WriteLine("CallChecked succeeded.");
		}
		catch (Exception e)
		{
			Console.WriteLine("CallChecked raised {0}", e.GetType().Name);
		}
	}

	private static void CallChecked ()
	{
		checked
		{
			var n = Int32.MaxValue;
			++n;
		}
	}

	private static void CallUnchecked ()
	{
		unchecked
		{
			var n = Int32.MaxValue;
			++n;
		}
	}
}
結果

コード:

CallUnchecked succeeded.
CallChecked raised OverflowExceptio
C#において,checkedコンテキスト内においてはオーバーフローを検出し,検出した場合にOverflowExceptionを送出します。
しかし,uncheckedコンテキスト内においてはオーバーフローの検出は行いません。
細かいことは,C# 5.0の言語仕様の,6.2.1 明示的な数値変換の一覧表 (英語では6.2.1 Explicit numeric conversions) に規則が書かれています。
なお,MSのcscコンパイラにおいて,デフォルトはuncheckedコンテキストです。

constexpr
記事: 5
登録日時: 5年前

Re: 宣言した変数の用量は中身の値に関わらず一定ですか?

#9

投稿記事 by constexpr » 4年前

C++で、int型のサイズが32bitで出力された場合。
int a = 0; int b =10000000;
一見すると桁が違うから大きさが違うように見えるが、0も一桁ではない。仮にintが32bitなら0は
00000000000000000000000000000000
という32bitの値になる(2進数)
10000000は
00000000100110001001011010000000
という32bitの値になる(2進数)

この32桁の2進数は違う値を示すが、桁数(を表現するために必要な領域)は同じ。

[hr]

あまり他人の回答に鉞は投げたくないのだが、
Hiragi(GKUTH) さんが書きました:int型が宣言された時点で32bit(或は16bit)はメモリ上で「確保」されます
というのは厳密には間違いで、あらぬ誤解を生みかねない。
Plain ints have the natural size suggested by the architecture of the execution environment; the other signed integer types are provided to meet special needs.
int型は実行環境における自然なサイズで表現されると書かれている。つまり、規格には32bitや16bitと言ったルールは存在しない。
たまたま、偶然にも32bitや16bitで表現されることが多いだけである。各コンパイラがドキュメントで警告しているように、int型のサイズは実行環境に依存することを踏まえ、サイズに依存するコードを書いてはいけない。上記の記述は初心者の誤解を産みがちで、オーバーフローよりもずっと「危険」なことに繋がりかねない。もしかしたら今後intは64bitが当たり前の時代だって来るかもしれない。
that is, large enough to contain any value in the range of INT_MIN and INT_MAX, as defined in the header <climits>.
int型の最大値はINT_MAX、最小値はINT_MINとして、標準ヘッダclimitに定義される。これはCの標準ライブラリだが、intに関しての規格はC言語と互換があるため、問題ない。
ただし、互換があるだけでC++でこれはおすすめしない。C++標準ライブラリlimitsにstd::numeric_limitsがあるので、これを使うべきである。std::numeric_limits<int>::max()とすれば最大値を取得できる。
The signed and unsigned integer types shall satisfy the constraints given in the C standard, section 5.2.4.2.1.
符号あり、符号なしのint型はC言語規格と互換がある。

標準ヘッダcstdintに、C++11以降では型のサイズをある程度指定できる型が定義されている。以下は一例。
実行環境における最大の整数型
intmax_t
最低でも指定bit数を持つ型
int_least32_t
int_least16_t
最低でも指定bit数を持ち、最速で計算できる型
int_fast16_t
int_fast32_t

C++03までの環境でも、boostに同様のものがある。boost.integerのほうが汎用的である。
ちなみに各コンパイラ固有の、専用のサイズ指定の型がある場合があるが、一般的には型のサイズは標準ライブラリかboostの型を使うべきである。組み込みは考えない。
Unsigned integers shall obey the laws of arithmetic modulo 2n where n is the number of bits in the value representation of that particular size of integer.
符号なしint型に関しては、2nを法とするモジュロ算術に従うことが定められている。つまり、符号なし整数型はオーバーフローしない。
std::numeric_limits<unsigned int>::max() + 1
の結果は0になることが定められているということだ。


宣言された時点で確保、というのも微妙なラインだが、あまりほじくっても仕方ないので触れないことにする。

規格の文面はWorking Draft, Standard for Programming Language C++ N4296より引用した。
§ 3.9.1 Fundamental types [basic.fundamental]
これはワーキングドラフトであり正式な規格ではないが、intに関する文面はC言語と互換が残されていることもあり、ほとんど変更されていないため、問題はないだろう。

アバター
TOMY
記事: 53
登録日時: 7年前
住所: 愛知県
連絡を取る:

Re: 宣言した変数の用量は中身の値に関わらず一定ですか?

#10

投稿記事 by TOMY » 4年前

みけCATさん私の間違った解答にご指摘ありがとうございます。
割と自分の知識と経験というのはあてにならないものですね・・・
次回からは黙るようにします。
百聞は一見にしかず。うんちくだけを頭にぶち込む前に実際に実験した方がいいよ。
書籍とか経験談とか見て知識をつけるのも大事だけど。

閉鎖

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