tags:

views:

98

answers:

4

My questions are in the code, but basically i want to know how/if I can do the two commented out lines? I know I can do it in a constructor but I don't want to!

struct foo
{
    int b[4];
} boo;

//boo.b[] = {7, 6, 5, 4}; // <- why doesn't this work? (syntax error : ']')
//boo.b = {7, 6, 5, 4}; // <- or else this? (syntax error : '{')

boo.b[0] = 7; // <- doing it this way is annoying
boo.b[1] = 6; // :
boo.b[2] = 5; // :
boo.b[3] = 4; // <- doing it this way is annoying

boo.b[4] = 3; // <- why does this work!

(Using: C++, Visual Studio 2005.)

+8  A: 

You can only use the initialization in the definition:

struct foo
{
    int b[4];
};
foo boo = { 7, 6, 5, 4 };

On the last question: 'why does boo.b[4] = 3 work?' The answer is that it is undefined behavior, and UB allows for quite a bit of different situations. Neither the compiler nor the runtime environment has to diagnose it, and in many cases the result will be overwritting the next element in memory. That could be tested with the following code:

// Test
foo boo;
int x = 0;
boo.b[4] = 5;
std::cout << x << std::endl;

NOTE: This is undefined behavior, so whatever the result of the test is, it is incorrect and cannot be assumed to be a repeatable test.

David Rodríguez - dribeas
More specifically, the ability to refer to elements beyond the array bounds is legal. The behavior will depend on whether that memory location belongs to another variable. So in this case the exact behavior is undefined in that the '5' may or may not end up overwriting the value of 'x'. However, if you have arranged to allocate extra memory beyond the end of the struct, then such array accesses would be ok. Thus you may sometimes see struct definitions for message headers that end in a 1 byte array field which really is just the beginning of variable-length multi-byte data.
Christopher Barber
+2  A: 
struct foo
{
    int b[4];
} boo = {7,6,5,4};
drawnonward
+1  A: 

In case you do need to write to that structure's member after it was initialized, it looks like your values are following a simple pattern (start with 7 and decrement by one), which means std::generate() or std::generate_n() could do the job, too:

#include <algorithm>
class DecrementFrom {
        int val;
public:
        DecrementFrom(int start) : val(start) {}
        int operator()() { return val--; }
};

std::generate_n(foo.b, 4, DecrementFrom(7));
Cubbi
+1  A: 

Strictly speaking, the syntax for initializing an array inside a struct is:

struct foo 
{ 
    int b[4]; 
}; 
foo boo = { { 7, 6, 5, 4 } };

However, according to 6.7.8.17 of the C standard, the compiler will implicitly track the appropriate scope if you do not provide it.

MSN