C ++で単一引用符を複数の文字に使用するとどうなりますか?


回答:


283

これは複数文字リテラルです。1952805748is 0x74657374、これは次のように分解されます

0x74 -> 't'
0x65 -> 'e'
0x73 -> 's'
0x74 -> 't'

編集:

C ++標準、§2.14.3/ 1-文字リテラル

(...)複数のc-charを含む通常の文字リテラルは、複数文字リテラルです。複数文字リテラルには、int型と実装定義の値があります。


11
これは実装定義であるとは言いませんでした。
Thomas Bonini、2011

2
その定義について最もおもしろいのは、sizeof(int)実装も定義されているということです。したがって、ストレージ順序の実装が定義されるだけでなく、これらの最大長も定義されます。
bobobobo 2013

74

いいえ、住所ではありません。いわゆるマルチバイト文字です。

通常、4つの文字を組み合わせたASCII値です。

't' == 0x74; 'e' == 0x65; 's' == 0x73; 't' == 0x74; 

したがって、0x74657374は1952805748です。

ただし、他のコンパイラでは0x74736574になる場合もあります。CおよびC ++標準はどちらも、マルチバイト文字の値は実装定義であると述べています。そのため、一般的にその使用は強く推奨されていません。


そのようなマルチバイト文字の長さは4バイトに制限されていますか?つまり、文字として書き出されたintを表しているのでしょうか。
ジョルジオ

2
@ジョルジオ:標準では、実装が定義されているだけで、詳細はありません。実際にintは、ほとんどのマシンで4バイトであるため、4バイトより多く使用しても意味がないと思います。はい、それはいくつかの定数を書くための便利な方法であることが意図されていましたが、残念なことに、コンパイラが異なると解釈が異なるため、現在、ほとんどのコーディングスタイルはその使用を思いとどまらせています。
chy

2
@chys:そして、それが実装定義であるという事実は、それが一貫している必要さえないことを意味します。適合コンパイラは、たとえば、すべての複数文字リテラルに値0を与えることができます(ただし、これは不便です)。
キース・トンプソン

2
このルーニー機能が標準に存在する理由を尋ねる必要があります。それはそのようなまれなユースケースのようであり、とにかく実装が定義されており、通常のビットシフトや必要に応じてoringを行うことで非常に明確に行うことができます。
Boann 2013

1
@Boann はい、私の感情は正確です。ただし、直接比較して==確認する必要があるため、スイッチなどで安全に使用できます
bobobobo

18

複数のc-charを含む通常の文字リテラルは、複数文字リテラルです。複数文字リテラルには、int型と実装定義の値があります。

実装で定義された動作は、実装で文書化する必要があります。たとえばgccでは、ここで見つけることができます

コンパイラーは一度に複数文字の文字定数を1文字ずつ評価し、前の値をターゲット文字あたりのビット数だけ左にシフトし、新しい文字のビットパターンをターゲットの幅に切り捨てますキャラクター。最後のビットパターンにはint型が指定されているため、単一の文字が署名されているかどうかに関係なく、署名されています。

詳細については、このページの説明を確認してください


10

彼らは本当にただですint。これらは、Core Audio API列挙型、たとえばCoreAudioTypes.hヘッダーファイルで広く使用されています。

enum
{
    kAudioFormatLinearPCM               = 'lpcm',
    kAudioFormatAC3                     = 'ac-3',
    kAudioFormat60958AC3                = 'cac3',
    kAudioFormatAppleIMA4               = 'ima4',
    kAudioFormatMPEG4AAC                = 'aac ',
    kAudioFormatMPEG4CELP               = 'celp',
} ;

これが「プラットフォームに依存しない」ことについては多くのおしゃべりがありますが、特定のプラットフォーム用に作成されたAPIを使用している場合は、移植性を重視します。同じプラットフォームで等しいかどうかのチェックは失敗しません。これらのenum'd値は読みやすく、実際にはIDが含まれています。これは非常に便利です。

以下で私が試したのは、マルチバイト文字リテラルをラップして印刷できるようにすることです(Macではこれが機能します)。奇妙なことに、4文字すべてを使用しないと、以下の結果が間違ったものになります。

#include <stdio.h>

#define MASK(x,BYTEX) ((x&(0xff<<8*BYTEX))>>(8*BYTEX))

struct Multibyte
{
  union{
    int val ;
    char vals[4];
  };

  Multibyte() : val(0) { }
  Multibyte( int in )
  {
    vals[0] = MASK(in,3);
    vals[1] = MASK(in,2);
    vals[2] = MASK(in,1);
    vals[3] = MASK(in,0);
  }
  char operator[]( int i ) {
    return val >> (3-i)*8 ; // works on mac
    //return val>>i*8 ; // might work on other systems
  }

  void println()
  {
    for( int i = 0 ; i < 4 ; i++ )
      putc( vals[i], stdout ) ;
    puts( "" ) ;
  }
} ;

int main(int argc, const char * argv[])
{
  Multibyte( 'abcd' ).println() ;  
  Multibyte( 'x097' ).println() ;
  Multibyte( '\"\\\'\'' ).println() ;
  Multibyte( '/*|' ).println() ;
  Multibyte( 'd' ).println() ;

  return 0;
}

6
「同じプラットフォームで等しいかどうかを確認しても失敗することはありません。」かもしれない。Visual Studio xyzにアップグレードして、舌を噛みます。このライブラリはひどい決定をしました。
オービットのライトネスレース

@LightnessRacesinOrbit "Visual Studio xyzにアップグレードして、舌を噛んでください。" Core Audio APIはOS XのシステムオーディオAPIなので、これは関係ありません。
ジャンマイケルCelerier

5
@Jean-MichaëlCelerier:結構です。...あなたのOSXクランのバージョンをアップグレードして、あなたの舌をかむ
軌道上での明度レース

1

この種の機能は、パーサーを構築するときに非常に役立ちます。このことを考慮:

byte* buffer = ...;
if(*(int*)buffer == 'GET ')
  invoke_get_method(buffer+4);

このコードは特定のエンディアンでのみ機能する可能性が高く、異なるコンパイラにまたがる可能性があります

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.