32

Pretty self-explanatory. The array is of an integral type, the contents are known and unchanging, and C++0x isn't allowed. It also needs to be declared as a pointer. I just can't seem to find a syntax that works.

The declaration in Class.hpp:

static const unsigned char* Msg;

Stuff in Class.cpp is really what I've tinkered with:

const unsigned char Class::Msg[2] = {0x00, 0x01}; // (type mismatch)
const unsigned char* Class::Msg = new unsigned char[]{0x00, 0x01}; // (no C++0x)

...etc. I've also tried initializing inside the constructor, which of course doesn't work because it's a constant. Is what I'm asking for impossible?

ACK_stoverflow
  • 3,148
  • 4
  • 24
  • 32
  • Is `Msg` declared static in the header and the implementation file? –  Jul 06 '12 at 17:44
  • 6
    Arrays decay into pointers, though, so isn't an array declaration fine? – chris Jul 06 '12 at 17:44
  • Nope, it's only `static` in the header. – ACK_stoverflow Jul 06 '12 at 17:44
  • @chris A value declared as an array isn't acceptable for passing to a function that wants a pointer, which is what these little arrays will all be used for. – ACK_stoverflow Jul 06 '12 at 17:45
  • 2
    Well no wonder, there is a type mismatch. You are confusing arrays and pointers. –  Jul 06 '12 at 17:45
  • But GCC 4.4 supports C++0x, doesn't it? – cha0site Jul 06 '12 at 17:46
  • 1
    @ACK_stoverflow, Any array (non-reference) you pass into a function will be decayed into a pointer, so declaring an array and passing it into a function expecting a pointer works fine. – chris Jul 06 '12 at 17:48
  • @chris perhaps I'm having issues with that because I'm using --pedantic gcc flag? Anyway, this code needs to be squeaky clean, and my compiler yells about that. – ACK_stoverflow Jul 06 '12 at 17:50
  • 1
    @ACK_stoverflow, [This](http://ideone.com/s6Xt9) compiles fine with `-pedantic`, and passes an array into a function taking a pointer. – chris Jul 06 '12 at 17:53
  • @chris You're right. The issue with the function I was passing the value into was the const - it wanted non-const values, but was fine with things declared as either `char[]` or `char*`. You were right from the beginning. – ACK_stoverflow Jul 06 '12 at 18:01
  • @chris You got to the true root of my problem, but the marked answer answered the question as it was asked, so I'm going to leave it like it is. Sorry; but you still dun good. – ACK_stoverflow Jul 06 '12 at 18:22

2 Answers2

51
// in foo.h
class Foo {
    static const unsigned char* Msg;
};

// in foo.cpp
static const unsigned char Foo_Msg_data[] = {0x00,0x01};
const unsigned char* Foo::Msg = Foo_Msg_data;
Michael Burr
  • 333,147
  • 50
  • 533
  • 760
  • 4
    +1, for a solution that uses a pointer and yet avoids the hassle of memory management. – David Rodríguez - dribeas Jul 06 '12 at 17:48
  • We have a winner! I was hoping there was a more compact way, but this definitely does what I was asking for. Nicely done, posted 5 minutes after the question was asked no less! – ACK_stoverflow Jul 06 '12 at 17:52
  • Why does the declaration in the header have to be static, please? – RAAC Apr 06 '14 at 14:47
  • @RAAC because you need it to be static, so that it can be accessed without instantiating an object from the class – Anubis Sep 25 '14 at 04:49
  • 1
    shouldn't the definition not have a `static` qualifier? gcc 4.9.2 tells me to remove it from `foo.cpp`. – Peter Mitrano Oct 05 '15 at 03:56
  • This still has an extra level of indirection vs. having a static array as a class member. :( A clever compiler may see through it and not actually load the array base address from `Msg` (instead using the link-time-constant `Foo_Msg_data` directly), but it's not perfect. – Peter Cordes Oct 02 '16 at 10:44
  • An alternative is a `static const` object of class type, of a class that has a non-static (and non-const) array member. Its constructor can initialize the array (perfect for something like sin/cos lookup tables that are easy and fast to generate once at startup), and has absolutely no overhead for lookups (identical asm to what you'd get for lookups in a static array). The main downside is that the table size is needed in the class definition, so you can't leave it as `float lut[]`. See [this answer for a `std::vector` version](http://stackoverflow.com/a/30077515/224132). – Peter Cordes Oct 02 '16 at 10:47
31

You are mixing pointers and arrays. If what you want is an array, then use an array:

struct test {
   static int data[10];        // array, not pointer!
};
int test::data[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };

If on the other hand you want a pointer, the simplest solution is to write a helper function in the translation unit that defines the member:

struct test {
   static int *data;
};
// cpp
static int* generate_data() {            // static here is "internal linkage"
   int * p = new int[10];
   for ( int i = 0; i < 10; ++i ) p[i] = 10*i;
   return p;
}
int *test::data = generate_data();
Ahmed Nassar
  • 4,683
  • 2
  • 19
  • 26
David Rodríguez - dribeas
  • 204,818
  • 23
  • 294
  • 489
  • 2
    +1 the confusion probably lies because you can access members of a char* in an "array-like" fashion. –  Jul 06 '12 at 17:46
  • Sorry, I should have been more specific: what I need is a const pointer to an array. – ACK_stoverflow Jul 06 '12 at 17:54
  • Why dynamically allocate the memory if the size is known at compile time? The array can be static, and still initialized with a loop at run-time (instead of having a bit table as part of your executable). That allows the compiler to optimize by removing the extra level of indirection, when it can see the pointer assignment (like the other answer suggests). – Peter Cordes Oct 02 '16 at 02:43