Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
#include<stdio.h>
void main()
{
if(0xA)
if(052)
if('\xeb')
if('\012') //what do the above 3 statements mean?
printf("Hello World!")
else;
else;
else;
else;
}
Output:
Hello World!
so here, what is the meaning of 052, \xeb and \012?
And what is the significance of the multiple else statements?
From the C Standard (6.8.4.1 The if statement)
2 In both forms, the first substatement is executed if the
expression compares unequal to 0. In the else form, the second
substatement is executed if the expression compares equal to 0. If the
first substatement is reached via a label, the second substatement is
not executed.
So as each expression in the if statements
if(0xA)
if(052)
if('\xeb')
if('\012')
are unequal to 0 then the enclosed call of the function printf (provided that a semicolon is present)
printf("Hello World!");
is executed.
So the if statements do not make much sense.
0xA is a hexadecimal integer constant equal to decimal 10
052 is octal integer constant equal to decimal 42
'\xeb' is a character constant specified as a hexadecimal escape sequence
'\012' is a character constant specified as an octal escape sequence
Take into account that according to the C Standard the function main without parameters shall be declared like
int main( void )
Thus as each expression of the if statements is not equal to 0 then the program is in fact equivalent to the following program
#include<stdio.h>
int main( void )
{
printf("Hello World!");
}
This is a trick question. Presumably someone thought you could learn something from it. Presumably this person also thinks that a good way to teach a child to ride a bicycle is to flatten the bicycle's tires, and put large boulders in the way, and randomly give the child a rough shove to the side, because it "builds character", and if you can learn to ride a bicycle in spite of those obstacles, you will eventually be a really good bike rider. But I digress.
Anyway, here's an explanation of what's going on in that code.
0xA is a hexadecimal constant. It has the value 0A16, or 10 (base 10).
052 is an octal constant. It has the value 528, or 42 (base 10).
'\xeb' is a hexadecimal character constant. It is a character with the value EB16, or 235 (base 10) (which in ISO-8859-1 or Unicode ends up being an e with two dots over it, Γ«).
'\012' is an ordinary, octal character constant. It is a character with the value 128, or 10 (base 10) (which in ASCII ends up being a newline character, '\n').
When you say
if( expr )
in C, the expression is considered "true" if it is nonzero, or "false" if it is zero. Needless to say, all four of those constants are nonzero.
The full syntax of an if statement in C is either
if( expr )
statement-or-block
or
if( expr )
statement-or-block
else
statement-or-block
where statement-or-block is either a single statement, or a "block" (sequence) of multiple statements enclodes in braces { }.
A little-used piece of syntax in C is the "empty statement". If you have nothing, followed by a semicolon, that's an empty statement, and it does... nothing.
It is considered mandatory in polite circles to indent your code to portray its structure. So the normal way of presenting this code would be:
#include <stdio.h>
int main()
{
if(0xA)
if(052)
if('\xeb')
if('\012')
printf("Hello World!")
else
;
else
;
else
;
else
;
}
And, again, all four expressions evaluate immediately to "true". So, in English, this code says "If true, then if true, then if true, then if true, then print 'Hello world!', else do nothing, else do nothing, else do nothing, else do nothing."
Phrased that way it sounds pretty stupid, I know. And in fact, it's just as stupid in C as it is in English.
P.S. Besides the bizarre and unnecessary conditionals, another problem with the code as posted, which I have quietly corrected, is that it declared main as void, which is something else that's not done in polite circles, and throws further doubt on the validity of the book this code came from.
The code you posted is equivalent to
#include<stdio.h>
int main( void ) // void main() is not a standard signature
{
if(0xA)
{
if(052)
{
if('\xeb')
{
if('\012')
{
printf("Hello World!")
}
else
{
}
}
else
{
}
}
else
{
}
}
else
{
}
}
Curly braces can be omitted if there is only a single statement within them:
if ( a )
{
do_something();
}
can be written as
if ( a )
do_something();
although I and others recommend against doing this except in specific cases.
An if statement itself counts as a single statement, so it's possible to write
if ( a )
{
if ( b )
do_something();
}
as
if ( a )
if ( b )
do_something();
And, of course, the compiler doesn't care about indentation, so
if ( a )
if ( b )
do_something();
means the same thing - however, as you've discovered, code written this way is a little hard to understand.
The test condition of an if, while, or for may be any scalar type (integer, floating-point, or pointer value). C didn't originally have a distinct Boolean type, so the rule is any non-zero value in a Boolean context evaluates to "true", while zero evaluates to "false".
Each of 0xA, 052, '\xeb', and '\012' is a scalar expression with a non-zero value (0xA and 052 are integer literals in hexadecimal and octal format, respectively, while '\xeb' and '\012' are escape sequences representing character values in hex and octal format), so the bodies of all the if statements are executed.
You have four nested if statements, and only the innermost one is doing anything interesting. The else clauses are empty and can be omitted entirely:
#include<stdio.h>
int main( void )
{
if(0xA)
{
if(052)
{
if('\xeb')
{
if('\012')
{
printf("Hello World!")
}
}
}
}
And, as I said above, the curly braces may be omitted as well:
#include<stdio.h>
int main( void )
{
if(0xA)
if(052)
if('\xeb')
if('\012')
printf("Hello World!")
}
All of which reduces to
int main( void )
{
printf("Hello World!")
}
A reasonably smart compiler won't bother generating the machine code for the if statements at all, and should generate machine code as though the program had been written as above.
Related
Part of my C code 1:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
[snip!!]
#define FALSE 0
#define TRUE 1
[snip!!]
typedef int Boolean;
[snip!!]
typedef struct {
int identification ;
char name[NAMESIZE] ;
char subject[SUBJECTSIZE] ;
int grade ;
} RECORD ;
typedef struct {
char type ;
RECORD student ;
} TRANSACTION ;
typedef struct {
char occupied ;
RECORD student ;
} MASTER ;
char *prog ;
Boolean get_transaction_record(FILE *fp, TRANSACTION *transaction);
[snip!!]
void main(int argc, char *argv[])
{
FILE *fpmas,*fptrans ;
int current_key ,
relative_record_number ;
Boolean allocated;
TRANSACTION transaction;
MASTER master ;
clrscr();
prog = argv[0];
[snip!!]
else
{
get_transaction_record(fptrans, &transaction) ;
current_key = choose_next_key(transaction.student.identification);
while(current_key != TRAILER)
{
relative_record_number = do_initial_status(
current_key,&allocated, fpmas,&master);
while(current_key == transaction.student.identification)
{
apply_transaction (&allocated, &transaction,&master) ;
get_transaction_record(fptrans, &transaction);
}
do_final_status (fpmas, relative_record_number, allocated, &master);
current_key = choose_next_key(transaction.student.identification);
} //end of while
fcloseall();
} //end of else
}
Part of code 2:
Boolean get_transaction_record(FILE *fp, TRANSACTION *transaction)
{
if (fscanf (fp, "%4d%c%20s%10s%2d",
&transaction -> student. Identification,
&transaction -> type,
transaction -> student.name,
transaction -> student. Subject,
&transaction -> student. Grade) == 5)
return(TRUE);
return(FALSE);
}
How these return(); work (in the screenshot I attached) ?! I see before Boolean application like this typedef int Boolean; before. But that usage was in accompany with if() . But I do not see any if() in this code!
My main question is, how it works when the return value (TRUE or FALSE), get back to main() function'?! In main(), there is no condition evaluation to take decision about that (TRUE or FALSE) returned value. So what?
Boolean - return
First, your C learning book is largely outdated. C99 (out in 1999) allows #include <stdbool.h> that contain a bool type and true/false defines, use these instead of making your own boolean.
C and many other languages are a bit weird with boolean, if and what is true of false. In C what is 0 is false, everything else is true, hence why TRUE is defined as 1 and FALSE defined as 0 in your book. Note that comparison operators such as ==, &&, ||, ! (not to be confused with binary operators &, |, ~) returns either 1 or 0 depending of the condition.
See this example:
#include <stdio.h>
#include <stdbool.h>
bool return_the_truth(void)
{
return true; // A trivial function that returns true.
}
int main(void) {
if (2)
printf("As you see just \"2\" is true since it's different of zero\n");
if (0)
printf("That line won't be printed\n");
if (4 - 4)
printf("Neither this one since 4-4 is zero\n");
if (true == 1)
printf("true is in fact a one.\n");
if (true == 2)
printf("But merely a integer with value 1 so this line won't print.\n");
// You can invoke a function that returns a boolean and ignore it's return value.
return_the_truth();
// It is never mandatory to use the returned value. This example is absurd but perfectly valid
fopen("delete_me.txt","a"); // <- Don't forget to delete this file afterward.
if (printf("printf() return an int that is the numbers of characters printed.\n"))
printf("Hence again, this line is printed because what in the if() is not zero.");
int boolean_check_result = 42 == 40+2;
if (boolean_check_result)
printf("You can write expressions like this, there boolean_check_result is %d.\n",boolean_check_result);
printf("You can performs math with boolean, there is %d true expressions there, it works because a comparison returns 1 if true, 0 if false and we doing a sum of 1 and zeros (it's brainfuck to understand don't do that or people reviewing your code will hate you).\n",
(4 == 5) + (4 < 5) + (4 != 5) + (4 > 5) + (4 >= 5) // <- The expressions.
);
// These examples below are valid C.
5 + 6; // This sum goes to... nothing
7 == 7; // Same for this boolean, nothing will happen
printf; // Functions are kind of constants variables so that works.
// It's a non-sense, a compiler will output warnings because making computations without using the results is likely a programming error.
printf("But remind you that in the case of a function (returning a boolean or not), there might be side-effects you want and don't care about the returned value such as with this printf().\n");
}
// Did you know that you can use a `void` value ?
// The code below is perfectly valid.
// It's useful for C++ wrappers when you want to exactly mimic the behavior a library in order to catch errors.
void a_function_that_does_nothing(void)
{
}
void you_can_return_a_void(void)
{
return a_function_that_does_nothing(); // Allowed because the function return a void
}
There is tons of valid case where a returned boolean are not used inside a if().
So to answer your original question (that I might forgot while writing this answer hehe...):
how it works when the return value (TRUE or FALSE), get back to main()
function'?!
And ! π₯ π₯ π₯ Nothing happens. The value is just lost, just like with printf() and any other functions. In the book the boolean value was an error indicator since scanf() return the number of inputs read, not 5 mean that the input was incorrect.
Not checking it is fine for learning purposes. In real-world input parsing, first don't use scanf(), then it could introduce a security vulnerability since some variables would not be written and in incorrect state and trigger unwanted behavior later that can be exploited by a malicious hacker to leak sensitive data of thousands of customers and costs millions of USD to a company (I'm barely exaggerating).
So don't be outraged when a boolean or other returned value is not used, memcpy() is a function where it's commonly sane to ignore it's return value. What is important is to understand what you are doing.
If you're still extremely angry about the fact that this boolean wasn't used and could avoid a potential security vulnerability... (I'm joking there, yet) as an exercise you can add error checking and do something useful such as printing an expressive error message telling the user that the input is incorrect and remind they what you are expecting and quit.
I have a homework assignment in which I believe the professor has made a typo, typing if(!(a=10)) instead of if(!(a==10)). However, when asked if this was typo, she told me to "assume that the equations are correct and give your answer." Specifically, the assignment is to describe the behavior of the program:
#include <stdio.h>
int main() {
int a = 100;
while (1) {
if (!(a=10)) {
break;
}
}
return 0;
}
If the offensive code read (!(a==10)) then the program would enter the if loop, reach the break and exit both loops, which makes sense for a beginner-level course in C programming.
However, if, truly, the code is meant to read (!(a=10)) then I don't know what the compiler will interpret that to mean. I do know that the code compiles, and when you run it in UNIX, it just allows you to input whatever you want using the keyboard, like say the number "7", and then you press enter and it moves to a new line, and you can enter "dog", and move to a new line, and on and on and it never exits back to the command line. So (1) how would the compiler interpret (!(a=10))? And (2) why does the program allow you to just continue to input entries forever?
Thanks!
For the first question,
What's the meaning of if( !(a=10) ){break;},
It's equivalent to
a = 10; if(!a) {break;}
For a value of 10 !a will be 0 and it never breaks the while loop.
In this particular example, if you assign if(!(a=0)), then it will exit the loop;
For the second question, there is no code present in your example.
But first question's answer can be extended here as the loop never breaks it keeps on asking the input values.
From the C Standard (6.5.3.3 Unary arithmetic operators ΒΆ5)
5 The result of the logical negation operator ! is 0 if the value of
its operand compares unequal to 0, 1 if the value of its operand
compares equal to 0. The result has type int. The expression !E is
equivalent to (0==E).
So according to the quote the if statement
if (!(a=10)) {
is equivalent to
if ( ( a = 10 ) == 0 ) {
As the value of the assignment sub-expression, a = 10 is equal to 10 that is it is not equal to 0 then the condition of the if statement evaluates to logical false and the sub-statement of the if statement will not get the control and you will have an infinite while loop.
In fact, you can rewrite this while loop
while (1) {
if (!(a=10)) {
break;
}
}
the following way with the same effect
while ( ( a = 10 ) ) {}
or just
while ( ( a = 10 ) );
or more simply:
while ( a != 0 );
because what is important is that within the while loop the variable a does become equal to 0.
while (1) {
if (!(a=10)) {
break;
}
}
as !(a = 10) is always zero (false) it is equivalent of:
while (1) {
}
Note: I know I can do this stuff by using strcmp() but I am just trying the equal to == operator.
Code 1:
#include<stdio.h>
int main()
{
char s1[]="bonaparte",s2[]="bonaparte";
if(s1==s2)
{
printf("True");
}
else
{
printf("Flase");
}
}
Output:
False
Code 2:
#include<stdio.h>
int main()
{
char s[]="bonaparte";
if(s=="bonaparte")
{
printf("True");
}
else
{
printf("Flase");
}
}
Output:
False
Code 3:
#include<stdio.h>
int main()
{
if("bonaparte"=="bonaparte")
{
printf("True");
}
else
{
printf("Flase");
}
}
Output:
True
So, in #1, we compare the base addresses of s1 and s2 and obviously they are going to different, so the output is "False".
In #2, we are comparing the base address of s and the base address of the constant string "bonaparte" and obviously it is again going to be different, so the output is "False".
However, in #3, we are comparing base addresses of one constant string "bonaparte" and another constant string "bonaparte". I think that the string names are same but they will get different locations in memory so, when we are trying to compare their base addresses, they should be different. But output is contradicting to above (what I think).
So what is exactly happening in the 3rd case?
When compiling your third code sample, the compiler is applying what is often called "string pooling" β that is, the compiler spots that two (or more) string literals are the same and, as such constants cannot be changed at runtime, optimizes the code by generating only one instance of the data, so the two literals end up with the same address.
Most compilers do this by default, but you may be able to disable it. For example, in Visual Studio with the MSVC compiler, you can set the /GF- option to disable it. With this set, your code above gives "Flase" (sic) as the output (Reference).
What will be the output for the code snippet given below?
int main()
{
if(0<7<5)
printf("I am printed");
else
printf("I am not printed");
}
I am printed
I am not printed
Compiler error
None
The output will be "I am printed" - reason being the < (less than operator) is left associative. As a result this will be
(0<7)<5
And as it is true - it will evaluate to 1. So the check will be 1<5, which is again true, giving you the desired result.
From standard itself
The expression a<b<c is not interpreted as in ordinary mathematics. As
the syntax indicates, it means (a<b)<c; in other words, if a is less
than b, compare 1 to c; otherwise, compare 0 to c.
The "I am printed" will be printed in this function.
(0<7<5) => (0<7)<5 => 1<5 => true.
main()
{
int a=10,b=30,c=0;
if( c =({a+b;b-a;}))
{
printf("%d",c);
}
}
why the construct ({;}) is legal in C and why it returns the last statement value as the result of the expression ( why it work similar to comma operator)?
It is not legal standard C99, but it is a very useful GCC extension, called statement-exprs (a parenthesized brace compound statement ending by some expression).
IIRC, some other compilers support that extension, e.g. Clang/LLVM
Statement expressions are much more useful when they contain control flow changes and side-effects, like:
c = 2*({while (a>0) a--,b--; a+b;});
However, in your particular case, you could just use the comma operator
if (c=(a+b,b-a))
Since a+b does not have any side effect, I guess that an optimizing compiler could handle that as
if (c=b-a)
GCC provides other useful extensions, notably local labels using __label__ and label as values with computed gotos (very useful in threaded interpreters ...). I don't know exactly why they have not been standardized. I wish that they would.
main()
{
int a=10,b=30,c=0;
if( c =({a+b;b-a;}))
{
printf("%d",c);
}
}
Here,{a+b;b-a;} is one scope.In this you have written 2 statements.This is actually treated as
{
c=a+b;
c=b-a;
}
Initially c value is 40 because of a+b. Again c is modified by b-a. To prove this consider following three cases..
(1).
if(c=({(a=a+b);;}))
{
printf("%d\n",c);
printf("%d\n",a);
}
Here o/p is c=40 and a=40;Because at end of scope (i.e) in last statement is dummy (;).
so,c=a+b is o/p.
(2)
if(c=({(a=a+b);b-a;}))
{
printf("%d\n",c);
printf("%d\n",a);
}
Here o/p is c=-10, a=40. Because last statement is b-a. this value is assigned to c.
(3) main()
{
int a=10,b=30,c=0;
if(c=({(a=a+b);0;}))
{
printf("%d\n",c);
printf("%d\n",a);
}
printf("%d\n",c);
}
Here o/p is c=0 only.If is not executed ,Because of last statement is 0;
C follows procedure oriented.And associativity of () is left to right.