Инициализация структуры, содержащей массивы - PullRequest
7 голосов
/ 12 февраля 2020

У меня есть структура в C, члены которой являются массивами с плавающей точкой. Я хочу инициализировать его во время компиляции следующим образом:

typedef struct curve {                                                                                         
    float *xs;                                                                                             
    float *ys;                                                                                             
    int    n;                                                                                              
} curve;                                                                                                       

curve mycurve1 = {                                                                                             
    {1, 2, 3},                                                                                                     
    {4, 2, 9},                                                                                                     
    3                                                                                                              
};

curve mycurve2 = {
    {1, 2, 3, 4},
    {0, 0.3, 0.9, 1.5},
    4
};                                                                                                              

Но я получаю ошибки компиляции.

Одним из возможных решений может быть использование массивов, а не указателей в структуре. Это принятый ответ на очень похожий вопрос: { ссылка }, но проблема этого подхода в том, что я не знаю размера массива во время определения типа. Мало того, я мог бы захотеть инициализировать другую, более крупную кривую.

Другой подход может быть с mallo c, но я нахожу это излишним, потому что я знаю размер массива во время компиляции и не мне нужно изменить его во время выполнения.

Я не знаю других подходов, которые могут быть полезны. Может быть, приведение массива к указателю ?? - Я не знаю, как бы я подошел к этому.

Ответы [ 2 ]

7 голосов
/ 12 февраля 2020

Вы не можете инициализировать скалярный объект, например указатель с фигурным списком, который содержит несколько инициализаторов.

Но вы можете использовать составные литералы.

Вот демонстрационная программа.

#include <stdio.h>

typedef struct curve {                                                                                         
    float *xs;                                                                                             
    float *ys;                                                                                             
    int    n;                                                                                              
} curve;                                                                                                       

int main(void) 
{
    curve mycurve1 = 
    {                                                                                             
        ( float[] ){ 1,  2, 3 },                                                                                                     
        ( float[] ){ 4,  2, 9 },                                                                                                     
        3
    };

    curve mycurve2 = 
    {
        ( float[] ){ 1, 2, 3, 4 },
        ( float[] ){ 0, 0.3, 0.9, 1.5 },
        4
    };

    for ( int i = 0; i < mycurve1.n; i++ )
    {
        printf( "%.1f ", mycurve1.xs[i] );
    }
    putchar( '\n' );

    for ( int i = 0; i < mycurve2.n; i++ )
    {
        printf( "%.1f ", mycurve2.ys[i] );
    }
    putchar( '\n' );

    return 0;
}

Его выход

1.0 2.0 3.0 
0.0 0.3 0.9 1.5 
3 голосов
/ 12 февраля 2020

Предлагаемое взятие на @ Влад из Москвы хороший ответ.

Используйте const при постоянной

, потому что я знаю размер массива во время компиляции, и мне не нужно его изменять во время выполнения.

Рассмотрим const curve mycurve1 = .... Это позволяет выбирать оптимизацию, выявляет неправильное использование и позволяет передавать &mycurve1 в bar(const curve *). Также с const float [... позволяет передавать mycurve1.xs на foo(const float *).

Избегать волхвов c чисел

#define CURVE1_N 3
const curve mycurve1 = {
  ( const float[CURVE1_N] ){ 1,  2, 3 },
  ( const float[CURVE1_N] ){ 4,  2, 9 },  
  CURVE1_N
};
...