[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

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: