2015-12-04 4 views
0

У меня есть следующие структурыИнициализация массива структуры в C

typedef struct { 
    int buf[BUF_SIZE]; // the buffer 
    size_t len; // number of items in the buffer 
    pthread_mutex_t mutex; // needed to add/remove data from the buffer 
    pthread_cond_t can_produce; // signaled when items are removed 
    pthread_cond_t can_consume; // signaled when items are added 
}; 

Изначально я просто инициализирует его следующим образом

buffer_t buffer = { 
    .len = 0, 
    .mutex = PTHREAD_MUTEX_INITIALIZER, 
    .can_produce = PTHREAD_COND_INITIALIZER, 
    .can_consume = PTHREAD_COND_INITIALIZER 
}; 

Хотя я хотел бы, чтобы инициализировать массив buffer_t с этими значениями, хотя я не совсем уверен, как правильно это сделать.

Что-то вроде

buffer_t buffer[NUM_ARRAY] = { 
    .len = 0, 
    .mutex = PTHREAD_MUTEX_INITIALIZER, 
    .can_produce = PTHREAD_COND_INITIALIZER, 
    .can_consume = PTHREAD_COND_INITIALIZER 
}; 

(который я понимаю, неверно)

Edit: Я закончил с использованием

buffer_t buffers[NUM_THREADS]; 

for (i = 0, i < 3, i ++) { 
     buffers[i] = (buffer_t) { 
       .len = 0, 
       .mutex = PTHREAD_MUTEX_INITIALIZER, 
       .can_produce = PTHREAD_COND_INITIALIZER, 
       .can_consume = PTHREAD_COND_INITIALIZER 
      }; 
} 
+1

Петля над каждым буфером в массиве ... Инициализировать его, как раньше ... Прибыль? – Samidamaru

+0

@belgin Fish, предложили ли предлагаемое здесь решение петли на самом деле работать для вас? Я не думаю, что это сработает. –

+0

Он скомпилирован, я до сих пор не дошел до сути использования буфера. Я обновил свой ответ с помощью решения, которое я использовал, не могли бы вы дать мне свой вклад? @BlueMoon –

ответ

3

Если NUM_ARRAY не слишком большой, вы можете сделать что-то вроде этого:

#define NUM_ARRAY 3 

buffer_t buffer[NUM_ARRAY] = { 
    { {0}, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER}, 
    { {0}, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER}, 
    { {0}, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER} 
}; 

Или вы могли бы явно кодировать это следующим образом:

buffer_t buffer[NUM_ARRAY]; 
int i; 
for (i=0; i<NUM_ARRAY; i++) { 
    memset(buffer[i].buf, 0, sizeof(buffer[i].buf)); 
    buffer[i].len = 0; 
    buffer[i].mutex = PTHREAD_MUTEX_INITIALIZER; 
    buffer[i].can_produce = PTHREAD_COND_INITIALIZER; 
    buffer[i].can_consume = PTHREAD_COND_INITIALIZER; 
} 

EDIT:

Так выглядит так: PTHREAD_MUTEX_INITIALIZER и PTHREAD_COND_INITIALIZER макросы не могут использоваться в присваивании как это, поскольку оно предназначено для использования только при инициализации и содержит { и } символов.

Таким образом, вы должны использовать синтаксис инициализации, как другие предположили:

buffer_t buffer[NUM_ARRAY]; 
int i; 
for (i=0; i<NUM_ARRAY; i++) { 
    buffer[i] = (buffer_t) { 
     0, 0, PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, PTHREAD_COND_INITIALIZER 
    }; 
} 
+0

Я пробовал что-то похожее на это раньше и даже используя ваш пример кода, я получаю «ожидаемое выражение перед {токеном» для последних 3 инициализаций в цикле for, вы знаете, почему? –

+0

Вам нужна пара '{}' для инициализации каждого массива и каждой структуры, и между каждым элементом/элементом массива должно быть запятая. Вероятно, у вас где-то было несоответствие. – dbush

+1

Почему бы не использовать составной литерал и избежать «memset»? – Olaf

0

Если буфер является глобальным, вы можете оставить инициализацию в этом частный случай, потому что PTHREAD_MUTEX_INITIALIZER - это структура со всеми нулями. В противном случае у вас не было бы другого выбора, кроме как инициализировать всех участников или программировать через него.

+1

Хотя это верно, это не обязательно относится к области памяти malloc, которая была очищена до нулей с помощью memset (или, альтернативно, выделена и обнулена 'calloc'). Это связано с тем, что C не гарантирует, что двоичное представление нулевого указателя есть все нули (или что двоичное представление с плавающей запятой 0 - все нули, но это не в тему), хотя исключения встречаются очень редко. –

0

Как правило, вы можете инициализировать массив структур что-то вроде этого:

#include <stdio.h> 
#include <stdlib.h> 

typedef struct buffer_t { 
    int a; 
    int b; 
    int c; 
} buffer_t; 

int main() 
{ 
    int i; 
    int NUM_ARRAY=4; 

    buffer_t buffer[NUM_ARRAY]; 

    for(i=0; i<NUM_ARRAY; i++) 
    { 
     buffer[i].a = 0; 
     buffer[i].b = 1; 
     buffer[i].c = 2; 
    }; 

    return 0; 
} 

Я чувствую, что вы после того, как более чем это?

+0

Это довольно подвержено ошибкам при добавлении полей или изменении их типа. – Olaf

2

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

Есть несколько способов, чтобы инициализировать весь массив с тем же struct каждый раз:

  1. Инициализировать каждый элемент массива в явном виде. Пример:

    buffer_t buffer[NUM_ARRAY] = { 
        { 
         .len = 0, 
         .mutex = PTHREAD_MUTEX_INITIALIZER, 
         ... 
        }, 
        { 
         .len = 0, 
         .mutex = PTHREAD_MUTEX_INITIALIZER, 
        }, 
        ... 
    }; 
    

    Это довольно утомительно. Стандартным способом было бы ...

  2. Используйте for цикл:

    buffer_t buffer[NUM_ARRAY]; 
    for (size_t i = 0; i < NUM_ARRAY; ++i) { 
        buffer[i] = (buffer_t) { 
         .len = 0, 
         .mutex = PTHREAD_MUTEX_INITIALIZER, 
         ... 
        }; 
    } 
    

    Путь лучше . Тем не менее, есть еще ...

  3. Designated initializer lists. Некоторые из них были стандартизированы, как те, которые вы используете, но этого нет. Поэтому это нестандартное расширение GCC, но стоит упомянуть в любом случае. Пример:

    buffer_t buffer[NUM_ARRAY] = { 
        [0 ... (NUM_ARRAY - 1)] = { 
         .len = 0, 
         .mutex = PTHREAD_MUTEX_INITIALIZER, 
         ... 
        } 
    }; 
    

Я рекомендую вариант 2-й , хотя.


(buffer_t) { } синтаксис доступен только с C99. Если ваш компилятор не поддерживает его, используйте простое назначение для члена struct.

+0

Просто чтобы добавить, используя хотя бы C99, это хорошая идея. – Olaf

+0

Опции 2 и 3 вызывают UB. –

+1

@BlueMoon: Вы можете понять почему? Это правильно по стандарту. А макросы верхнего регистра должны давать постоянное выражение. Для последнего допустимо даже не константное выражение, поскольку в любом случае оно использует расширение gcc. – Olaf

Смежные вопросы