6

Struck hack is used to allocate more memory than the initial need of the struct itself so that you can reference the out-of-bounds part of the array such that you stay inside the memory actually allocated.

Here's how it works.

struct Foo
{
  // ..
  size_t size;
  int data[1];
};

const size_t SIZE = 100;
Foo *p = (Foo*) malloc(sizeof(Foo) + sizeof(int) * (SIZE - 1));
p->size = SIZE;
for (int i = 0; i < p->size; ++i) (p->data)[i] = i;

Question:

Can we just use a single integer instead of an array of size one? If that's doable, why does the array-of-size-one version become much more popular then?

struct Foo
{
  // ..
  size_t size;
  int data;
};

// ..
for (int i = 0; i < p->size; ++i) (&p->data)[i] = i;
Eric Z
  • 14,327
  • 7
  • 45
  • 69
  • Side note: since you're already using implementation-specific code (which is accessing array out of bounds), you can use http://stackoverflow.com/questions/6180012/array-with-size-0 to simplify the allocation call. – liori Jul 24 '11 at 14:35
  • Array of size zero is illegal in C and C++. Isn't it? – Eric Z Jul 24 '11 at 14:40
  • As is accessing array outside its bounds. If you break the standard by using "struct hack", why not use another non-standard thing which actually makes "struct hack" simpler? – liori Jul 24 '11 at 15:04
  • 2
    Yes. But then, so is accessing an array out of bounds. You've already stepped outside the bounds of standard C++, so what's one more form of non-standard behavior between friends? – Dennis Zickefoose Jul 24 '11 at 15:11
  • You cannot get 'int data[0]' compile while you can with 'int data[1]' – Eric Z Jul 24 '11 at 15:11
  • @Dennis Zickefoose: One is ill-formed, the other is well-formed. Yes, both are Undefined Behavior, but that's independent from well-formed-ness. – MSalters Jul 25 '11 at 08:38

4 Answers4

8

Accessing an array outside of it's bounds is undefined behaviour. For example, your debugger might decide to insert canary arrays each side of the array.

The smart thing to do would be to just use a std::vector, that's what it's for. The struct hack is an old C-ism and redundant in C++.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 2
    One thing is that `std::vector` forces an additional allocation (which may be undesirable in some circumstances, e.g. performance-wise). Do you know of a C++ way to allocate only one block of memory for the struct and its array ? – Raphaël Saint-Pierre Jul 27 '11 at 14:03
7

With the second version, you are unable to use the nice-looking direct array synatx. You can't do

p->data[i]

anymore but have to do

(&p->data)[i]

what looks much more ugly.

marc
  • 6,103
  • 1
  • 28
  • 33
  • 1
    Which you wouldn't use in C++ anyway (see tags); your class data is accessed with methods. Question might be mistagged, though, considering the C-isms like `malloc`. – MSalters Jul 25 '11 at 08:39
5

Because it's more convenient to write p->data[i] than (&p->data)[i].

Stan
  • 787
  • 5
  • 16
2

Because p->data[i] is shorter and more readable than(&p->data)[i].

n. m. could be an AI
  • 112,515
  • 14
  • 128
  • 243