Call #define multiple times based on a specific value - c

If you call something like this in C:
#include <stdio.h>
#define REPS ,a
...
int a = 1;
printf("%d" REPS);
It will work, but is it possible to call the REPS macro multiple times based on an unknown value, like for example, that I want to have five inputs in a scanf, yet I want my code to automate it (for example, if #define REPS ,a[i] then: ... ,a[1] ,a[2])?

It will work, but is it possible to call the REPS multiple times based in an unknown value
No. #define creates a preprocessor macro that you can use in your code, but when the compiler compiles your code, the actual value is substituted for the macro. If you have:
#define FOO 7
for example, then every occurrence of FOO in your code is replaced by 7 before the code is compiled; by the time the compiler sees your code, there's no #define and no FOO, only 7 wherever FOO was. Although there are some other preprocessor commands (e.g. #if) that can control whether a given #define is evaluated at all, there are no other preprocessor control structures (loops etc.).
I want to have five inputs in a scanf, yet I want my code to automate it (for example, if #define REPS ,a[i] then: ... ,a[1] ,a[2])?
You can certainly automate something like that; it's just that the preprocessor isn't the right tool for the job. Consider:
int reps = 5
//...
for (int i = 0; i < reps; i++) {
scanf(" %d", &a[i]);
}

REPS is evaluated at compile time, so it cannot depend on run-time values in this case a. There are hacks but in general you cannot do compile loops with macros.
I suggest you write a function along these lines instead:
#include <stdio.h>
void print_int_array(size_t n, int a[n]) {
for(int i = 0; i < n; i++)
printf("%d%s", a[i], i + 1 < n ? ", " : "\n");
}
int main() {
print_int_array(0, (int []) {});
print_int_array(1, (int []) {1});
print_int_array(2, (int []) {1, 2});
}

Related

Non-deterministic output of simple C program

This is an unfinished program I'm writing to learn C (only checks multiples of 2 currently...)
Ultimately, I want this to be an implementation of the Sieve of Eratosthenes (prime numbers)
The problem I'm having is that the output is non-deterministic: sometimes the output includes 11, other times it does not - This happens for a handful of numbers. I have experimented by changing a few things, such as actually initializing the array of booleans to false.
Any ideas why this might be happening?
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main(int argc, char *argv[]) {
int n = atoi(argv[1]);
int initialPrimeIterator = 2;
_Bool compositePrimeNumbers[n];
printf("Prime Numbers from 2 -> %d\n", n);
for (int i = initialPrimeIterator; i < n; i += initialPrimeIterator) {
compositePrimeNumbers[i-1] = true;
}
printf("Done...\n");
printf("Printing prime numbers from 2-> %d\n", n);
for (int i = 2; i < n; i++) {
if (!compositePrimeNumbers[i]){
printf("%d\n", i + 1);
}
}
return 0;
}
edit: haha. Just realized I have an array named 'compositePrime...' Should just be 'compositeNumbers'
Since I understand you are aiming at completing the program when overcoming this hurdle, I will not post a completed program, but only point out issues in your current version:
As it has been noted, the array compositePrimeNumbers is uninitialized. Since it must be initialized with all values false which is represented by 0, the quickest way is this:
memset(compositePrimeNumbers, 0, sizeof(compositePrimeNumbers));
You should not mark the current initialPrimeIterator as a composite number, hence the for-loop should start with the next multiple. Also, n must be included:
for (int i = 2 * initialPrimeIterator; i <= n; i += initialPrimeIterator) {
(actually, this can be optimized by replacing 2 * initialPrimeIterator with initialPrimeIterator * initialPrimeIterator).
With these changes, I believe you are well on the way to complete the program.
In C, a local array is not initialized, probably for performance reasons.
One way to fix this is to loop over it to set each element to false.

Defining equations with a constant

I am trying to define a constant that would have the following in it
ch[co].gold < 10000*100
how can I make it, something like
define x = ch[co].gold < 10000*100;
so that every time I write
if (x) {say(cn,"You need 10 000 gold coins");}
Or that is not possible?
Function:
int x(int val) {
return (val < 10000 * 100);
}
Usage
// ...
if (x(ch[co].gold)) {
printf("You need 10 000 gold coins.\n");
}
// ...
Well, here is my solution
struct s {
int gold;
};
const int co = 2;
struct s ch[] = {112,2321,3234};
#define x() ch[co].gold < 10000*100
int main(){
if (x()) {
}
return 0;
}
Is this what you are expecting?
#define x (ch[co].gold < 10000*100)
Add this line of code before the place you use it, usually it's just below the #includes.
Conventionally, we use capital letters with clearer meanings instead of x.
#define is simply text substition performed by the preprocessor.
To do what you say you want use the following #define:
#define x ch[co].gold < 10000*100
Every time the preprocessor encounters the symbol x it will replace it with ch[co].gold < 10000*100.
I think that what you really want is to make it a proper function as suggested by pmg. It is a wiser choice.

Issues by the redefinition of a macro in C

I want to change the value of a macro during the run of the program, for that I've wrote this example :
#include <stdio.h>
#define MAX (65535 *0.5)
int main ( ){
float amp = 0.0;
float temp = 0.0 ;
temp = MAX ;
char c;
while (1){
printf(" MAX value %.2d.%.3d \n ", (short)temp,(short)(temp*1000));
scanf("%c",&c);
if( c =='x') {
#undef MAX
#define MAX (65535 +amp);
amp+= 0.1;
temp = MAX;
}
}
return 0 ; }
I've got two problems :
1. the printf doessn't show the values as hoped, for instand 19.211, it always
-32768.-32768
2. I don't see any change of the value of the macro.
any idea what I'm doing wrong here ?
You can only define macros at compile time. The c preprocessor replaces every occurrance of a macro before actual compilation happens, with gcc you can see what code was generated after preprocessing by using the -E switch, if you try it experimenting with different macros, you may get to understand the preprocessor a little better, read the link to understand more.
This
if( c =='x') {
#undef MAX
#define MAX (65535 +amp);
amp+= 0.1;
temp = MAX;
}
does not do what you think.
If you execute the preprocessor on the source code, then what will actually happen is that the snippet above will be compiled as
if( c =='x') {
amp+= 0.1;
temp = MAX;
}
so as you can see, it doesn't do what you think.
Also, this is not related to the macro redefinition issue, but your code has a bug that can make it enter an infinite loop, this
scanf("%c",&c);
will keep scanning the '\n' that is left in the stdin after pressing Enter/Return, so you need to explicitly ignore that character by adding a white space before the specifier like this
scanf(" %c", &c);
/* ^ white space goes here */
Note: another answer has suggested that you are using the incorrect data type and suggested a solution, you should take a look at it, since in fact it seems your program has an integer overflow issue.
Let's run your file through the C preprocessor (CPP) manually. The result is
int main ( ) {
float amp = 0.0;
float temp = 0.0 ;
temp = (65535 *0.5) ;
char c;
while (1) {
printf(" MAX value %.2d.%.3d \n ", (short)temp,(short)(temp*1000));
scanf("%c",&c);
if( c =='x') {
amp+= 0.1;
temp = (65535 +amp);;
}
}
return 0 ;
}
Macros are evaluated before the compiler even sees your source code. You cannot change the value of a macro based on a decision taken at runtime.
Why not instead use a variable float max = ... and change that one's value depending on user input?
Macros are resolved during compilation, so during program execution there is no such thing like MAX - each occurence was already replaced by its value (65535).
However, if you need to define local constant (local in terms of translation unit), why not use static variable?
static unsigned int MAX = 65535;
And then:
if (c == 'x')
{
MAX = 65535 + amp;
//...
}
You are using too short data type and printing the fractional part incorrectly. Consider doing this:
double i;
printf(" MAX value %.2d.%.3d \n ", (int)temp,(int)(modf(temp,&i)*1000));
...instead of this:
printf(" MAX value %.2d.%.3d \n ", (short)temp,(short)(temp*1000));
Be sure to #include <math.h> if using modf.
Your redefinition of the MAX macro looks strange to me, though. Macros are defined at compile time, not at run time, so most of the time you don't want to redefine macros.
Note also that
scanf("%c",&c);
will read the newline as a separate character, so you want to do instead:
scanf(" %c",&c);
...to consume whitespace. Do consider checking also for the EOF (end-of-file) condition; currently you don't do that.

Macro function to behave like for loop

Consider the following code i managed to write:
#include <stdio.h>
#define FOR(A, B, C) for(A; B; C++)
int main()
{
FOR(i=0, i<10, i)
printf("%i", i);
return 1;
}
The output is:
0123456789
If i do FOR(i=5, i<10, i)
then respectively the output is 56789
My questions are is that legal? Will it cause any errors in different cases? Does it works exactly like a for loop?
Yes it's a "legal" macro, but no, it does not work like a real for loop.
Your macro won't handle this:
int a, b;
for(a = 0, b = 4711; a < b; ++a);
for instance, since you can't distinguish the , used to build a longer initializing expression to the one used to separate the expressions that make up the parts:
FOR(a = 0, b = 0, a < b, ++a);
will break, since it looks like a call with 4 arguments instead of 3.
A macro is just copied everywhere the preprocessor sees you using the macro keyword. It just copies the text, nothing more.
To elaborate on that a bit more, consider this example:
#define MY_MACRO a
int MY_MACRO = 5;
When the preprocessor comes along it will take the above and change it to:
int a = 5;
and then the compiler will come along and compile it like normal C/C++ code.
When you add arguments to your macro, they are just substituted in place within your macro. This can be a problem, consider the following two macros:
#define BAD_MACRO(a, b) a*b
#define GOOD_MACRO(a, b) (a)*(b)
They look almost the same, but consider the following:
int k = BAD_MACRO(2, 3); // k = 2*3 = 6
int j = GOOD_MACRO(2, 3); // j = 2*3 = 6
int m = BAD_MACRO(2+1, 3); // m = 2+1*3 = 5
int n = GOOD_MACRO(2+1, 3); // n = (2+1)*3 = 9
Although note that neither of these macros are good or bad, they just don't have the same behaviour as a typical function.

How to make a variable value passage for preprocessor?

Here I know that the following code simply copies the character i rather than its value to the preprocessor statement (which makes a error for undefined symbol i in compile-time).
What I want is:
Is their a way such that the compiler treats, i as a variable with some value rather than a character ?
#include <stdio.h>
#define PRINT(x) printf("%d \n", y ## x)
int main(void) {
int y1=0 , y2=1 , y3=4;
for(int i=1; i <= 3; ++i) {
PRINT(i);
}
return 1;
}
About the pre-processor
First of all, I think there's a need to clarify how the preprocessor works: it pre-processes the input files, which means it runs before the compiler. Unfortunatly, for historical reasons, it doesn't know anything about C or C++, doesn't parse anything, and just does very simple textual operations on words and parenthesis. Just to illustrate my point:
#define this __FILE__
#define file -- Hell no!
#define fine(a, b) fine: a ## _ ## b
Ok, so this is not a valid C or C++ file
But the preprocessor will run just fine(go, try!)
Run this with a pre-processor, for example gcc -x c -E -P test.txt and you'll get:
Ok, so "test.txt" is not a valid C or C++ -- Hell no!
But the preprocessor will run just fine: go_try!
So, obviously, when the preprocessor sees PRINT(i) in your code, it replaces it with printf("%d \n", yi) without thinking much about it. And it has absolutely no idea i is a variable, don't even think about evaluating it's value.
Solutions
Basically, what you want is print a bunch of numbers.
You could simply do
printf("0\n1\n4\n");
But this lacks makes changing numbers cumbersome,
so let's go with
printf("%d\n%d\n%d\n", 0, 1, 4);
Which makes it easy to change a number, but not to add/remove one.
Ok so how about:
printf("%d\n", 0);
printf("%d\n", 1);
printf("%d\n", 4);
Yeah, you can change/add/remove numbers easily but as any sane programmer you hate repetition. So, we need some kind of loop.
By far the simplest and most straightforward way to iterate in C is at runtime, using an array:
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/sizeof(int); ++i) {
printf("%d\n", y[i]);
}
If you want, you can hide the printf using a function:
inline void print_int(int* y, int i) { print_int(y[i]); }
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/4; ++i) print_int(y, i);
And going further with functions:
inline void print_int(int x) { printf("%d\n", x); }
inline void print_int(int* y, int i) { print_int(y[i]); }
inline void print_ints(int * y, int n)
{
for(int i = 0; i < n; ++i)
print_int(y, i);
}
template<int n> // C++
inline void print_ints(const int[n] & y) { print_ints(&y[0], n); }
int [] y = { 0, 1, 4 };
print_ints(y); // C++
// or in C:
print_ints(y, sizeof(y)/sizeof(int));
Now, what if you absolutely want the generated code to look like solution 3. ? This means you need the iteration to happen at compile-time. Tricky!
That's where the preprocessor can come into play. There are (hacky) ways to make it do this kind of things. I strongly recommend not implementing this yourself (except to play), but use the Boost.preprocessor library instead:
#define PRINTER(R,D, NUMBER) printf("%d\n", NUMBER);
#define NUMBERS (0, 1, 4)
BOOST_PP_LIST_FOR_EACH(PRINTER, _, BOOST_PP_TUPLE_TO_LIST(NUMBERS))
// will expand to printf("%d\n", 0); printf("%d\n", 1); printf("%d\n", 4);
Under standard C, this is not possible; during preprocessing, the compiler simply sees the identifier i as simply that - an identifier. It does not know that i is of type int, or that it's even a variable in the first place.
The easiest way to achieve what's intended is to use an array, like so:
int i;
int y[] = { 0, 1, 4 };
for (i = 0; i < 3; i++) // NOTE: arrays in C start at index 0, not 1
{
printf("%d \n", y[i]);
}
Also note that I got rid of the macro, as you want to use the value of a runtime variable i to select another runtime variable.

Resources