Check if int is defined as macro. C - 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.

Related

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.

A homework is about use macro

This questions is about my homework.
This topic is need to use like:
#define GENERIC_MAX(type)\
type type##_max(type x, type y)\
{\
return x > y ? x : y;\
}
The content of the question is to make this code run normally:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
The result of the operation is like this:
i=5.2000
j=3
And this code is my current progress, but there are have problems:
#include <stdio.h>
#define printname(n) printf(#n);
#define GenerateShowValueFunc(type)\
type showValue_##type(type x)\
{\
printname(x);\
printf("=%d\n", x);\
return 0;\
}
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
I don’t know how to make the output change with the type, and I don’t know how to display the name of the variable. OAO
This original task description:
Please refer to ShowValue.c below:
#include <stdio.h>
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Through [GenerateShowValueFunc(double)] and [GenerateShowValueFunc(int)] these two lines macro call, can help us to generated as [showValue_double( double )] and [showValue_int( int )] function, And in main() function called. The execution result of this program is as follows:
i=5.2000
j=3
Please insert the code that defines GenerateShowValueFunc macro into the appropriate place in the ShowValue.c program, so that this program can compile and run smoothly.
A quick & dirty solution would be:
type showValue_##type(type x)\
{\
const char* double_fmt = "=%f\n";\
const char* int_fmt = "=%d\n";\
printname(x);\
printf(type##_fmt, x);\
return 0;\
}
The compiler will optimize out the variable that isn't used, so it won't affect performance. But it might yield warnings "variable not used". You can add null statements like (void)double_fmt; to silence it.
Anyway, this is all very brittle and bug-prone, it was never recommended practice to write macros like these. And it is not how you do generic programming in modern C. You can teach your teacher how, by showing them the following example:
#include <stdio.h>
void double_show (double d)
{
printf("%f\n", d);
}
void int_show (int i)
{
printf("%d\n", i);
}
#define show(x) _Generic((x),\
double: double_show, \
int: int_show) (x) // the x here is the parameter passed to the function
int main()
{
double i = 5.2;
int j = 3;
show(i);
show(j);
}
This uses the modern C11/C17 standard _Generic keyword, which can check for types at compile-time. The macro picks the appropriate function to call and it is type safe. The caller doesn't need to worry which "show" function to call nor that they pass the correct type.
Without changing the shown C-code (i.e. only doing macros), which I consider a requirement, the following code has the required output:
#include <stdio.h>
#define showValue_double(input) \
showValueFunc_double(#input"=%.4f\n" , input)
#define showValue_int(input) \
showValueFunc_int(#input"=%d\n" , input)
#define GenerateShowValueFunc(type) \
void showValueFunc_##type(const char format[], type input)\
{\
printf(format, input); \
}
/* ... macro magic above; */
/* unchangeable code below ... */
GenerateShowValueFunc(double)
GenerateShowValueFunc(int)
int main()
{
double i = 5.2;
int j = 3;
showValue_double(i);
showValue_int(j);
}
Output:
i=5.2000
j=3
Note that I created something of a lookup-table for type-specific format specifiers. I.e. for each type to be supported you need to add a macro #define showValue_ .... This is also needed to get the name of the variable into the output.
This uses the fact that two "strings" are concatenated by C compilers, i.e. "A""B" is the same as "AB". Where "A" is the result of #input.
The rest, i.e. the required function definition is very similar to the teacher-provided example, using the ## operator.
Note, this is if the variable name has to correctly be mentioned in the output.
With out the i = things would be easier and would more elegantly use the generated functions WITHOUT having the called showValue_double(i); be explicit macros. I.e. the functions generated are 1:1 what is called from main(). I think that might be what is really asked. Let me know if you want that version.

Can someone explain variables declaration in C

I'm new to programming, I'm taking this online programming course CS50. So I had an assignment to write a program in C, where user inputs some words (no matter how much space there is before or after words) and we have to print first initials of each word. So I made this program:
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main(void)
{
int n;
int i;
string name = get_string();
if(name != NULL)
{
if (name[0] != ' ')
{
printf("%c", toupper(name[0]));
}
for(i = 0, n = strlen(name); i < n; i++)
{
if(name[i] ==' ' && isalpha(name[i+1]))
{
printf("%c", toupper(name[i+1]));
}
}printf("\n");
}
}
But it was correctly done only after I declared variables int n; int i;
Before that, I could not even compile program. Why? At first I declared int i
in for loop, but program didn`t even compiled. And just out of luck I tried to declare outside loop and its correct. I dont understand this point. Can someone explain? :)
All variables and functions must be declared before they may be used. The variable i must be declared before it can be used as an index in the for loop.
Under the 1989/1990 standard and earlier K&R language versions, all declarations had to come before any executable statements in a block:
void foo( void )
{
/**
* The variable i is used to control a for loop later on in the function,
* but it must be declared before any executable statements.
*/
int i;
/**
* Some amount of code here
*/
for( i = 0; i < some_value; i++ ) // K&R and C90 do not allow declarations within the loop control expression
{
/**
* The variable j is used only within the body of the for loop.
* Like i, it must be declared before any executable statements
* within the loop body.
*/
int j;
/**
* Some amount of code here
*/
j = some_result();
/**
* More code here
*/
printf( "j = %d\n", j );
}
}
As of the 1999 standard, declarations may be mixed with other statements, and they may appear as part of the initial expression of a for loop:
void foo( void )
{
/**
* Some amount of code here
*/
for ( int i = 0; i < some_value; i++ ) // C99 and later allow variable declarations within loop control expression
{
/**
* Some code here
*/
int j = some_result(); // declare j when you need it
/**
* More code here
*/
printf( "j = %d\n", j );
}
}
The chief difference between the two snippets above is that in the first case, i is visible over the body of the entire function, whereas in the second snippet, it's only visible within the body of the for loop. If you need i to be visible to any code following the for loop, then you need to declare it outside the loop control expression:
int i;
for ( i = 0; i < some_value; i++ )
{
...
}
...
do_something_with( i );
Again, i must be declared before it can be used in the loop control expression; it's just in the second case, that declaration is part of the loop control expression.
EDIT
I don't know what development environment or compiler you are using. You might want to see if you can specify which version of the language you want to compile against (for example, in gcc, you'd specify -ansi or -std=c90 for the 1989/1990 version and -std=c99 for the 1999 version).
First of all - welcome to C language! I think C is a great language to start with.
Variables declaration - in C, we are allowed to declare on a local variable only at the beginning of a scope - at the very beginning of a function, loop, if statement, etc.
For example:
We can't run this:
for(int i = 0; i<4: ++i) { printf("%d",i); }
The declaration is in the for statement - not at the beginning of the scope. In C++, this code will work.
However, we can do the following:
int foo()
{
int i;
for(i=0;i<4; i++) { ...}
}
Remark: local variables and parameters passed are allocated on stack. When we declare on a local variable we push the variable into the stack and we get to the end of the scope - the variable pops out.

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

How do I #define an array in 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);
}

Resources