1

I have 2 defines, one with a string and one with a number.How can i make a const array from the define with the string and the number. There are also some additional constant which should be in this array.

How can i write this Code to have 0x22, 0x41, 0x42, 0x42, 0x21 in the array foobar, from the defines FOO and BAR?

#define FOO "AB"
#define BAR 33

extern int rs232_write(const unsigned char *data, unsigned char count);

const unsigned char foobar[] =
{
    0x22,
    FOO[0], /*what must i put here, this do not work*/
    FOO[1],
    0x42,
    BAR,
};


int main(void)
{
    rs232_write(foobar,sizeof(foobar));
    return 1;
}

In gcc, for example, i get the error:

./001.c:9:5: error: initializer element is not constant
     FOO[0], /*what must i put here*/
     ^

The String have always the same length. I did also a try the other way around:

#define FOO "AB"
#define BAR 33

extern int rs232_write(const unsigned char *data, unsigned char count);

const char foobar[] = \
    "\x22" \
    FOO    \
    "\x42" \
    BAR   /*what must i put here, this also not work*/


int main(void)
{
    rs232_write(foobar,sizeof(foobar));
    return 1;
}

Here i get also a error, for example gcc prints:

./002.c:2:13: error: expected ‘,’ or ‘;’ before numeric constant
 #define BAR 33
             ^

I working on a Microcontroller with not much space, so i would like to avoid creating the array at runtime and my compiler do only support C89.

4
  • What is wrong with the code you show us? Commented Jan 30, 2017 at 12:29
  • See the comment, compiler do not accept it (also tryed with gcc), "error: initializer element is not constant" and "error: expected ‘,’ or ‘;’ before numeric constant" Commented Jan 30, 2017 at 12:30
  • When posting questions about build errors, always include the exact errors (in unedited and unmodified and most importantly complete form) in the body of the question. Preferably a straight copy-paste of the full build log. Commented Jan 30, 2017 at 12:32
  • @Someprogrammerdude The point is, it is not valid in C89 (and as far as i know also not in C99 or C11), so it is nothing about a compiler problem. But i put a error example of a compiler. Commented Jan 30, 2017 at 12:36

4 Answers 4

1

The simplest, using memcpy:

#include <stdio.h>
#include <string.h>

#define FOO "AB"
#define BAR 33

extern int rs232_write(const unsigned char *data, unsigned char count);

unsigned char _foobar[] =
{
    0x22,
    0, 0,
    0x42,
    BAR,
};
const unsigned char *foobar;

int main(void)
{
    foobar = (const unsigned char *)memcpy(_foobar + 1, FOO, 2) - 1;
    rs232_write(foobar,sizeof(foobar));
    return 0;
}

The ugly, using an X Macro and a compound literal:

In this way you can use the first two digits:

const unsigned char foobar[] =
{
    0x22,
    'A', 'B',
    0x42,
    33,
};

or the full string "AB"

#include <stdio.h>

#define FOO X('A', 'B', '\0')
#define BAR 33

extern int rs232_write(const unsigned char *data, unsigned char count);

const unsigned char foobar[] =
{
    0x22,
    #define X(a, b, c) a, b
    FOO,
    #undef X
    #define X(a, b, c) ((char []){a, b, c})
    0x42,
    BAR,
};

int main(void)
{
//  rs232_write(foobar,sizeof(foobar));
    printf("%s\n", FOO);
    return 0;
}

Output:

AB
Sign up to request clarification or add additional context in comments.

4 Comments

The memcpy(), or in my case, simple write the two values, is that was i trying to avoid. but X Macro will work. I did not know that you can create a array and make a function call at the same time.
Is not a function call, take a look to the link: Those features are that macros can call other macros, that macros may be redefined, and that a nested macro call is not expanded until the macro that calls it is expanded during one of its calls.
No, i talk about something like strcpy(buffer,((char []){0x44,0x61,0})), that i can call strcpy() with a array which i not create before, and without a string, not about the macros.
Ah, ok, yes, this is called a compound literal, edited
1

This should work:

#include<stdio.h>

#define FOO 'A','B'
#define BAR 33

const char foobar[] = {
    0x22,
    FOO,
    0x42,
    BAR,  
    '\0'
};

int main(void)
{
    printf("%s\n", foobar);
    return 0;
}

BTW it is very bad to init the array that way, maybe you can explain your aim better.

2 Comments

But i still need FOO as string on other places, so it is possible to create a const string from this define?
It is based on a binary rs232 protocol, which i can not change, and i need to send the software name and version in one package (group of frames).
1
#include <stdio.h>
#include <stdlib.h>

#define FOO           "ab"
#define BAR           33

#define STRINGIFY(x)  STRINGIFY2(x)
#define STRINGIFY2(x) #x

const char foobar[] = "\x22" FOO "\x42" STRINGIFY(BAR);

int main(void)
{
  printf("foobar = |%s| (%ld+1 characters)\n",
    foobar, (long) sizeof(foobar) - 1);
  return EXIT_SUCCESS;
}

Running this program ouputs:

foobar = |"abB33| (6+1 characters)

3 Comments

I do want to have the byte 33 or in this case the character '!' in the array, not the bytes 51 (0x33) or the character "3". So it should print "abB!"
@12431234123412341234123: Then why not simply #define BAR "\x21" or #define BAR "!"?
I need BAR as a integer in other places. but maybe i can #define _BAR "!" and #define BAR _BAR[0]
0

The problem is that the compiler doesn't know, at the time of compilation, where the string literal "AB" will be placed in memory. Its location will be decided when the program is linked or possibly when it is loaded into memory.

Therefore using it will not result in a compile-time constant that is required for the initialization of the foobar array.

In this case you really have no option but to use setting foobar[1] and foobar[2] once at run-time. However, even on an extremely small embedded system this will not incur much overhead either in memory or in time. If the program runs more than a few seconds it will most likely not even be measurable.

4 Comments

I do not care about the time, but the memory usage of my program is already a problem and i try to reduce it to not need to enable any optimization. 20 Bytes RAM maybe sounds extremely small, but you will notice it with only 1KiB
@12431234123412341234123 Adding the run-time initialization will add about two more instructions. If you have only this single array then it's not likely to cause a problem. If you have many arrays like this, you might consider using only one and then initialize all at run-time. Code is (often) smaller than data. And why don't you want to enable optimization? Have you tried building with e.g. -Os? Does it make any difference?
@12431234123412341234123 Oh, and you should probably have added all the limitations and the target platform to your question, it is very relevant information.
enable optimizations makes debugging harder. The target is not relevant to the questions, since i only ask a thing about plain C. But it is a MSP430 from the MSP430x4-Family. My Programmcode is a lot bigger than the vRAM. (There are also much more nvRAM than vRAM, about 50 times more)

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.