Pergunta

Eu encontrei algum código de inicialização struct ontem que me jogou para um loop. Aqui está um exemplo:

typedef struct { int first; int second; } TEST_STRUCT;
void testFunc() {
    TEST_STRUCT test = {
        second: 2,
        first:  1
    };
    printf("test.first=%d test.second=%d\n", test.first, test.second);
}

Surpreendentemente (para mim), aqui está a saída:

-> testFunc
test.first=1 test.second=2

Como você pode ver, a estrutura é inicializado corretamente. Eu não estava declarações rotulados conscientes poderia ser usada assim. Já vi várias outras maneiras de fazer a inicialização struct, mas eu não encontrar qualquer exemplos deste tipo de inicialização struct em qualquer um dos FAQs C on-line. Alguém está ciente de como / por que isso funciona?

Foi útil?

Solução

Aqui é a seção do manual gcc que explica a sintaxe dos inicializadores designados para ambas as estruturas e matrizes:

Em um inicializador estrutura, especificar o nome de um campo para inicializar com ' .fieldname = ' antes de o valor do elemento. Por exemplo, dada a seguinte estrutura,

 struct point { int x, y; };

o seguinte inicialização

 struct point p = { .y = yvalue, .x = xvalue }; 

é equivalente a

 struct point p = { xvalue, yvalue }; 

Outra sintaxe que tem o mesmo significado, obsoleto desde GCC 2.5, é ' nome do campo: ', como mostrado aqui:

 struct point p = { y: yvalue, x: xvalue };

A página relevante pode ser encontrada aqui .

O seu compilador deve ter a documentação similar.

Outras dicas

Estes não são nem etiquetas nem bitfields.

Esta é uma sintaxe para inicializar os membros de struct que datam dos dias antes da C99. Ele não é normalizada mas disponível em e.g. gcc.

typedef struct { int y; int x; } POINT;
POINT p = { x: 1, y: 17 };

Em C99, foi introduzido sintaxe para inicializar os membros de struct específicas pela primeira vez em um padrão, mas parece um pouco diferente:

typedef struct { int y; int x; } POINT;
POINT p = { .x = 1, .y = 17 };

Sim, como apontado acima, estes initializers são designados, que são padrão C, mas você deve passar a usar períodos em vez de dois pontos. E como você notar, a maioria dos livros lá fora ainda estão em algum lugar preso em torno de 1984 em sua sintaxe e deixar de mencioná-los. fatos mais divertidos:

- Ao usar inicializadores designados, tudo não especificado é inicializado em zero. Isto ajuda com excepcionalmente grandes estruturas, p.ex.:.

typedef struct {
   double a, b, c, d, e;
   char label[100];
} too_many_type;

too_many_type tm = {.a = 1, .e = 2, .b=1.5};
assert(tm.a + tm.b + tm.c + tm.d + tm.e == 4.5);
assert(!strlen(label));
.

- Além disso, você pode usar o formulário literal composto para utilizar este formulário em uma linha não-inicialização, por exemplo:

too_many_type tm2;
tm2 = (too_many_type) {.a = 3, .e=6};

Estes são realmente grandes recursos, e são suportados por cada compilador C que eu posso pensar, sendo que é o padrão. É uma pena que eles não estão tão bem conhecido.

Não é realmente "declarações rotulado", mas uma maneira de dar valores iniciais para os campos nomeados na estrutura.

GCC dá um aviso sobre "uso obsoleto da designada initializer com ':'", e em C99 você deveria escrever:

    TEST_STRUCT test = {
        .second = 2,
        .first =  1
    };

Essa sintaxe não é definida pelo padrão C. Seção 6.7.8 Initialization diz

         designation:
                designator-list =
         designator-list:
                designator
                designator-list designator
         designator:
                [ constant-expression ]
                . identifier

Se o seu compilador aceita uma designação com dois pontos, sem uma mensagem de diagnóstico significa que o compilador não é (ou está configurado para não ser) Padrões de Conformidade.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top