Birden fazla karakterde kullanıldığında tek tırnaklar C ++ 'da ne yapar?


Yanıtlar:


283

Çok karakterli bir değişmez. 1952805748olarak 0x74657374ayrışan

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

Düzenle:

C ++ standardı, §2.14.3 / 1 - Karakter değişmez değerleri

(...) Birden fazla c-char içeren sıradan bir karakter değişmezi, çok karakterli bir değişmez değerdir. Çok karakterli bir değişmezin int türü ve uygulama tanımlı değeri vardır.


11
Bunun uygulama tanımlı olduğunu söylemediniz.
Thomas Bonini

2
Sanırım bu tanımla ilgili en eğlenceli şey sizeof(int)uygulamanın da tanımlanmış olmasıdır. Depolama emri uygulaması sadece tanımlanmakla kalmaz, aynı zamanda bunların maksimum uzunluğu da tanımlanır.
bobobobo

74

Hayır, bu bir adres değil. Çokbaytlı karakter.

Tipik olarak, birleştirilen dört karakterin ASCII değerleri.

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

Yani 0x74657374 1952805748'dir.

Ancak başka bir derleyicide 0x74736574 de olabilir. C ve C ++ standartlarının her ikisi de çok baytlı karakterlerin değerinin uygulama tanımlı olduğunu söylüyor . Bu nedenle, genel olarak kullanımı kesinlikle önerilmez.


Böyle bir çok baytlık karakterin uzunluğu 4 bayt ile sınırlandırılmış mı? Yani karakter olarak yazılan bir int'i temsil ediyor mu?
Giorgio

2
@Giorgio: Standart, daha fazla ayrıntı olmadan, yalnızca uygulamanın tanımlandığını söylüyor. Uygulamada, intçoğu makinede 4 bayt olduğu için, 4 bayttan fazla kullanmanın mantıklı olduğunu düşünmüyorum. Evet, bazı sabitleri yazmak için uygun bir yol olması amaçlanmıştı, ancak maalesef farklı derleyiciler bunu farklı şekilde yorumluyorlar, bu nedenle günümüzde çoğu kodlama stili kullanımını engelliyor.
chys

2
@chys: Ve bunun uygulama tanımlı olması, tutarlı olması bile gerekmediği anlamına geliyor. Uygun bir derleyici, tüm çok karakterli değişmez değerlere 0 değerini verebilir (bu düşmanca olsa da).
Keith Thompson

2
Bu kaçık özelliğin neden standartta var olduğunu sormak gerekir. Böyle nadir bir kullanım durumu gibi görünüyor, yine de uygulama tanımlanmış ve sıradan bit kaydırma ve / veya gerekirse oldukça net bir şekilde yapılabilir.
Şubat'ta Boann

1
@Boann Evet , duygularım tam olarak. Ancak, anahtarlarda ve ==
neyse

18

Birden fazla c-char içeren sıradan bir karakter değişmezi, çok karakterli bir değişmez değerdir. Çok karakterli bir değişmezin int türü ve uygulama tanımlı değeri vardır.

Uygulama tanımlı davranışın uygulama tarafından belgelenmesi gerekir. örneğin gcc'de burada bulabilirsiniz

Derleyici bir seferde çok karakterli bir karakteri sabitler, bir önceki değeri hedef karakter başına bit sayısı kadar kaydırır ve sonra bir hedefin genişliğine kesilmiş yeni karakterin bit deseninde kayar. karakter. Son bit desenine int türü verilir ve bu nedenle, tek karakterlerin imzalanıp imzalanmadığına bakılmaksızın imzalanır.

Daha fazla ayrıntı için bu sayfadaki açıklamaya bakın


10

Onlar gerçekten sadece ints. Core Audio API numaralandırmalarında, örneğin CoreAudioTypes.hbaşlık dosyasında,

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

Bunun "platformdan bağımsız" olmadığı konusunda çok fazla sohbet var, ancak belirli bir platform için yapılmış , taşınabilirliği önemseyen bir API kullandığınızda . Aynı platformda eşitlik kontrolü asla başarısız olmaz. Bu enumdeğerlerin okunması daha kolaydır ve kimliklerini aslında değerlerinde içerirler , ki bu oldukça hoştur.

Aşağıda yapmaya çalıştığım, yazdırılabilmesi için çok baytlı bir karakter değişmezidir (Mac'te bu işe yarar). Garip olan şey, 4 karakterin hepsini kullanmazsanız, sonuç aşağıda yanlış olur.

#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
"Aynı platformda eşitlik kontrolü asla başarısız olmaz." Olabilir. Visual Studio xyz'e yükseltin ve dilini ısır. Bu kütüphane korkunç bir karar verdi.
Yörüngedeki Hafiflik Yarışları

@LightnessRacesinOrbit "Visual Studio xyz'e yükseltin ve dilini ısır." Core Audio API, OS X'in sistem ses API'sıdır, bu nedenle ilgili değildir.
Jean-Michaël Celerier

5
@ Jean-MichaëlCelerier: Güzel; OSX Clang sürümünüzü yükseltin ve dilinizi ısırın ...
Orbit'teki Hafiflik Yarışları

1

Bu tür bir özellik, ayrıştırıcılar oluştururken gerçekten iyidir. Bunu düşün:

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

Bu kod muhtemelen yalnızca belirli bir endianess üzerinde çalışacak ve farklı derleyicileri kırabilir

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.