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?

share|improve this question
    
Have you tried void cpaddr(char target[], const char *source) – jantje Mar 2 '16 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 '16 at 20:33
    
I'm using 4.9.3. Screenshot of result: i.imgur.com/2RJbGwg.png – Mads Skjern Mar 3 '16 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. – underscore_d Jun 26 '16 at 7:13
up vote 3 down vote accepted

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);
share|improve this answer
    
I think that it should be PSTR() instead of F(). F() is a very special Arduino String hack. – Mikael Patel Mar 2 '16 at 22:07
    
F() just imposes a type to PSTR() for overloading. You can use either. – Majenko Mar 2 '16 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*'". – Mikael Patel Mar 2 '16 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 '16 at 22:31
    
But apparently not on memcpy_P as it takes whatever, i.e. const void*. – Mikael Patel Mar 2 '16 at 22:32

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.

share|improve this answer
    
As Majenko said, memcpy would be better than doing a byte-by-byte copy. – Nick Gammon Mar 2 '16 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 '16 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. – underscore_d Jun 26 '16 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 '16 at 9:25

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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