Re: а кто C хорошо знает?
On Mon, 8 Oct 2012, Dmitry E. Oboukhov wrote:
имеется некая структурка
struct something {
...
unsigned count;
unsigned element[0];
};
то есть в поле count сказано сколько элементов будет после структурки.
ну и обращение к ним идет так:
for (i = 0; i < s->count; i++) {
s->elements[i] = i;
}
теперь когда мы это хотим саллоцировать, то пишем такой аллокатор
struct something * some_alloc(unsigned size) {
return malloc(sizeof(struct something) + sizeof(unsigned) * size);
}
Э.. Насколько я знаю С, уже тут нехорошая вещь.
То чем вы пользуетесь есть расширение gcc
http://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
и как всякое расширение лучше им без необходимости не пользоваться.
В С89 обычная практика использовать:
unsigned element[1];
и затем
struct something * some_alloc(unsigned size) {
return malloc(sizeof(struct something) + sizeof(unsigned) * (size-1));
}
Это наиболее переносимый вариант.
Можно использовать flexible arays из С99
unsigned element[];
(без нуля !)
gcc (>3 версии) отлично их кушает.
а вот если появилась необходимость саллоцировать такой объект
статически, как быть?
хочется макрос
#define SOMETHING(name, size) ...
чтобы пользователь мог сказать
void foo(void) {
static SOMETHING(name, 5);
SOMETHING(name2, 10);
}
и получить саллоцированный на стадии компиляции (или в стеке) такой объект?
Вообще говоря нельзя. Собственно говоря flexible arrays придуманы
именно для удобства алокации памяти в run time.
Как это можно сделать в С++ я тоже не понимаю.
Трюк, который предложил Виктор Вагнер, работает, но кое где
синтаксис прийдется править.
Вот программка для тестирования
------ кусь кусь -----
#include <stdio.h>
#include <stdlib.h>
struct something {
unsigned count;
unsigned element[];
};
#define SOMETHING(NAME, SIZE) \
union{ \
struct something NAME; \
struct { unsigned count; unsigned element[SIZE]; }; \
} NAME;
#define SOMETH_DIN(name, size) struct something* name=some_alloc(size); \
name->count=(size);
struct something* some_alloc(unsigned size) {
return malloc(sizeof(struct something) + sizeof(unsigned) * size);
}
void print_something(struct something* s) {
printf(" something -> count= %u\n", s->count);
int i;
for(i = 0; i < s->count; i++) {
printf(" -> [%i] = %u\n",i,s->element[i]);
}
}
int main() {
struct something *s = some_alloc(10);
s->count=3;
int i;
for(i = 0; i < s->count; i++) {
s->element[i] = i;
}
print_something(s);
SOMETH_DIN(p,5);
for(i = 0; i < p->count; i++) {
p->element[i] = 10+i;
}
print_something(p);
SOMETHING(P,5);
P.count=4;
for(i = 0; i < P.count; i++) {
P.element[i] = 20+i;
}
print_something(&P.P);
return 0;
}
------ кусь кусь -----
Ho!
1) неименованные структуры - это опять же расширение
над ansiC. Если же именовать, то прийдется писать везде P.P
2) в вызове функции все равно прийдется писать P.P
p.s. Что такое "саллоцировать" я даже в гугле поискал )) Велик и могучь р.я.
Reply to: