Wie functionieren designated initializers?

Gast #4522194
Lesenswert?

Hallo,

kann mir jemand sagen wie das da unten funktioniert bzw. was das genau 
ist und wozu man es benutzen kann? Was ein struct ist, ist mir klar aber 
bei mir sehen die irgendwie einfacher aus.
1
static const struct pios_overo_cfg pios_overo_cfg = {
2
    .regs  = SPI2,
3
    .remap = GPIO_AF_SPI2,
4
    .init  = {
5
        .SPI_Mode              = SPI_Mode_Slave,
6
        .SPI_Direction         = SPI_Direction_2Lines_FullDuplex,
7
        .SPI_DataSize          = SPI_DataSize_8b,
8
        .SPI_NSS                                   = SPI_NSS_Hard,
9
        .SPI_FirstBit          = SPI_FirstBit_MSB,
10
        .SPI_CRCPolynomial     = 7,
11
        .SPI_CPOL              = SPI_CPOL_High,
12
        .SPI_CPHA              = SPI_CPHA_2Edge,
13
        .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2,
14
    },
15
    .use_crc = false,
16
    .dma     = {
17
        .irq                                       = {
18
            // Note this is the stream ID that triggers interrupts (in this case TX)
19
            .flags = (DMA_IT_TCIF7),
20
            .init  = {
21
                .NVIC_IRQChannel    = DMA1_Stream7_IRQn,
22
                .NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH,
23
                .NVIC_IRQChannelSubPriority        = 0,
24
                .NVIC_IRQChannelCmd = ENABLE,
25
            },
26
        },
27

28
        .rx                                        = {
29
            .channel = DMA1_Stream0,
30
            .init    = {
31
                .DMA_Channel            = DMA_Channel_0,
32
                .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR),
33
                .DMA_DIR                = DMA_DIR_PeripheralToMemory,
34
                .DMA_PeripheralInc      = DMA_PeripheralInc_Disable,
35
                .DMA_MemoryInc          = DMA_MemoryInc_Enable,
36
                .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
37
                .DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte,
38
                .DMA_Mode               = DMA_Mode_Circular,
39
                .DMA_Priority           = DMA_Priority_Medium,
40
                // TODO: Enable FIFO
41
                .DMA_FIFOMode           = DMA_FIFOMode_Disable,
42
                .DMA_FIFOThreshold      = DMA_FIFOThreshold_Full,
43
                .DMA_MemoryBurst        = DMA_MemoryBurst_Single,
44
                .DMA_PeripheralBurst    = DMA_PeripheralBurst_Single,
45
            },
46
        },
47
        .tx                                        = {
48
            .channel = DMA1_Stream7,
49
            .init    = {
50
                .DMA_Channel            = DMA_Channel_0,
51
                .DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR),
52
                .DMA_DIR                = DMA_DIR_MemoryToPeripheral,
53
                .DMA_PeripheralInc      = DMA_PeripheralInc_Disable,
54
                .DMA_MemoryInc          = DMA_MemoryInc_Enable,
55
                .DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
56
                .DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte,
57
                .DMA_Mode               = DMA_Mode_Circular,
58
                .DMA_Priority           = DMA_Priority_Medium,
59
                .DMA_FIFOMode           = DMA_FIFOMode_Disable,
60
                .DMA_FIFOThreshold      = DMA_FIFOThreshold_Full,
61
                .DMA_MemoryBurst        = DMA_MemoryBurst_Single,
62
                .DMA_PeripheralBurst    = DMA_PeripheralBurst_Single,
63
            },
64
        },
65
    },
66
    .sclk                                          = {
67
        .gpio = GPIOB,
68
        .init = {
69
            .GPIO_Pin   = GPIO_Pin_13,
70
            .GPIO_Speed = GPIO_Speed_100MHz,
71
            .GPIO_Mode  = GPIO_Mode_AF,
72
            .GPIO_OType = GPIO_OType_PP,
73
            .GPIO_PuPd  = GPIO_PuPd_NOPULL
74
        },
75
    },
76
    .miso                                          = {
77
        .gpio = GPIOB,
78
        .init = {
79
            .GPIO_Pin   = GPIO_Pin_14,
80
            .GPIO_Speed = GPIO_Speed_50MHz,
81
            .GPIO_Mode  = GPIO_Mode_AF,
82
            .GPIO_OType = GPIO_OType_PP,
83
            .GPIO_PuPd  = GPIO_PuPd_NOPULL
84
        },
85
    },
86
    .mosi                                          = {
87
        .gpio = GPIOB,
88
        .init = {
89
            .GPIO_Pin   = GPIO_Pin_15,
90
            .GPIO_Speed = GPIO_Speed_50MHz,
91
            .GPIO_Mode  = GPIO_Mode_AF,
92
            .GPIO_OType = GPIO_OType_PP,
93
            .GPIO_PuPd  = GPIO_PuPd_NOPULL
94
        },
95
    },
96
    .slave_count                                   = 1,
97
    .ssel                                          = {
98
        {
99
            .gpio = GPIOB,
100
            .init = {
101
                .GPIO_Pin   = GPIO_Pin_12,
102
                .GPIO_Speed = GPIO_Speed_50MHz,
103
                .GPIO_Mode  = GPIO_Mode_OUT,
104
                .GPIO_OType = GPIO_OType_PP,
105
                .GPIO_PuPd  = GPIO_PuPd_UP
106
            },
107
        }
108
    },
109
};
#4522214
Lesenswert?

Das sind einfach mehrfach verschachtelte Strukturen.

Die selbe Initialisierung würde als Code so aussehen:
1
pios_overo_cfg.regs  = SPI2;
2
pios_overo_cfg.remap = GPIO_AF_SPI2;
3
pios_overo_cfg.init.SPI_Mode              = SPI_Mode_Slave;
4
pios_overo_cfg.init.SPI_Direction         = SPI_Direction_2Lines_FullDuplex;
5
pios_overo_cfg.init.SPI_DataSize          = SPI_DataSize_8b;
6
//...
7
pios_overo_cfg.use_crc = false;
8
// Note this is the stream ID that triggers interrupts (in this case TX)
9
pios_overo_cfg.dma.irq.flags = (DMA_IT_TCIF7);
10
pios_overo_cfg.dma.irq.init.NVIC_IRQChannel    = DMA1_Stream7_IRQn;
11
pios_overo_cfg.dma.irq.init.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH;
12
pios_overo_cfg.dma.irq.init.NVIC_IRQChannelSubPriority        = 0;
13
pios_overo_cfg.dma.irq.init.NVIC_IRQChannelCmd = ENABLE;
14
pios_overo_cfg.dma.rx.channel = DMA1_Stream0;
15
pios_overo_cfg.dma.rx.init.DMA_Channel            = DMA_Channel_0;
16
pios_overo_cfg.dma.rx.init.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR);
17
//...
Persönliche Seite #4522436
Lesenswert?

Vereinfacht:
1
struct bla
2
{
3
  int a;
4
  int b;
5
  int c;
6
};
7

8
// klassische Initialisierung
9

10
struct bla eins = { 1, 2, 3 };
11

12
// mit "designated initializers"
13

14
struct bla zwei = { .b = 2, .a = 1, .c = 3 };

Bei der klassischen Initialisierung müssen die Initialisierer in der 
korrekten Reihenfolge angegeben werden, wenn nur ein Element der 
Struktur (mit einem von 0 abweichenden Wert) initialisiert werden soll, 
dann müssen alle Elemente der Struktur, die in der Deklaration vorher 
stehen, auch initialisiert werden.

Will man im obigen Beispiel nur das Strukturelement c initialisieren, 
müssen der Reihenfolge wegen zwangsweise auch a und b initialisiert 
werden.

Bei "designated initializers" ist die Reihenfolge egal, und so ist auch 
eine alleinige Initialisierung von c möglich; a und b werden dann mit 0 
initialisiert.
Gast #4522590
Lesenswert?

Und gerade bei einer so komplexen Struktur hat man den Vorteil, dass man 
gleich sieht, welches Element welchen Wert bekommt, ohne dass man 
daneben noch die Definition des Typs sehen und die Elemente einzeln 
abzählen muss.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren