Pre-Processor C Macro Syntax - c

I am trying to understand the Pre-Processor syntax. Its really simple line of code that either returns "ON" or "OFF". However I am utterly confused as to what exactly the condition is?
I understand C's conditional statement as follows:
? x : y
If Condition ? return - replace? x : or y either way this line of code is as follows:
#define ONOFF(a) ((a) ? "ON" : "OFF")
I don't understand what condition must be met here? Is the condition that a has to be something other than null?

True and Flase can be more perfectly presented as 1 or 0 . As I can see you have declared
#define ONOFF(a) ((a) ? "ON" : "OFF")
Your condition here is (a), which istrueif the value ofa is non zero and false if ais 0
Which means in your program, if you write
int a=1;
char *str;
str=ONOFF(a);
The substitution which takes place is
int a=1;
char *str;
str=((a) ? "ON" : "OFF")// here a=1
Since here a is 1 and
1 is true and str gets the value ON. If a were 0, then str would get the value OFF

The condition is that a has to evaluate to true. In c, that means that a must be an expression that is non-zero.
If a is a pointer type, NULL is false and any other value is true.
If a is an integer type, 0 is false and any other value is true.
If a is a floating point type, 0 is false and any other value is true.
If a is a struct or a void type you will get a compile error.

To add a bit of context here, the first operand of the conditional operato has to be of scalar type. Now, from chapter §6.2.5, of C11,
Arithmetic types and pointer types are collectively called scalar types.
So, for the conditional expression,
any non-zero value gets evaluated as TRUE and zero (0) is evaluated as FALSE.
(In case of pointers) a NULL is FALSE, any non-NULL is TRUE.

Preprocessor macros do textual substitution, so a is not a variable -- it's just a placeholder for whatever text is in the parentheses when the macro is used.
You could use it for checking pointers are not null like this:
printf("%s\n", ONOFF(ptr));
printf("%s\n", ONOFF(ptr != null)); // This is the same
Or any other type of condition you like:
printf("%s\n", ONOFF(a > b));
printf("%s\n", ONOFF(a && b));
printf("%s\n", ONOFF(a == 1 || c == 4));
printf("%s\n", ONOFF(somefunction() != 0));
printf("%s\n", ONOFF((a == b && c == d) || (a == c && b == d));
printf("%s\n", ONOFF(my_bool_value));

Related

How is 0 used in conditional operator in C?

Conditional operator in C is used like this:
condition ? value_if_true : value_if_false
What does 0 mean when it's used in the value_if_false?
I've seen some people using it like this, for example.
a == b ? i++ : 0
It seems like it does nothing. Does this work like return 0 in other functions?
In C language, ternary is shorter version of if statement and it requires both statements, if_true and if_false. It would be like this (in fact it can have multiple statements for one case, separated with comma):
Short:
condition ? if_true : if_false;
Long:
if (condition) {
if_true;
} else {
if_false;
}
You can also assign the value if you put something infront of condition.
Short:
result = condition ? if_true : if_false;
Long:
if (condition) {
result = if_true;
} else {
result = if_false;
}
Now here is the trick. In C language, writing 0; is a valid statement, so your ternary becomes in longer version same as code below:
if (a == b) {
i++;
} else {
0; /* This is valid C statement */
}
Or if you have assignment too, it would be:
if (a == b) {
result = i++;
} else {
result = 0;
}
You can also do this:
int a;
/* Code here ... */
condition ? a = 5: 0;
That is effectively the same as:
if (condition) {
a = 5;
} else {
/* DO not touch a */
}
The ?: operator is a ternary operator, but it is not called "ternary" as some answers and/or comments here suggest. It just is the arity of the operator, just as + is a binary operator or as & is unary. If it has a name at all, it is called "Conditional Expression"-operator
It is not quite equivalent to if/else, because it is a conditional value (with the consequence, that both expressions must have the same type) in the first place, not a conditional execution. Of course, both types can be cast to make them equal.
In the case of what the OP does, a better option (if if shall not be used) is in my opinion:
a == b && i++;
which resembles a bit more logical what happens. But of course it is a matter of style.
The reason why someone might want to write a == b ? i++ : 0; is that s/he probably wants to have an (Caution! You are now entering an opinion-based area) easier and faster alternative to if (a == b) i++; - although this is of course opinion-based and I personally not share the same opinion.
One thing I can think of as a "blocker" at the if statement is the requirement to write the parentheses () which can be omitted by using the conditional operator instead.
"But why the 0?"
The C syntax requires a third operand for the conditional operator. Else if you would want to compile for example:
a == b ? i++;
you will get an error from the compiler:
"error: expected ':' before ';' token"
Or respectively, doing so:
a == b ? i++ : ;
would raise:
"error: expected expression before ';' token"
So they use 0 as kind of "syntax satisfier" to be able to use the conditional operator as replacement for the if statement. You could use any other numeral value here as well, but 0 is the most readable value, which signifies that it has no use otherwise.
To showcase the use at an example:
#include <stdio.h>
int main (void)
{
int a, b, c = 4;
a = 2;
b = 2;
a == b ? c++ : 0;
printf("%d",c);
return 0;
}
The output for c will be 5, because a == b.
Note that a == b ? i++ : 0 is different when used f.e. inside of an assignment like f.e.:
int c = a == b ? i++ : 0;
Here c is either getting assigned by i or 0, dependent upon a == b is true or not. If a == b is true, c is assigned by i. If a == b is wrong, c is assigned by 0.
Side Notes:
To view it from a technical point, ?= is called the "conditional operator". The conditional operator is one of the group of ternary operators.
If you want to learn more about the conditional operator ?=, look at ISO:IEC 9899:2018 (C18), §6.5.15 - "Conditional operator" for more information.
There's nothing special about 0 one could write
a == b ? i++ : 1
And it would behave the same way.
Only difference is when you assign the expression to say another variable:
int c = a == b ? i++ : 1;
// a == b -> c will be i++
// a != b -> c will be 1
However it's much cleaner to write
if (a == b) i++;
It helps to think of the ternary operator as a shorthand way or writing an if-else statement.
If(a == b){
i++;
}else{
//if assigned, return 0. Else do nothing.
}

What does the exclamation point in if (!strcmp() ... do?

Can someone explain what the exclamation point in the if statement does (i.e. !strmcp)?
string names[] = {"EMMA", "RODRIGO", "BRIAN", "DAVID"};
// Search for EMMA
for (int i = 0; i < 4; i++)
{
if (!strcmp(names[i], "EMMA"))
{
printf("Found\n");
return 0;
}
}
printf("Not found\n");
return 1;
For an if statement, if the expression evaluates to 0, then the block of code following the if statement is not executed. Any other value (positive or negative), will result in executing the code block. The function strcmp uses 0 to say that strings are equal because less than 0 is used to differ from greater than 0.
So in this code, we want printf("Found\n"); to be executed when the strings are equal. Since strcmp results in 0, we need to negate the value so that it becomes 1 which will result in executing that code block.
strcmp() returns 0 if the strings are identical, so you need to negate it, if you use it in an if clause to assert a true statement.
If your clause is if(0), the code inside the condition will not be executed.
For completion, it returns negative if the first different character found is lower in the first string, for instance:
first parameter string: "abca"
second parameter string :abcd"
This will return negative. If it's the other way arround it will return positive.
Also, string is not usually used in C (I refer you to Jonathan Leffler's commment), you can use char*:
char *names[] = {"EMMA", "RODRIGO", "BRIAN", "DAVID"};
Unary operator ! is called the logical NOT operator (cf., for example, this definition at cppreference.com). ! expression returns 1 if expression evaluates to 0, and it returns 0 if expression evaluates to anything else but 0.
So the condition in if (!0) gives 1; this means, the condition is met and the if-block is entered. It has the same meaning as if(0==0)
Consequently, the meaning of
if(!strcmp(names[i], "EMMA"))
in your code is exactly the same as
if(0==strcmp(names[i], "EMMA"))
And you already know when strcmp returns 0...
The exclamation point is the C's boolean negation character.
It means give me the boolean opposite of the value. A boolean is either true or false, which are 1 or 0 in the C Language.
In C, if statements execute their conditional statements if the argument is true.
if (a) means if a is true (i.e. non-zero)
if (!a) means if a is false (i.e. 0)
Therefore:
if (a) is the same as if (a != 0)
if (!a) is the same as if (a == 0)
Sometimes you'll see code that uses two exclamation points in a row "!!"
For example:
int a = !!b;
That ensures a will be ONLY 0 or 1, regardless of what the value of b is.
If b is ANY non-zero value, the ! operator will treat it as though it is true true, which it treats as being the same as 1
So:
!0 == 1
!1 == 0
!52 == 0
!25692 == 0
The second ! does the boolean inversion again, so:
!!0 == 0
!!1 == 1
!!52 == 1
!!25692 == 1
In C any non zero value is considered ad the logical truth, zero i considered as logical false. ! is a logical negation. So !0 (not false) will be the truth and if(!strcmp(str1,str2)) {statements} statements will be executed when str1 will be same as str2

how will this statement execute conditional operation in c?

i have conditional operator's statement and i have no idea how its works.
there are two questions:
Question 1 : what will the following statement do :
quotient=(b==0)?0:(a/b) \\ here a,b,quotient is integer
Question 2 : Can preceding statement be written as follow ?
quotient=(b)?(a/b):0;
NOW MY QUESTION IS :
Question:1 :: we do not know b's value then how can we check this condition(b==0)
Question 2:: what (b) indicate ?
The conditional check in the C ternary conditional operator is an implicit comparison to not-zero.
In other words
quotient = b ? a / b: 0;
is the same as
quotient = b != 0 ? a / b : 0;
or the absurd
quotient = (b != 0) != 0 ? a / b : 0;
This is consistent throughout C, e.g. in an if, a for stopping condition, a while, &&, ||, &c.
If you try
int b = 0;
if (b) {
printf("Hello World");
}
Does not print anything while :
int b = 1;
if (b) {
printf("Hello World");
}
Prints Hello World. Why ? Because 0 is false and 1 is true.
If you do quotient=(b)?(a/b):0; it is interpreted to is b true ? or in other words is b evaluated to 1 (while, again, 1 is true and 0 is false)
C did not originally have a Boolean type. Conditionals are simply int values in C. 0 is false, and any other value is truthy. If the type of b is int, or it can implicitly convert to int, then (b) ? foo : bar does the same thing as (b == 0) ? bar : foo. (However, b==0 will evaluate to 1 or 0, whereas b by itself might have other nonzero values that if or ? consider truthy.)

C assignments in an 'if' statement

I came across this line of code written in C that confuses me coming from a JavaScript background.
short s;
if ((s = data[q]))
return s;
Is this assigning s to data[q], and if it equals true/1, return s?
Yes, an assignment...well assigns...but it's also an expression. Any value not equalling zero will be evaluated as true and zero as false.
it would be the same as
if ((s = data[q]) != 0) return s;
Your code is assigning data[q] to s and then returns s to the if statement. In the case when s is not equal to 0 your code returns s otherwise it goes to the next instruction.
Or better said it would expand to the following:
short s;
s = data[q];
if (s != 0)
return s;
Basically C evaluates expressions. In
s = data[q]
The value of data[q] is the the value of expression here and the condition is evaluated based on that.
The assignment
s <- data[q]
is just a side-effect.
Read this [ article ] on sequence points and side-effects

macro syntax induced error

I the following code and a small little part of it didn't make sense because it was beyond the knowledge I have currently and I was wondering if someone could clear this little problem out for me
stack.h
#ifndef _STACK_H
#define _STACK_H
#include "lis1.h"
typedef List Stack ;
#define stack_init list_init
#define stack_destroy list_destroy
#define stack_size(stack) (stack)->size
#define stack_is_empty(stack) ((stack)->size==0)?1:0
int stack_push(Stack*stack,void*data);
int stack_pop(Stack*stack,void**data);
#endif
please note the #define stack_is_empty(stack) ((stack)->size==0)?1:0 carefully
and on compilation of the following program ,
#include<stdio.h>
#include"stack.h"
static char ams[5] = { 'h', 'e', 'l', 'l', 'o' };
void* data;
Stack stack;
char*ss;
void debug(int a)
{
printf(" debug %d \n", a);
}
int main()
{
stack_init(&stack, NULL);
debug(1);
int i;
for (i = 0; i < 5; i++)
{
stack_push(&stack, (void*) (&ams[i]));
};
debug(2);
while (printf("checker\n") && stack_is_empty(&stack) != 1)
{
printf("->");
printf("[%d ", stack_size(&stack));
stack_pop(&stack, &data);
printf("%c]", *((char*) data));
printf("--\n");
};
return 0;
}
I get this
debug 1 debug 2 checker
->[5 o]-- checker
->[4 l]-- checker
->[3 l]-- checker
->[2 e]-- checker
->[1 h]-- checker
segmentation fault
but if I change #define stack_is_empty(stack) ((stack)->size==0)?1:0
to #define stack_is_empty(stack) (((stack)->size==0)?1:0), there is no seg fault
My Query
My question why did the program work perfectly fine in the former case until the conditional spews a '1'..I seem to understand why the latter works.
In C, a macro is just substituted textually, with no regard to whether it produced the expression that you might expect.
Without the parentheses, your while loop condition expands to:
printf("checker\n")&&((&stack)->size==0)?1:0!=1
Which is interpreted as:
(printf("checker\n") && ((&stack)->size==0)) ? 1 : (0 != 1)
The printf thus becomes part of the condition for this ternary expression, but that's doesn't cause a problem, it returns the number of bytes printed which will be interpreted as true as long as it's non-zero. Then you perform an and with your actual condition, the part that checks the stack size. If the stack size is equal to zero, this returns 1, or true. If the stack size is not equal to zero, this returns the result of (0 != 1), which is always true. So this condition always returns a true value, and the while loop keeps going, even after it's run out of items on the stack.
When you add the parentheses, it's interpreted as you expected:
printf("checker\n") && ((((&stack)->size==0)) ? 1 : 0) != 1)
When writing macros that expand to an expression, you should always have a pair of parentheses around the result, to ensure that it is interpreted as a single expression, rather than operator precedence rules possibly causing the expression to be interpreted differently than you intended.
I should note that there is a lot of redundancy in this statement. You are checking the value of a boolean expression, (&stack)->size==0 to see if it is true, returning 1 if it is and 0 if not. But the == already returned a 1 if it was true and a 0 if not; there's no need for the ternary operator. Then you use != 1 to see if it's false. But how do you get false from a boolean expression? Simply use the not operator, !. You can skip the ternary operator and != 1 comparisons entirely:
#define stack_is_empty(stack) ((stack)->size==0)
while (!stack_is_empty(&stack)) {
// ...
}
Remember that C macros are just text replacement, NOT expression evaluations.
Using your umbra keyed stack_is_empty, your if condition becomes :
While (printf("checker\n") && ((&stack)->size)==0)?1:0!=1) {
Trouble is, the != operator has high precedence, so it effectively becomes :
While (printf("checker\n") && ((&stack)->size)==0)?1: (0!=1) ) {
Since 0 != 1, that while loop is going to keep going beyond the size of your stack.
After the macro substitution
printf("checker\n")&&stack_is_empty(&stack)!=1
becomes
printf("checker\n")&&((&stack)->size==0)?1:0!=1
because the ternary operator ?: has a fairly low precedence, this is equivalent to:
(printf("checker\n") && ((&stack)->size==0)) ? 1: (0 != 1)
Note that printf("checker\n") always returns a true value(because it returns how many characters it prints), so the check (&stack)->size==0) is never evaluated due to shortcut circuit.
Advice: always use enough parenthesis in macro definition.

Resources