C言語

C言語:整数定数の型について

C言語の整数定数の型について、規格の記述をまとめました。C言語について記していますが、C++言語でも同じです。

整数定数は型をもちます

整数の変数は型を持ちます。それと同じように整数の定数も型を持ちます。

用語を定義しておきます。

  • 整数定数:以下のどれか。後で示す整数接尾語を付けてもよい。
    • 10進定数:0以外で始まる。0から9が続く。基数は10
    • 8進定数:0で始まる。0から7が続く。基数は8
    • 16進定数:0xまたは0Xで始まる。0-9、a-f、A-Fが続く。基数は16

補足として、0は文法上は8進定数になります。16進定数は、英字小文字でも大文字でも構いません。

  • 整数接尾語:整数定数の後ろにつける。以下のどれか。
    • U接尾語:uまたはU
    • L接尾語:lまたはL
    • LL接尾語:llまたはLL ※C90には存在しない。

C90では、U接尾語を符号無し接尾語と、L接尾語を長語接尾語と呼んでいました。C99からLL(long long)が導入されたため、用語を変更したようです。

整数定数の型

表で示します。定数整数は、次の並びのうちでその値を表現できる最初の型となります。

定数C90の型C99以降の型
10進定数かつ
整数接尾語なし
int
long int
unsigned long int
int
long int
long long int
(8進定数または
 16進定数)かつ
整数接尾語なし
int
unsigned int
long int
unsigned long int
int
unsigned int
long int
unsigned long int
long long int
unsigned long long int
U接尾語付きunsigned int
unsigned long int
unsigned int
unsigned long int
unsigned long long int
10進定数かつ
L接尾語付き
long int
unsigned long int
long int
long long int
(8進定数または
 16進定数)かつ
L接尾語付き
long int
unsigned long int
long int
unsigned long int
long long int
unsigned long long int
U接尾語付き かつ
L接尾語付き
unsigned long intunsigned long int
unsigned long long int
10進定数かつ
LL接尾語付き
存在しないlong long int
(8進定数または
 16進定数)かつ
LL接尾語付き
存在しないlong long int
unsigned long long int
U接尾語付き かつ
LL接尾語付き
存在しないunsigned long long int

参考までに規格の記述してある場所を記しておきます。

  • C90:JIS X 3010:1993 6.1.2.3
  • C99以降: JIS X 3010:2003 6.4.4.1
         ※ISOのC11、C17も調べましたが仕様は同じでした。

実際の例

ABC269C問題解説)は、bit全探索を行う典型的な問題となります。以下のコードで、AC(正解)となります。

20、23、24行目を単に「1」と書くと、上述の整数定数の型の規則により int となります。AtCoderの環境では、int は32ビットです。問題の制約($0 \leqq N < 2^{60}$)から、64ビット整数が必要となります。

20行目は、size() は unsigned を戻すため、ULL を付けないと動作しません。

23、24行目は、シフト演算の右辺を unsinged long long にしているため、型のバランシングにより、1と書いても、演算をする前に unsinged long long 型に暗黙の型変換が行われるため動作しますが、1ULL と書いたほうが意図が伝わりやすいでしょう。

#include <bits/stdc++.h>
using namespace std;

typedef unsigned long long int ull;

int main()
{
	ull n;
	cin >> n;

	vector<ull> p;
	vector<ull> result;

	for (ull i = 0; i < 64; ++i) {
		if ((n & (1ULL << i)) != 0) {
			p.push_back(i);
		}
	}

	for (ull bit = 0; bit < (1ULL << p.size()); ++bit) {
		ull n = 0;
		for (ull i = 0; i < p.size(); ++i) {
			if ((bit & (1ULL << i)) != 0) {
				n += (1ULL << p[i]);
			}
		}
		result.push_back(n);
	}

	for (int i = 0; i < result.size(); ++i) {
		cout << result[i] << endl;
	}

	return 0;
}

最後に

整数定数の型について、自分の頭を整理するために記事にしました。

C言語を使いこなしていきましょう!

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA