C ++ 'da numaralandırma bildirirken neden typedef kullanıyorsunuz?


183

Yıllardır herhangi bir C ++ yazmadım ve şimdi geri dönmeye çalışıyorum. Daha sonra bununla karşılaştım ve pes etmeyi düşündüm:

typedef enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

Bu nedir? typedefAnahtar kelime neden burada kullanılıyor? TokenTypeBu bildirimde neden ad iki kez görünüyor? Anlambilimin bundan farkı nedir:

enum TokenType
{
    blah1 = 0x00000000,
    blah2=0x01000000,
    blah3=0x02000000
};

Yanıtlar:


156

C'de, enum'unuzu ilk şekilde bildirmek, onu şu şekilde kullanmanıza izin verir:

TokenType my_type;

İkinci stili kullanırsanız, değişkeninizi şu şekilde beyan etmek zorunda kalacaksınız:

enum TokenType my_type;

Başkaları tarafından belirtildiği gibi, bu C ++ 'da bir fark yaratmaz. Benim tahminim ya bu yazdı kişi kalbinde bir C programcısı, ya da C kodu C ++ derlemek. Her iki durumda da, kodunuzun davranışını etkilemez.


12
Sorunuz yalnızca C için doğrudur, ancak C ++ için doğru değildir. C ++ sıralamaları ve yapıları, bir typedef varmış gibi doğrudan kullanılabilir.
David Rodríguez - dribeas

7
Evet, ama bu gerçekten "bu ne anlama geliyor?" Hakkında sorulan gerçek soruyu cevaplıyor.
BobbyShaftoe

Peki bu teknik olarak bir typedef ya da enum mu?
Miek

5
Her ikiside. Ayrıca söyleyebilirsin: enum TokenType_ {...}; typedef enum TokenType_ TokenType;
Ryan Fox

Cevap tamam, ama asıl nokta TokenType; numaralandırma bildiriminin ardından tür adını bildiren şeydir. Bu yüzden cevap% 100 tam değil 'İlk yol' ilan etmek, hem bir hemum hem de bir sözdizim bloğundaki enum olan yeni bir tür adı belirtir. Bu yüzden cevap yardımcı oldu, ama sanırım biraz geliştirilebiliyor. Belki oy vermek için çok sert davrandım. Bu yüzden ondan sonra iptal ettim. Kendimden gerçekten emin olsaydım, cevabı düzenleme / iyileştirme konusunda bir yağma olurdu ... ama bu oldukça iyi bir cevap
Ross Youngblood

97

Bu bir C mirası, eğer C, eğer yaparsanız:

enum TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
};

aşağıdaki gibi bir şey kullanarak kullanmanız gerekir:

enum TokenType foo;

Ancak bunu yaparsanız:

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

Şunları beyan edebileceksiniz:

TokenType foo;

Ancak C ++ 'da, yalnızca eski tanımı kullanabilir ve bir C typedef'teymiş gibi kullanabilirsiniz.


1
Söyledikleriniz C'de doğrudur. C ++ 'da doğru değildir.
Jonathan Leffler

49
Son cümlemde söylediğim gibi değil mi?
mat

2
@mat Son cümle hakkındaki yorumunuzu onayladım, ancak adil olmak kötü ifade ve kafa karıştırıcı.
AR

20

Yapmanıza gerek yok. C'de (C ++ değil) , numaralandırılmış türdeki bir veri öğesine başvurmak için enum Enumname kullanmanız gerekiyordu . Bunu basitleştirmek için size izin verildi typedef tek bir isim veri türüne gönderilir.

typedef enum MyEnum { 
  //...
} MyEnum;

enum parametresini alan izin verilen fonksiyonlar

void f( MyEnum x )

daha uzun yerine

void f( enum MyEnum x )

Yazım adının adının numarasına eşit olması gerekmediğini unutmayın. Aynı şey yapılar için de geçerlidir.

Diğer yandan, C ++ 'da gerekli değildir, çünkü numaralandırmalara, sınıflara ve yapılara isimleriyle türler olarak doğrudan erişilebilmektedir.

// C++
enum MyEnum {
   // ...
};
void f( MyEnum x ); // Correct C++, Error in C

Aslında bunun genel olarak kabul edilen yanıttan daha iyi bir yanıt olabileceğini düşünüyorum, çünkü bu açıkça "neden" farklı olduğunu açıklıyor.
Ross Youngblood

11

C'de iyi bir stildir, çünkü türü bir numaralandırmanın yanı sıra bir şeyle değiştirebilirsiniz.

typedef enum e_TokenType
{
    blah1   = 0x00000000,
    blah2   = 0X01000000,
    blah3   = 0X02000000
} TokenType;

foo(enum e_TokenType token);  /* this can only be passed as an enum */

foo(TokenType token); /* TokenType can be defined to something else later
                         without changing this declaration */

C ++ 'da numaralandırmayı tanımlayabilir, böylece C ++ veya C olarak derlenir.


Söylemek istemiyor musun In C++ you can *typedef* the enum so that it will compile as C++ or C.? Dedin ki: In C++ you can define the enum so that it will compile as C++ or C.Nasıl değiştirdiğime dikkat defineet typedef. Eh ... Ben varsayalım typedefing olduğunu tanımlayan.
Gabriel Staples

6

Holdover yönüne C


'Erken' niteleyicinin alakalı olduğunu unutmayın; enum öneki olmadan tür adını kullanmak istiyorsanız, bunu yine de C'ye yazarsınız.
Jonathan Leffler

1
doğru. Onu sileceğim. Uzun süredir C spec'i takip etmedim. Benim için c / c ++ ayrımını kontrol etmek için çok tembeldim ... -1.
Tim

6

Bazı insanlar C'nin isim alanlarına sahip olmadığını ancak teknik olarak doğru olmadığını söylüyor. Üç tane var:

  1. Etiketler ( enum, unionve struct)
  2. Etiketler
  3. (diğer her Şey)

typedef enum { } XYZ;anonim bir numaralandırma ilan eder ve ismini global isim alanına aktarır XYZ.

typedef enum ABC { } XYZ;ABCetiket ad alanında bir numaralandırma bildirir ve ardından genel ad alanına olarak alır XYZ.

Bazı insanlar ayrı ad alanlarıyla uğraşmak istemezler, böylece her şeyi yazarlar. Diğerleri asla tanımlamaz çünkü ad boşluğunu istemektedir.


Bu tam olarak doğru değil. yapılara, sendikalara ve numaralandırmalara etiket adıyla referans verilir (anonim değilse, belirttiğiniz gibi). Türler ve etiketler için ayrı ad alanları vardır. Etiketle aynı ada sahip bir tür olabilir ve para cezası derleyebilirsiniz. Ancak, bir enum bir yapı ile aynı etikete sahipse, bu tam olarak aynı etikete sahip 2 yapı veya 2 enum gibi bir derleme hatasıdır. Ayrıca, go için etiketlerin ayrı bir ad alanı olduğunu unutursunuz. Bir etiket, etiketle veya tanımlayıcıyla aynı ad olabilir, ancak bir tür olamaz ve tanımlayıcı bir etiketle aynı ada sahip olabilir, ancak bir tür olamaz.
Rich Jahn

3

Bu biraz eski, ama umarım, bu yılın başlarında karşılaştığımda takdir ettiğim gibi yazmak istediğim bağlantıyı takdir edersiniz.

İşte öyle . Bazı kötü typedefs kavramak zorunda kaldığımda her zaman aklımdaki açıklama alıntı gerekir:

Değişken bildirimlerinde, eklenen adlar karşılık gelen türlerin örnekleridir. [...] Ancak, typedefanahtar kelime bildirimden önce geldiğinde, tanıtılan adlar karşılık gelen türlerin takma adlarıdır

Daha önce birçok kişinin söylediği gibi, C ++ 'da numaralandırma bildiren typedefs kullanmaya gerek yoktur . Ama bu typedef'in sözdiziminin açıklaması! Umarım yardımcı olur (Muhtemelen OP değil, neredeyse 10 yıl geçti, ancak bu tür şeyleri anlamak için mücadele eden herkes).


1

Bazı C kod stili kılavuzunda typedef versiyonunun "açıklık" ve "basitlik" için tercih edildiği söylenir. Kabul etmiyorum, çünkü typedef beyan edilen nesnenin gerçek doğasını gizliyor. Aslında, typedefs kullanmıyorum çünkü C değişkenini bildirirken nesnenin gerçekte ne olduğu konusunda net olmak istiyorum. Bu seçim, eski bir kod parçasının gerçekte ne yaptığını daha hızlı hatırlamama yardımcı olur ve gelecekte kodu korurken diğerlerine yardımcı olur.


1

"Neden" sorusunun asıl cevabı (bu eski sorunun başında şaşırtıcı bir şekilde göz ardı edilmektedir), bu enumbildirimin muhtemelen hem C hem de C ++ kodu olarak çapraz derlenebilecek bir başlık dosyasında (yani hem C hem de C ++ uygulama modüllerine dahil). Bu tür başlık dosyaları yazma sanatı, yazarın her iki dilde de uygun uyumlu anlama sahip dil ​​özelliklerini seçme yeteneğine dayanır.

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.