Why is this not working with printf() in c - c

I have the following code:
int i=1;
printf((i==1)?" ":" " "hello");
printf(" " "hello");
And I am astonished to see that the first printf only gives a space as output and the second printf outputs a space followed by the string hello. I was expecting output like second one in case of first one. But is there something here I am missing. Please help me with this ...

String literal joining is a lexical feature, which means this:
(i==1) ? " " : " " "hello"
is the same as this:
(i==1) ? " " : " hello"
It should now be pretty obvious why you get the result you get.

i == 1 is true, so the ternary operator evaluates to the first of the two options, " ". Not at all surprising.

C automatically combines two adjacent string literals together.
So your parameter to the second printf: " " "hello" gets joined together to become " hello", which is then printed out normally.
Other answers have explained why your first printf works the way it does, which should be pretty obvious.

Since the condition tested in the ternary operator (i==1) evaluates to true, it returns the expression right after the ?.
The semantics of the ternary operator are something like this:
test_something?if_true:not_true
Your printf statement works as it should.

The source of your confusion is the misunderstanding of when the concatenation is performed. Joining two consecutive string literals is done by the compiler at compile time, not by your program at run time. Therefore there is only one way to parse the first printf: both string literals belong to the "else" branch of the expression. You can test it by setting i to zero and observing the output.

Related

Using empty char in C

I want to use the ternary operator and an empty char '' to spell correctly the word "neightbor" (with or without a "s").
I want to do the following :
printf("There is %d neightbor%c\n", nbNeighbors, (nbNeighbors>1)?'s':'');
obviously, I get an arror error: empty character constant
How can I menage to use this trick to get the right spelling in one printf ?
You could use a non-printable character but they may end up looking like something else.
You'd be better off using strings:
printf("There %s %d neighbor%s\n",
nbNeighbors != 1 ? "are" : "is",
nbNeighbors,
nbNeighbors != 1 ? "s" : ""
);
OP: "I want to use the ternary operator..."
Unless the exercise is to practice the ternary operator, committing to a particular technique blinds one to possibilites.
The example below uses 'branchless' code to deliver a grammatically correct result (ignoring the American spelling of "neighbour".)
printf( "There %s %d neighbor%s\n",
"are\0is" + (nbNeighbors == 1)*4,
nbNeighbors,
"s" + (nbNeighbors == 1) );
I'd never recommend manipulating the truth, but manipulating a truth value can come in handy sometimes.
EDITThe above may be difficult for some to read/understand.
Below is the same thing expressed slightly differently:
printf( "There %s %d neighbor%s\n",
!(nbNeighbors-1)*4 + "are\0is",
nbNeighbors,
!(nbNeighbors-1) + "s" );
Tested, functional and branchless.

How does this quine work?

I just came across this quine question, but no one really went into how it works: C/C++ program that prints its own source code as its output
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);}
What I especially don't understand is the following has the same output even though I changed the ints:
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,5,s,11);}
It still prints the 34s! Can someone walk me through this step by step?
Let's start by formatting the code to span multiple lines. This breaks the fact that it's a quine, but makes it easier to see what's happening:
char* s = "char*s=%c%s%c;main(){printf(s,34,s,34);}";
main() {
printf(s, 34, s, 34);
}
Essentially, this is a declaration of a string s that's a printf-formatted string, followed by a declaration of a function main that invokes printf on four arguments. (This definition of main uses the old-fashioned "implicit int" rule in C where functions are assumed to have int as a return type unless specified otherwise. I believe this is currently deprecated in C and know for certain that this is not legal C++ code.)
So what exactly is this printf call doing? Well, it might help to note that 34 is the ASCII code for a double-quote, so the line
printf(s, 34, s, 34);
is essentially
printf(s, '"', s, '"');
This means "print the string s with arguments ", s, and "." So what's s? It's shown here:
char* s = "char*s=%c%s%c;main(){printf(s,34,s,34);}";
This follows a common self-reference trick. Ignoring the %c%s%c part, this is basically a string representation of the rest of the program. The %c%s%c part occurs at the point where it becomes self-referential.
So what happens if you call printf(s, '"', s, '"')? This will fill in the placeholder %c%s%c with "char*s=%c%s%c;main(){printf(s,34,s,34);}", which is the string contents of the string s. Combined with the rest of the string s, this therefore proints
char*s="char*s=%c%s%c;main(){printf(s,34,s,34);}";main(){printf(s,34,s,34);";
which is the source code of the program. I think this is kinda neat - the closest English translation of a general Quine program I know is "print this string, the second time in quotes" (try it - see what happens!), and this basically does exactly that.
You were asking why changing the numbers to 5 and 11 didn't change that 34 was being printed. That's correct! The string literal s has 34 hard-coded into it, so changing the 5 and 11 in the call to printf won't change that. What it will do is no longer print the quotation marks around the inside of the string s and instead print non-printing characters.

Writing printf(#"") with multiple line string

Is it possible to write something like this:
printf(#"
-
-
-
-
");
I can do it in C#, but can't in C. It gives me an error in CodeBlocks. Am I allowed to do such ?
Error message: error: stray '#' in program.
No. That syntax doesn't exist in C.
If you want a multiple-line string, write it as multiple double-quoted strings with no other tokens in between them. They will be combined.
printf(
"some string"
"more of the string"
"even more of the string"
);
(You will, of course, need to add a \n at the end of each line if that's what you want.)
No that's not a syntax that C understands, C doesn't have raw literals.
You can use \ as the last character to continue on the next line:
const char *str = "hello\n\
world";
Also, consecutive string literals will be concatenated. So you can do e.g.
const char *str = "Hello\n"
"world\n";
C#'s verbatim strings are not available in C. If you have some characters to escape, like " or \, escape them with '\', there is no there option in this language.
If you want to embed multiple lines in a string literal, you can either insert \n at the appropriate location in your string, or escape the return character as well:
printf("Here's\
a multiline\
string litteral");
Line continuation with \ at the end of the line.
printf("\
\
-\
-\
-\
-\
");
String literals in C may not contain newlines. You have two workarounds:
Use implicit string concatenation (done by the compiler).
printf("The quick brown"
" fox jumps over"
" the sleazy dog.");
Escape the newline by placing a backslash in front of it.
printf("The quick brown\
fox jumps over\
the sleazy dog.");
Personally, I prefer the first form since the second looks ugly (my opinion) and forces you to ruin your code indentation.
In either case, the string will simply not contain the newlines. So if you really meant for them to be there, you'll have to add them via \n.

Using macros in printf with a number sign

I'm a bit confused about an explanation concerning macros in K&R 2nd Ed, p.90. Here is the paragraph:
Formal parameters are not replaced within quoted strings. If, however, a parameter name is preceded by a # in the replacement text, the combination will be expanded into a quoted string with the parameter replaced by the actual argument.
I'm not sure what that second sentence is saying. It goes on to explain a use for this with a "debugging print macro".
This can be combined with a string concatenation to make, for example, a debugging print macro:
#define dprint(expr) printf(#expr " = %g\n", expr);
Edit:
All the input was useful. Thank you guys.
If you define macro like this:
#define MAKE_STRING(X) #X
Then, you can do something like this:
puts(MAKE_STRING(a == b));
Which will expand into:
puts("a == b");
In the dprint() example, it is printing out a string form of the expression, as well as the expression value.
dprint(sin(x)/2);
Will expand into:
printf("sin(x)/2" " = %g\n", sin(x)/2);
String literal concatenation will treat the first parameter as a single string literal.
It is just a neat feature where you can convert a macro parameter into a string literal which mainly is useful for debugging purposes. So
dprint(x + y);
is expanded by the C preprocessor to this
printf("x + y = %g\n", x + y);
Notice how the value of the parameter expr appears both inside the string literal and also in the code generated by the macro. For this to happen you need to prefix expr with # to create a string literal.
One thing worth pointing out is that adjacent string literals are combined into a single string literal, e.g. "x + y" " = %g\n" are combined into "x + y = %g\n".
#expr is expanded into "expr". Two string literals next to each other are automatically concatenated. We can see that invoking gcc -E for dprint(test) will give the following output:
("test" " = %g\n");
This site may help. It describes how stringification can be implemented.

Ternary operator inside printf

After reading this I started thinking that I have learned a loot about printf(). Suddenly I found following code snippet from this book:
int main()
{
char str[]="Hello";
int i=5,j=10;
printf(i>j?"%50s":"%s",str); //unable to understand this
return 0;
}
Surprisingly above code is running without errors and it prints Hello.
As per my knowledge following is syntax of printf():
int printf(const char *format,argument_list);
So according to this syntax, printf() should start with format string. But as you can see in above code printf() is starting with i>j.
Does it mean I am wrong in interpreting syntax of printf()?
Does placing ternary operator inside printf() is a special case?
EDIT
I know about ternary operator I am asking about first argument of printf() which should be const char* which I seem not in my example.
The conditional operator:
i>j?"%50s":"%s"
is an expression and it has to be evaluated before the function call itself can be evaluated. We can see this by going to the draft C99 standard section 6.5.2.2 Function calls which says:
An argument may be an expression of any object type. In preparing for
the call to a function, the arguments are evaluated, and each
parameter is assigned the value of the corresponding argument.81)
So what is the result of the evaluation of the conditional operator? If we go to section 6.5.15 Conditional operator it says (emphasis mine):
The first operand is evaluated; there is a sequence point after its
evaluation. The second operand is evaluated only if the first compares
unequal to 0; the third operand is evaluated only if the first
compares equal to 0; the result is the value of the second or third
operand (whichever is evaluated), converted to the type described
below.95
so in either case the result is a string literal which will decay to pointer to char which satisfies the requirement for the first argument to printf.
This code is normal and is not any special case. The requirement for printf is that the first argument should be of the type const char*, but it does not necessarily mean that it needs to be a string literal like "%s". All it means that you need to pass as the first argument an expression of the type const char*. And i>j?"%50s":"%s" fulfils this requirement.
I think you well understood the printf syntax but i think you are missing something about C syntax.
It exist a form of "compact IF like" statement formatted like that : ( condition ? true : false )
For example you can do :
int a=5;
int b=(a==5 ? 128 : 256);
int c=(a!=5 ? 8 : 9);
In this case, b=128 and c=9.
An other example :
int flag=1;
printf("The value is: %s", (flag!=0 ? "true" : "false) );
In this case you can see : The value is true
On your example :
printf(i>j?"%50s":"%s",str);
if i is upper than j you use "%50s" format and, if i is lower you use "%s" format
It can be view like :
if (i>j)
printf("%50s",str);
else
printf("%s",str);
You can see the advantage of compact test.
It is a ternary operator and in this the condition i>j is false so %s will be passed as parameter to printf which will print the value of character array which is hello.
Does it mean I am wrong in interpreting syntax of printf()?
No you are not interpreting it wrong.
Does placing ternary operator inside printf() is a special case?
In C, you can say that its an expression instead of a statement
Your code is equivalent to:
if (i > j)
printf("%50s", str);
else
printf("%s", str);
The ternary operator is simply an inline if that's used as an expression (while a regular if is used to create a block). Your line is equal to this:
if (i > j)
printf("%50s", str);
else
printf("%s", str);
if(i>j)
printf("%50s",str);
else
printf("%s",str);
Therefore, Hello gets printed in both situations
Q: Does it mean I am wrong in interpreting syntax of printf()?
A: No, just need to expand what is allowable.
Q: Does placing ternary operator inside printf() is a special case?
A: No ?: is not special, but sometimes confusing at first glance.
The format supplied to printf() does not need to be a literal. It may be any string variable.
int main() {
char str[]="Hello";
char *format;
int i,j;
i = 5; j = 10;
format = i > j ? "%50s" : "%s";
printf(format, str);
i = 10; j = 5;
format = i > j ? "%50s" : "%s";
printf(format, str);
return 0;
}
There is a statement of the form: condition?consequent:alternative.
The condition is checked, and if it's true you'll get the consequent. otherwise you'll get the alternative.
For example:
5>3 ? 10 : 5
5>3 is true, so you'll get 10.

Resources