5

I need to hard code 8 byte addresses into char arrays of length 8. This must be done many places in my code (in function scope), so I have tried to come up with a one-liner. The following works perfectly in C when compiling with gcc.

char a[8];

void cpaddr(char target[], char *source) {
    int i;
    for (i=0; i<8; i++)
        target[i] = source[i];
}

int main() {
    char b[] = {0x00, 0x10, 0xFF, 0xCA, 0x00, 0x00, 0xA2, 0x7D};
    cpaddr(a, b);

    // line below does not compile with Arduino IDE
    cpaddr(a, (char[]) {0x00, 0x10, 0xFF, 0xCA, 0x00, 0x00, 0xA2, 0x7D});
}

When compiling on Arduino the last line, which is the one-liner I was aiming for, does not compile. It gives:

/home/bob/Desktop/ate/Ate.ino: In function 'int main()':
Ate:101: error: taking address of temporary array
cpaddr(a, (char[]) {0x00, 0x10, 0xFF, 0xCA, 0x00, 0x00, 0xA2, 0x7D});
^
exit status 1
taking address of temporary array

What is the problem here, that apparently is not a problem with gcc?

How do I fix it?

4
  • Have you tried void cpaddr(char target[], const char *source)
    – jantje
    Commented Mar 2, 2016 at 13:25
  • I tried your exact code with g++ (and gcc) version 4.8.4 and got the exact same error message you got.
    – Nick Gammon
    Commented Mar 2, 2016 at 20:33
  • I'm using 4.9.3. Screenshot of result: i.imgur.com/2RJbGwg.png Commented Mar 3, 2016 at 8:19
  • ( type[] ){val, ues} is not a valid way to create a temporary in C++: stackoverflow.com/questions/15458883/… The solution is to typedef it. Commented Jun 26, 2016 at 7:13

3 Answers 3

4

It is quite right, using that kind of syntax is not allowed. It's a bit of a pain, but it's ok since there is an alternative method - kind of a "trick" if you will.

That trick is to use a string, not an array. After all, a string is just an array, it's just handled slightly differently by the compiler.

Instead of using {...} use "..." and use the hexadecimal character escape sequence \xNN, such as:

cpaddr(a, "\x00\x10\xFF\xCA\x00\x00\xA2\x7D");

You could even lose your custom function and use a standard library function - memcpy():

memcpy(a, "\x00\x10\xFF\xCA\x00\x00\xA2\x7D", 8);

On the 8-bit AVRs you can save RAM by using the progmem variant and the F() macro:

memcpy_P(a, F("\x00\x10\xFF\xCA\x00\x00\xA2\x7D"), 8);
10
  • I think that it should be PSTR() instead of F(). F() is a very special Arduino String hack. Commented Mar 2, 2016 at 22:07
  • F() just imposes a type to PSTR() for overloading. You can use either.
    – Majenko
    Commented Mar 2, 2016 at 22:17
  • Because of the type you cannot use F() directly without a cast. The compiler will say "cannot convert 'const __FlashStringHelper*' to 'const char*'". Commented Mar 2, 2016 at 22:30
  • Mine didn't. It compiled perfectly fine. I always test before posting code. It's not a cast, it's a reinterpret_cast.
    – Majenko
    Commented Mar 2, 2016 at 22:31
  • But apparently not on memcpy_P as it takes whatever, i.e. const void*. Commented Mar 2, 2016 at 22:32
1

See Using array init list as temporary in C++11?

You can solve it by using const. This compiles:

char a[8];

void cpaddr(char target[], const byte *source) {
    int i;
    for (i=0; i<8; i++)
        target[i] = source[i];
}

int main() {
    byte b[] = {0x00, 0x10, 0xFF, 0xCA, 0x00, 0x00, 0xA2, 0x7D};
    cpaddr(a, b);
    cpaddr(a, (const byte[]) {0x00, 0x10, 0xFF, 0xCA, 0x00, 0x00, 0xA2, 0x7D});
}

Note I had to change your array from char to byte because I was getting (valid) warnings that things like 0xCA don't fit into a char.

4
  • As Majenko said, memcpy would be better than doing a byte-by-byte copy.
    – Nick Gammon
    Commented Mar 2, 2016 at 20:41
  • I hate it when people use non-standard arduino specific types like byte, when there is a perfectly good and standard uint8_t available...
    – Majenko
    Commented Mar 3, 2016 at 20:14
  • As explained in the very thread you linked, ( type[] ){val, ues} is not a valid way to create a temporary in C++: stackoverflow.com/questions/15458883/… The solution is to typedef it. Commented Jun 26, 2016 at 7:12
  • Recent versions of the IDE use C++11, so whether or not it is valid in C++ doesn't really matter.
    – Nick Gammon
    Commented Jun 26, 2016 at 9:25
0

How do I fix it?

"Char []" shouldn't compile under c. It is just invalid.

You can use string, cast to char * . or just another pointer as you did already.

Not the answer you're looking for? Browse other questions tagged or ask your own question.