Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C hardcoded array as memcpy parameter

I want to pass in a hardcoded char array as the source parameter to memcpy ... Something like this:

memcpy(dest, {0xE3,0x83,0xA2,0xA4,0xCB} ,5);

This compiled with clang gives the following error:

cccc.c:28:14: error: expected expression

If i modify it to be (see the extra parenthesis ):

memcpy(dest,({0xAB,0x13,0xF9,0x93,0xB5}),5);

the error given by clang is:

cccc.c:26:14: warning: incompatible integer to pointer
              conversion passing 'int' to parameter of
              type 'const void *' [-Wint-conversion]

cccc.c:28:40: error: expected ';' after expression
memcpy(c+110,({0xAB,0x13,0xF9,0x93,0xB5}),5);

So, the question:

How do I pass in a hardcoded array as the source parameter of memcpy (http://www.cplusplus.com/reference/cstring/memcpy/)

I have tried:

(void*)(&{0xAB,0x13,0xF9,0x93,0xB5}[0])  - syntax error
{0xAB,0x13,0xF9,0x93,0xB5}               - syntax error
({0xAB,0x13,0xF9,0x93,0xB5})             - see above
(char[])({0xE3,0x83,0xA2,0xA4,0xCB})     - error: cast to incomplete type 'char []' (clang)

and some more insane combinations I'm shamed to write here ...

Please remember: I do NOT want to create a new variable to hold the array.

like image 716
Ferenc Deak Avatar asked Mar 02 '16 11:03

Ferenc Deak


4 Answers

If you use C99 or later, you can use compound literals. (N1256 6.5.2.5)

#include <stdio.h>
#include <string.h>
int main(void){
    char dest[5] = {0};
    memcpy(dest, (char[]){0xE3,0x83,0xA2,0xA4,0xCB} ,5);
    for (int i = 0; i < 5; i++) printf("%X ", (unsigned int)(unsigned char)dest[i]);
    putchar('\n');
    return 0;
}

UPDATE: This worked for C++03 and C++11 on GCC, but are rejected with -pedantic-errors option. This means this is not a valid solution for standard C++.

#include <cstdio>
#include <cstring>
int main(void){
    char dest[5] = {0};
    memcpy(dest, (const char[]){(char)0xE3,(char)0x83,(char)0xA2,(char)0xA4,(char)0xCB} ,5);
    for (int i = 0; i < 5; i++) printf("%X ", (unsigned int)(unsigned char)dest[i]);
    putchar('\n');
    return 0;
}

points are:

  • Make the array const, or taking address of temporary array will be rejected.
  • Cast numbers to char explicitly, or the narrowing conversion will be rejected.
like image 120
MikeCAT Avatar answered Nov 13 '22 23:11

MikeCAT


You can just send a string as parameter. It seems to compile just fine.

#include <iostream>
#include <string.h>
using namespace std;

int main() {
    char dest[6] = {0};
    memcpy(dest,"\XAB\x13\XF9\X93\XB5", 5);

    return 0;
}
like image 21
Igal S. Avatar answered Nov 13 '22 23:11

Igal S.


The best solution is not to do this at all, but to use a temporary variable:

const char src[] = {0xE3,0x83,0xA2,0xA4,0xCB};
memcpy(dest, src, sizeof(src));

This code is the most maintainable, because it contains no "magic numbers", so it will not contain any missing array item or array-out-bounds bugs, like the compound literal version could.

This code is also compatible with C++ and C90.

The most important thing here is to realize that the generated machine code will be identical anyway. Don't think you are doing any form of optimization by using compound literals.

like image 20
Lundin Avatar answered Nov 14 '22 00:11

Lundin


You can use Compound Literals.

int main()
{
    unsigned char dest[5];
    size_t i;

    memcpy(dest, (unsigned char[]){0xE3,0x83,0xA2,0xA4,0xCB} ,5);

    printf("Test: " );
    for(i=0; i<sizeof(dest)/sizeof(dest[0]); i++)
        printf("%02X - ", dest[i] );
    printf("\n");
    return 0;
}
like image 11
LPs Avatar answered Nov 13 '22 23:11

LPs