Как задать размер массива внутри структуры с помощью переменной?
Пытаюсь создать структуру и хочется размер массива внутри неё задавать при инициализации структуры. Пробую написать что-то вроде вот этого:
struct data
{
uint8_t buffsize;
uint8_t data[buffsize];
uint8_t counter;
}d;
но компилятор ругается (error: 'buffsize' undeclared here (not in a function)). Структуру объявляю не внутри функции, нужно чтобы она была видна из любого места программы. Можно ли как-то это сделать средствами языка С? Или в Си нельзя задавать размер массива с помощью переменной?
Ответы (3 шт):
Если структура физически находиться в стеке, то изменить размер уже нельзя. Все локальные переменные занимают место в памяти рядом. Вариант первый: не массив а указатель на память в куче. Вариант два : объект будет только в куче и с последним элементом массивом плавающего размера.
// gcc -Wall -std=c11 vararr.c -o vararr
# include <stdint.h>
# include <stdio.h>
# include <stdlib.h>
// вариант 1
typedef struct datap datap ;
struct datap
{
uint8_t buffsize;
uint8_t counter;
uint8_t * data ;
} ;
// вариант 2
typedef struct datav datav ;
struct datav
{
uint8_t buffsize;
uint8_t counter;
uint8_t data [ ] ;
} ;
int main ( ) {
// вариант 1
unsigned int n = 10 ;
datap dp = { .buffsize = n , .counter = 0 ,
.data = malloc ( sizeof(uint8_t[n]) ) } ;
dp . data [ 5 ] = 5 ;
printf("sizeof(dp)=%zu\n",sizeof(dp));
printf("sizeof(dp)+sizeof(uint8_t[%u])=%zu\n",n,
sizeof(dp)+sizeof(uint8_t[n]));
free ( dp . data ) ;
// вариант 2
unsigned int m = 10 ;
datav * const dv = malloc ( sizeof ( datav ) + sizeof(uint8_t[m]) ) ;
printf("sizeof(dv)=%zu\n",sizeof(dv));
printf("sizeof(dv)+sizeof(datav)=%zu\n",sizeof(dv)+sizeof(datav));
printf("sizeof(dv)+sizeof(datav)+sizeof(uint8_t[%u])=%zu\n",m,
sizeof(dv)+sizeof(datav)+sizeof(uint8_t[m]));
dv -> buffsize = m ;
dv -> counter = 0 ;
dv -> data [ 5 ] = 5 ;
free ( dv ) ; }
Результат :
> ./vararr
sizeof(dp)=16
sizeof(dp)+sizeof(uint8_t[10])=26
sizeof(dv)=8
sizeof(dv)+sizeof(datav)=10
sizeof(dv)+sizeof(datav)+sizeof(uint8_t[10])=20
Память массива всегда должна будет находиться в куче. Первый вариант мобильнее. Позволяет менять размеры и быстрее делать операции копирования, переноса. Второй вариант экономнее. Но изменение размеров не позволяет.
Тебе уже норм ответили. Может быть подойдёт такой вариант:
#define buffsize 10
struct data
{
uint8_t data[buffsize];
uint8_t counter;
} d;
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
struct data
{
uint8_t buffsize;
uint8_t* data;
uint8_t counter;
};
int initData(struct data* d, const uint8_t* data, uint8_t buffsize, uint8_t counter)
{
d->data = malloc(buffsize);
if (d->data == NULL)
{
return -1;
}
memcpy(d->data, data, buffsize);
d->buffsize = buffsize;
d->counter = counter;
return 0;
}
void cleanData(struct data* d)
{
free(d->data);
d->data = NULL;
}
int main()
{
struct data d = {0, NULL, 0};
uint8_t data[] = {9, 8, 7, 6};
initData(&d, data, sizeof(data), 1);
printf("2-th element = '%d' buffsize: %d\n", d.data[1], d.buffsize);
cleanData(&d);
return 0;
}