How do I #define an array in C? - c

Is the following syntax to define an array valid syntax in C?
#define array[] { \
for (j=0; j<N_frequencysteps;j++) \
{ \
array[j] = (function); \
} \
}
If not, how do I define an array in C?

It depends on how you define 'valid syntax'.
The C pre-processor will accept it as an object-like macro.
The C compiler will not accept the output as legitimate C.
Consider an invocation:
array[23];
The C compiler sees:
[] { for (j=0; j<N_frequencysteps;j++) { array[j] = (function); } } [23];
That is gibberish (even with the 'enter code here' removed).
How can you define an array in C?
enum { ARRAYSIZE = 23 };
int array[ARRAYSIZE];
int j;
for (j = 0; j < ARRAYSIZE; j++)
array[j] = 0;
You could also use an initializer, but you might get compiler warnings unless you are thorough:
int array[ARRAYSIZE] = { 0 };
One more possibility: if you want to define an array and initialize it with calls to a specific function, then you could, I suppose, try:
#define ARRAY(type, name, size, initializer) type name[size]; \
for (int j = 0; j < size; j++) name[j] = initializer
This could be used as:
ARRAY(int, array, 23, j % 9);
(Note that this initializer depends on an implementation detail of the macro - not a good idea. But I don't think I'd ever use such a macro, anyway.) It depends on you being in C99 mode if you have more than one of these in a particular block of code (since it would then mix code with declarations) - and also because the declaration in the for loop is only supported in C++ and C99, not in C90.

This looks really wrong. Why not define array in a normal way?
int array[SIZE];
for (j=0; j<N_frequencysteps;j++)
{
array[j] = (function);
}

Related

How could I correct this macro?

I wrote this for my homework:
#define SUMARRAY(array, size) ({ \
int sum = 0; \
for (int i = 0; i < size; i++) \
{ \
sum += array[i]; \
} \
sum; \
})
The warning is:
ISO C forbids braced-groups within expression
Edit:
Compiler:
gcc (MinGW.org GCC-6.3.0-1) 6.3.0
ISO C11
The assignment is:
Write a program that defines and uses macro SUMARRAY to sum the values in a numeric array. The macro should receive the array and the number of elements in the array as arguments.
There is no need to use a macro for this.
You use a gcc extension to create an expression from a statement, which your compiler refuses under strict ISO C conformance option (-std=c90 or similar), there is no simple solution to write this macro is a conformant way.
Note these extra problems with this macro:
the macro arguments are not parenthesized in the expansion, so you may experience precedence problems if you pass expressions.
the macro defines new variables i and sum... This will pose a problem if you already have variables with these names where you instantiate the macro, especially if you pass sum or i as a macro argument.
the macro assumes array has integer contents
Here is a safer way to write this macro:
#define SUMARRAY(array, size) ({ \
int sum__ = 0; \
size_t size__ = (size); \
typeof(*(array)) *array__ = (array); \
for (size_t i__ = 0; i__ < size__; i__++) \
sum__ += array__[i__]; \
sum__; \
})
I would recommend you write a function instead:
static inline int sumarray(const int *array, int size) {
int sum = 0;
for (int i = 0; i < size; i++)
sum += array[i];
return sum;
}
If you really need to use a macro, write it as a simple wrapper:
#define SUMARRAY(array, size) sumarray(array, size)

Can macro in c generate serialized statement? [duplicate]

I want to generate an array initializer with arbitrary logic that unfortunately requires some looping.
#define RANDOM_ARRAY(n) \
...
double array[] = RANDOM_ARRAY(10);
Suppose the code above generates an initializer for a 10-element array. Is it possible to define such a macro (with a loop) in C99 ?
NB: it doesn't have to be a macro if a function call could suffice (but it has to be possible to call it among global initializers, not in a second function);
Unfortunately, it is not possible to create a recursive (or loop) macrofunction in C. Nevertheless, if you have a reasonable maximum length for your initializer, you can use this type of construct :
#define INITIALIZER(N) { INITIALIZER_ ## N }
#define INITIALIZER_1 1
#define INITIALIZER_2 INITIALIZER_1, 2
#define INITIALIZER_3 INITIALIZER_2, 3
int
main(void)
{
int tab[3] = INITIALIZER(3);
return 0;
}
The C preprocessor doesn't support loops, so what you want is not (easily) possible.
I added the '(easily)' because there are ways to get loop-like behavior using something like boost's ITERATE. This uses recursive file inclusion to emulate a loop. But I'm not sure if you want to go that far.
Since you're working in C99, you can of course create a macro that does the initialization, but you won't be able to make it look like an initializer:
#define INCREMENTING_ARRAY(t,a,n) t a[n]; do {\
for(size_t i = 0; i < n; ++i)\
a[i] = i;\
} while(0);
This creates an array whose elements are initialized to be incrementing, as an example.
Usage:
int main(void)
{
INCREMENTING_ARRAY(int, dozen, 12);
int i;
for(i = 0; i < sizeof dozen / sizeof *dozen; ++i)
printf("array at %d = %d\n", i, dozen[i]);
return 0;
}
This works since in C99 you can freely mix declarations and code, so the int i; after the macro usage is fine. In C89, it wouldn't have worked.

Check if int is defined as macro. C

I've tried to check around, but I can't seem to find an answer.
I'm writing some C code, and I want to figure out if given int i, is that defined as a macro somewhere. For instance, running a for loop checking if the counter is a macro. I've come up with the following, but it give me warnings when I compile, so I'm assuming its bad code
for(int i = 1; i < 25; i++){
#define DEFINED 1
#ifndef i
#define DEFINED 0
#endif
int a = DEFINED;
if(a){
bla bla
}
}
Thank you so much.
Short answer: You can't use the value of i as a condition in a preprocessor expression. You can't even check if it's defined.
Longer answer: preprocessing is one of the early translation stages. It happens even before the code is compiled. The value of i is available only during run time. Meaning after the program has been compiled, linked, and then executed. The two stages are as far apart as they can be.
You can't check if an i variable is defined either, since the symbol i is known as a variable only during the compilation stage (again, after the preprocessor has finished its run).
It's true that the preprocessor allows you to conditionally compile code, but you cannot base those conditions on things which are known only at later translation stages.
The reason you're getting a warning is because you redefine DEFINED in the event the macro i is not defined. You need to define this macro entirely within an #if.
#ifndef i
#define DEFINED 0
#else
#define DEFINED 1
#endif
The preprocessor doesn't "know" C. Barring special directives like #error and #pragma, it is much just a text-substitution system.
#if((n)def) only works for macros declared with the preprocessor with the #define keyword; C variables like int i are not macros.
To give you a better idea:
#include <stdio.h>
#define MYFORLOOP for(i = 0; i < 25; i++)
int main()
{
int i;
int data[25];
MYFORLOOP
{
data[i] = i;
}
MYFORLOOP
{
printf("%d\n", data[i]);
}
return 0;
}
The code is then preprocessed before it is actually compiled, so what the compiler actually "sees" is:
// < The contents of stdio.h, including any headers it includes itself >
int main()
{
int i;
int data[25];
for(i = 0; i < 25; i++)
{
data[i] = i;
}
for(i = 0; i < 25; i++)
{
printf("%d\n", data[i]);
}
return 0;
}
The reason #ifdef i would fail is because the variable i is not a #define macro.

Token pasting in c using a variable that increments

I have a set of arrays :msg1[] msg2[] .... msgn[] . And I need to use the values in a while loop. as msgi[]. When I define it as #define MSG(a) msg##a
and put it in a loop and increment i, it expands it to msgi?
You can't do it that way. Instead you could create a new array, that contains pointers to the actual arrays:
int array1[...];
int array2[...];
int *all_arrays[] = { array1, array2 };
build your c code with gcc -E myfile.c and you will see the reason
this called preprocessor code. the prprocessor code is the code generated by your compilator before the compilation. in this code the compilator replace the macros in your origin code with the content of the macro.
your origin code:
for (i=0; i<10; i++) {
for (j=0; j<10; j++)
MSG(i)[j] = 3;
}
preprocessr code generated from the origin code (could be seen with gcc -E):
for (i=0; i<10; i++) {
for (j=0; j<10; j++)
msgi[j] = 3;
}
You can use 2D array instead
int msg[5][5];
It can't be done cause macros are replaced at compilation time not runtime, so it will be replaced once...
what you could do is use 2D array if there are in the same size or use array of arrays if there are in different sizes:
//once in your code you need to do this:
int array0[];
int array1[];
//...
int arrayX[]; //X should be replaced with a real number...
int **arrayOfArrays = new (int*)[X+1];
arrayOfArrays[0] = array0;
arrayOfArrays[1] = array1;
//...
arrayOfArrays[X] = arrayX;
//now you could use it like that anytime in your code:
int i;
for(i = 0; i < X; ++i)
{
//Do whatever you want to do, like:
arrayOfArrays[i][0] = 1234;
}
When I define it as #define MSG(a) msg##a and put it in a loop and
increment i, it expands it to msgi?
No, it will not work that way, because the macro gets expanded before compilation, not after. You'll need a different approach, such as the 2D array suggested by #zakinster.
No, unfortunately it won't. C does not support runtime name lookups. Instead, you should use a two dimensional array of the form:
void** msg;
This will allow the arrays to be of different sizes and types, although you will have to cast to whatever type the array is.

Using preprocessor directives to define generic functions in C

I just came to C from C# and was looking for a way to define generic functions like those in C#. I came across this post but when I tried to compile it I get a bunch of errors ("`n' undeclared here (not in a function)", " syntax error before "array" ", etc.)
Here's my code:
#include<conio.h>
#include<stdlib.h>
#define MAKE_PRINTEACH(TYPE)\
void printeach_##TYPE (TYPE[n] array, int n, void(*f)(TYPE)){\
int i;\
for(i = 0; i < n; i++) {\
f(array[i]);\
}\
}
MAKE_PRINTEACH(int)
MAKE_PRINTEACH(float)
void printInt(int x)
{
printf("got %d\n",x);
}
void printFloat(float x)
{
printf("got %f\n",x);
}
int main()
{
int[5] ia = {34,61,3,6,76};
float[6] fa = {2.4,0.5,55.2,22.0,6.76,3.14159265};
printeach_int(ia, 5, printInt);
printeach_float(fa,6,printFloat);
getch();
}
What am I doing wrong here?
I am using DevC++ if that makes a difference.
A correct version would look like this
#define MAKE_PRINTEACH(TYPE) \
void printeach_##TYPE (size_t n, TYPE array[n], void(*f)(TYPE)){ \
for(size_t i = 0; i < n; i++) { \
f(array[i]); \
} \
}
to summarize what went wrong with your version:
n must be declared before it is used
the array bounds come after the identifier
the semantically correct type for array sizes and things like that is size_t
C since C99 also has local variables for for loops.
You might try this variation:
#define MAKE_PRINTEACH(TYPE)\
void printeach_##TYPE (TYPE * array, int n, void(*f)(TYPE)){\
int i;\
for(i = 0; i < n; i++) {\
f(array[i]);\
}\
}
The TYPE[n] array implies the compiler supports VLA (Variable Length Array) and I do not know whether your compiler does.
For gcc adding the command line option -std=c99 would make the original code compile.
Update:
Corrections applied as by Jens's comment.
The solution I propose is to simply pass a pointer to a variable of the type which the array (as proposed in the OP) would have contained. Doing so, is the way arrays are passed to a function. They are passed by reference.
Also Jens mentions several other warnings/errors. As there are:
1 conio.h is not a standard C include, stdio.h whould be appropriate here
2 Arrays are declared by adding the array's size to the variable name, not to the type. It has to be: int ia[5]not int[5] ia
3 main() returns int, the OP does not return anything.
4 The prototype for getch() is missing. One might like to include curses.h

Resources