Czy domyślne wartości wyliczenia w języku C są takie same dla wszystkich kompilatorów?

107

Podczas deklarowania enum, jak pokazano poniżej, nie wszystkie kompilatory C ustawić domyślne wartości jak x=0, y=1i z=2na obu systemach Linux i Windows?

typedef enum {
    x,
    y,
    z
} someName;
SSS
źródło
3
Tak, wymagają tego normy i jestem pewien, że ktoś będzie mógł je zacytować.
Nemo

Odpowiedzi:

115

Tak. O ile nie określisz inaczej w definicji wyliczenia, początkowy moduł wyliczający zawsze ma wartość zero, a wartość każdego kolejnego modułu wyliczającego jest o jeden większy niż poprzedni moduł wyliczający.

James McNellis
źródło
14
i to identyczne zachowanie jest wymagane zarówno przez C, jak i C ++. W C ++ jest to [dcl.enum]: „Jeśli pierwszy moduł wyliczający nie ma inicjatora, wartość odpowiadającej mu stałej wynosi zero. Definicja modułu wyliczającego bez inicjatora daje modułowi wyliczającemu wartość uzyskaną przez zwiększenie wartości poprzedniego modułu wyliczającego o jeden”.
Ben Voigt
3
Tak, a także w innych językach, które zaczynają się na literę C, na przykład C #.
James McNellis
70

C99 Standard

Wersja robocza N1265 C99 zawiera tekst 6.7.2.2/3 „Specyfikatory wyliczenia”

Moduł wyliczający z = definiuje stałą wyliczenia jako wartość wyrażenia stałego. Jeśli pierwszy moduł wyliczający ma no =, wartość jego stałej wyliczania wynosi 0. Każdy kolejny moduł wyliczający z no = definiuje swoją stałą wyliczania jako wartość wyrażenia stałego uzyskanego przez dodanie 1 do wartości poprzedniej stałej wyliczenia. (Użycie modułów wyliczających z = może generować stałe wyliczenia z wartościami, które powielają inne wartości w tym samym wyliczeniu).

W przypadku zgodnych implementacji zawsze obowiązują następujące zasady:

main.c

#include <assert.h>
#include <limits.h>

enum E {
    E0,
    E1,
    E2 = 3,
    E3 = 3,
    E4,
    E5 = INT_MAX,
#if 0
    /* error: overflow in enumeration values */
    E6,
#endif
};

int main(void) {
    /* If unspecified, the first is 0. */
    assert(E0 == 0);
    assert(E1 == 1);
    /* Repeated number, no problem. */
    assert(E2 == 3);
    assert(E3 == 3);
    /* Continue from the last one. */
    assert(E4 == 4);
    assert(E5 == INT_MAX);
    return 0;
}

Skompiluj i uruchom:

gcc -std=c99 -Wall -Wextra -pedantic -o main.out main.c
./main.out

Przetestowano w Ubuntu 16.04, GCC 6.4.0.

Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło
7

Jeśli pierwsza wartość zmiennej wyliczeniowej nie zostanie zainicjowana, kompilator C automatycznie przypisuje wartość 0. Kompilator kontynuuje zwiększanie wartości poprzedniej zmiennej wyliczeniowej o 1.

Na przykład:

enum months{jan,feb,mar}

Wyjaśnienie: wartość jan będzie wynosić 0, luty będzie wynosić 1, mar będzie wynosić 2.

enum months{jan=123,feb=999,mar}

Wyjaśnienie: wartość Jan będzie wynosić 123, luty 999, mar będzie wynosić 1000.

enum months{jan='a',feb='s',mar}

Objaśnienie: Wartość jan to „a”, feb - „s”, mar - „t”.

Vignesh vicky
źródło
1
Ponieważ nie 't'jest to gwarantowane, mogą istnieć zestawy znaków, w których litery nie są w kolejności alfabetycznej
MM
-15

Tak, wartość wyliczenia bydefult zaczyna się od 0 do n-tego elementu na dowolnej platformie.

Devidas Gaikwad
źródło
14
Zastanów się, jak Twoja odpowiedź dodaje się do puli odpowiedzi. To znaczy, w jaki sposób twoja nowa odpowiedź (5 lat później) dodaje coś nowego, czego nie ma w innej odpowiedzi? Na pierwszy rzut oka wydaje się, że zawiera mniej informacji niż pozostałe dwie odpowiedzi.
LawfulEvil
2
Ehhh @LawfulEvil relaks. Wiele odpowiedzi daje ludziom, którzy patrzą na to w przyszłości, wiele perspektyw. To powiedziawszy, jest to źle sformatowana, pozbawiona informacji odpowiedź, ale obszerne odpowiedzi same w sobie nie są złe.
Kenny Worden