C / C ++では長い長い


84

このコードをGNUのC ++コンパイラで試していますが、その動作を理解できません。

#include <stdio.h>;

int main()
{
    int  num1 = 1000000000;
    long num2 = 1000000000;
    long long num3;
    //num3 = 100000000000;
    long long num4 = ~0;

    printf("%u %u %u", sizeof(num1), sizeof(num2), sizeof(num3));
    printf("%d %ld %lld %llu", num1, num2, num3, num4);
    return 0;
}

コメント行のコメントを解除すると、コードがコンパイルされず、エラーが発生します。

エラー:整数定数が長い型には大きすぎます

ただし、コードをそのままコンパイルして実行すると、10000000000よりはるかに大きい値が生成されます。

どうして?


8
今では手遅れかもしれませんが、将来の読者のために、を使用<stdint.h>して使用することをお勧めしますuint64_t。64ビット値を表示するには、printf( "%" PRIu64 "\n", val);
enthusiasticgeek

@enthusiasticgeekが<stdint.h>含まれていますuint64_t a = 0xffffffffffffff; printf( "%" PRIu64 "\n",a ); : error: expected ‘)’ before ‘PRIu64’ printf( "%" PRIu64 "\n",a ); :: warning: spurious trailing ‘%’ in format [-Wformat=] printf( "%" PRIu64 "\n",a );
Herdsman

回答:


147

文字100000000000はリテラル整数定数を構成しますが、値がタイプに対して大きすぎintます。リテラルのタイプを変更するには、接尾辞を使用する必要があります。

long long num3 = 100000000000LL;

接尾辞LLは、リテラルを型にしlong longます。Cは、左側の型からこれを結論付けるのに十分な「スマート」ではありません。型はリテラル自体のプロパティであり、使用されているコンテキストではありません。


47
この回答が書かれたときはおそらく正しかったのですが、C ++標準では、接尾辞のない整数リテラルのタイプは、、の最初でintありlong intlong long intその値を表すことができるとされています。[C ++§2.14.2/ 2]したがって、他のタイプには大きすぎる整数リテラルに「LL」サフィックスを追加する必要がなくなりました。
bames53 2012年

8
これが以前に問題であった理由は、C ++が割り当てられている変数の型からリテラル型を決定するのに十分な「スマート」ではなかったためではなく、コンパイラ拡張が拡張整数を実装しなかったためでした。標準言語でうまく機能するように入力します。C ++には、拡張整数型が標準とより適切に統合されるようなルールがあります。open
std.org

4
@unwindこれらの提案に従って答えを編集する必要があると思います。
アントニオ

26

試してみてください:

num3 = 100000000000LL;

そしてところで、C ++ではこれはコンパイラ拡張であり、標準ではC99の一部であるlonglongは定義されていません。


11
さて、C ++ 11は今では長い長いものを定義しています
Mohamed El-Nakib 2014

4

コンパイルするモードによって異なります。longlongはC ++標準の一部ではありませんが、(通常は)拡張機能としてのみサポートされています。これは、リテラルのタイプに影響します。intが十分に大きい場合、接尾辞のない10進整数リテラルは常にint型になります。数値を表すのにさの、それ以外の場合はlong型です。数値が長すぎても大きすぎる場合、結果は実装によって定義されます(おそらく、下位互換性のために切り捨てられたlong型intの数だけです)。この場合、(ほとんどのコンパイラで)long long拡張を有効にするには、LLサフィックスを明示的に使用する必要があります。

次のC ++バージョンは、リテラルの型を少なくともlong longにすることを明示的に望まない限り、接尾辞を必要としない方法で、longlongを公式にサポートします。数値をlongで表すことができない場合、コンパイラはLLサフィックスがなくても自動的にlonglongを使用しようとします。これはC99の動作でもあると思います。


1

あなたのコードはここでうまくコンパイルされます(その行がコメントされていなくても。それをに変更する必要がありました

num3 = 100000000000000000000;

警告の取得を開始します。


どのコンパイラ?C ++では、整数リテラルは、それが収まるintまたはlongの小さい方です。C99では、int、long、longlongの最小値です。したがって、非標準の拡張機能としてC ++に長い間ボルトで固定する場合、おそらくコンパイラはリテラルにC99ルールも採用しています。
スティーブジェソップ

64ビットLinuxシステム上のgccバージョン4.3.2(Debian 4.3.2-1.1)。
Omry Yadan

@SteveJessopおそらく少し遅れていますが、longは必ずしも64ビットではありません。ほとんどの場合そうですが、どこにでもあるという保証はありません。あなたが持っている唯一の保証は、それが少なくともintと同じ大きさであり、それは少なくとも短いintと同じ大きさであり、それは少なくともcharと同じ大きさであるということです。最後に、charは、実装の基本的な文字セット(通常は8ビット)のすべての文字を表すのに十分な大きさとして定義されます。
pauluss86 2013年

@ pauluss86:私は保証について話していませんでした。Omryは、64ビットのDebianシステムでgcc4.3.2を使用していると述べました。(私は一般的な知識の問題としてたまたま知っていた)gccはlong、そのOSのLP64 ABIに沿って64ビットを使用するようにそのようなシステムでデフォルトで構成されているので、これが彼が見ているものを説明していることを観察しました。
スティーブジェソップ2013年

@SteveJessopあなたのコメントが間違っていると言っているのではありません!残念ながら多くの人が考える、longが常に64ビットであるという仮定は危険であると指摘するだけです。
pauluss86 2013年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.