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
    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
    Mar 2, 2016 at 20:33
  • I'm using 4.9.3. Screenshot of result: i.imgur.com/2RJbGwg.png 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. 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. Mar 2, 2016 at 22:07
  • F() just imposes a type to PSTR() for overloading. You can use either.
    – Majenko
    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*'". 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
    Mar 2, 2016 at 22:31
  • But apparently not on memcpy_P as it takes whatever, i.e. const void*. 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
    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
    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. 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
    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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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