I was going through scope rules questions and all and then got a code snippet, below:
#include <stdio.h>
int main()
{
int x = 1, y = 2, z = 3;
printf(" x = %d, y = %d, z = %d \n", x, y, z);
{
int x = 10;
float y = 20;
printf(" x = %d, y = %f, z = %d \n", x, y, z);
{
int z = 100;
printf(" x = %d, y = %f, z = %d \n", x, y, z);
}
}
return 0;
}
If I change the last print to:
printf("x = %d, y = %d, z = %d \n", x, y, z);
I get the following output, which I don't understand: (Ideone link)
x = 10, y = 0, z = 1077149696
So, could you explain why is z printing that value?
x, y, and z are resolved to most local definitions.
When you use incorrect printf % specifier, the behaviour is undefined.
y is float but you are using %d to print it (in later line).
printf uses varargs and once you corrupt the stack by using incorrect specifier (%d instead of %f in this case), stack is corrupted and incorrect interpretation of stack data (at incorrect offset) would cause many painful surprises.
Decoding This UB
This is what might be happening on your machine (One possible explanation). Because of default argument promotion, bit pattern (in hex) 0x4034000000000000 is being pushed to stack for 20.0f. Sizeof int on your little-endian machine is 4 bytes. When you print float as int your machine 0x00000000 is consumed and interpreted as int which prints first 0, later %d consumes 0x40340000 interpret it as int and prints 1077149696. Final 100 (0x00000064) is left in stack unconsumed and printf returns.
But never rely on this and always write a code for which the behaviour is well defined.
#mohit-jain is correct.
Using the wrong format specifier yields incorrect parameter interpretation on the stack, resulting in undefined and compiler specific behavior.
Note that on a modern compiler, like gcc or clang, it will complain that your format specification is wrong:
$ clang test.c
test.c:12:54: warning: format specifies type 'int' but the argument has type 'float'
[-Wformat]
printf(" x = %d, y = %d, z = %d \n", x, y, z);
~~ ^
%f
1 warning generated.
z = 1077149696
Using %d to print float values is undefined behaviour.
Use "%f" instead
All the variables you have used have storage type "Auto" or "Automatic".
The scope of the automatic variable lies inside the block in which it is declared.
If there are nested blocks, then the variable declared in the outermost block will be visible to all other blocks.
In case if a block has a declared a variable that matches with the one declared in outer blocks, then it will overwrite the outer variable "in its block" i.e.(locally).
To sum up :
Automatic variables are local to the block in which they are declared.
Related
I want to write a C program that evaluates the factorials of the integers from 1 to 5 and print them in a tabular format. However, I keep getting a strange number over everything. Here's the code:
#include <stdio.h>
int main()
{
int factorial;
printf("X\t Factorial of X\n");
for(int x=1; x<=5; x++)
{
factorial = 1;
for (int j=1; j<=x; j++)
{
factorial *=j;
}
printf("%d\t %d\n", &x, &factorial);
}
return 0;
}
Here's the result of this code:
X Factorial of X
6356768 6356772
6356768 6356772
6356768 6356772
6356768 6356772
6356768 6356772
What's wrong with my code? The result should be like this:
X Factorial of X
1 1
2 2
3 6
4 24
5 120
Remove & which stands for address of. You are printing address of the variable, not its value.
printf("%d\t %d\n", x, factorial);
When using printf (and related output functions), the %d format specifier expects an int as the corresponding argument. In your printf("%d\t %d\n", &x, &factorial); you are passing the addresses of the x and factorial variables.
So, just remove the two & (address of) operators: printf("%d\t %d\n", x, factorial);!
You are possibly being confused by the fact that, for scanf (and other input functions), the %d specifier requires a pointer to its target variable.
printf("%d\t %d\n", &x, &factorial);
&x and &factorial are addresses of those variables, not the variables themself. Omit the &.
In the statement printf("%d\t %d\n", &x, &factorial); you have used '&' which prints the address of that element.
Unlike scanf, printf() with format %d requires integer values, not addresses (&x is the address containing an integer, so a pointer to integer which type is int *). The correct expression is
printf("%d\t %d\n", x, factorial);
Why was the previous expression wrong?
With printf("%d\t %d\n", &x, &factorial); you are asking to printf to print the decimal representations of the addresses of x and factorial respectively.
For this reason it is not surprising that the values that used to be printed, 6356768 and 6356772:
Are big numbers, multiples of 4 (because they address integers, that have a size 4 bytes, and in 32 bits architectures like yours are aligned to memory locations multiples of 4)
They are memory locations, and their addresses do not vary even if their contents are changed
You can find printf documentation here.
I tried declaring two variables,one of type int * and one of type double * and assigned each their addresses,but assignment by de-reference and printing displays correct value of int but prints 0.0 for double.why is that?
#include <stdio.h>
int main(void)
{
int *x;
x = (int *)&x;
*x = 3;
//print val of pointer
printf("%d\n", x);
double *y;
y = (double *)&y;
*y = 4.0;
printf("%lf\n", y);
return 0;
}
I get 4.0.
What you do is you re-interpret the memory allocated to store addresses (x and y) as int and double, respectively.
You do that twice: When you assign data values to the re-interpreted memory, and when you print a copy of it. The two cases are distinct.
Writing to memory through a pointer of incompatible type is undefined bahavior, and compilers like gcc are known to do funny things (trap or ignore the code) in such cases. There are meandering discussions about that, including a famous rant by Linus Torvalds. It may or may not work. If it works, it probably does the expected thing. (For correct code you must use a union or perform a memcpy.)
One condition for it to work is that your data types don't need more space than the pointers. On a 32 bit architecture (and that may be a 32 bit compiler for a 64 bit Intel CPU), a double will be longer than a 4 byte address (a IEEE 754 double has 8 bytes). *y = 4.0; writes beyond y's memory, overwriting other data on the stack. (Note that y points to itself, so that assigning to *y overwrites y's own memory.)
Passing a pointer value as a parameter to printf with a conversion specification of %d resp. %lf is undefined as well. (Actually it's already undefined if the conversion specification is %p and the pointer value is not cast to void *; but that's often ignored and irrelevant on common architectures.) printf will just interpret the memory on the stack (which is a copy of the parameters) as an int resp. as a double.
In order to understand what happens let's look at the memory layout on the stack of main. I have written a program detailing it; the source is below. On my 64 bit Windows the double value of 4.0 gets printed alright; the pointer variable y is large enough to hold the bytes of a double, and all 8 bytes are copied to printf's stack. But if the pointer size is only 4 bytes, only those 4 bytes will be copied to printf's stack, which are all 0, and the bytes beyond that stack will contain memory from earlier operations, or arbitrary values, for example 0 ;-), which printf will read in an attempt to decode a double.
Here is an inspection of the stack on a 64 bit architecture during the various steps. I have bracketed the pointer declarations with two sentinel variables declStart and declEnd, so that I could see where the memory is. I would assume that the program would run with minor changes on a 32 bit architecture as well. Try it and tell us what you see!
Update: It runs on ideone, which appears to have 4 byte addresses. The double version doesn't print 0.0 but some arbitrary value, likey because of stack garbage behind the 4 address bytes. Cf. https://ideone.com/TJAXli.
The program for the output above is here:
#include <stdio.h>
void dumpMem(void *start, int numBytes)
{
printf("memory at %p:", start);
char *p = start;
while((unsigned long)p%8){ p--; numBytes++;} // align to 8 byte boundary
for(int i=0; i<numBytes; i++)
{
if( i%8 == 0 ) printf("\nAddr %p:", p+i);
printf(" %02x", (unsigned int) (p[i] & 0xff));
}
putchar('\n');
}
int len; // static allocation, protect them from stack overwrites
char *from, *to;
int main(void)
{
unsigned int declStart = 0xaaaaaaaa; // marker
int *x = (int *) 0xbbbbbbbbbbbbbbbb;
double *y = (double *)0xcccccccccccccccc;
unsigned int declEnd = 0xdddddddd; // marker
printf("Addr. of x: %p,\n of y: %p\n", &x, &y);
// This is all UB because the pointers are not
// belonging to the same object. But it should
// work on standard architectures.
// All calls to dumpMem() therefore are UB, too.
// Thinking of it, I'd be hard-pressed to find
// any defined behavior in this program.
if( &declStart < &declEnd )
{
from = (char *)&declStart;
to = (char *)&declEnd + sizeof(declEnd);
}
else
{
from = (char *)&declEnd;
to = (char *)&declStart + sizeof(declStart);
}
len = to - from;
printf("len is %d\n", len);
printf("Memory after initializations:\n");
dumpMem(from, len);
x = (int *)&x;
printf("\nMemory after assigning own address %p to x/*x: \n", &x);
dumpMem(from, len);
*x = 3;
printf("\nMemory after assigning 3 to x/*x: \n");
dumpMem(from, len);
//print val of pointer
printf("x as long: %d\n", (unsigned long)x);
y = (double *)&y;
*y = 4.0;
printf("\nMemory after assigning 4.0 to y/*y: \n");
dumpMem(from, len);
printf("y as float: %f\n", y);
printf("y as double: %lf\n", y);
printf("y as unsigned int: 0x%x\n", y);
printf("y as unsigned long: 0x%lx\n", y);
return 0;
}
Boy, that's the weirdest piece of code I have seen lately ...
Anyway if you really want to figure out what is going on throughout the code, the best way to do it would be to step through it with a debugger. Here's how it works on my machine:
(gdb) break main
Breakpoint 1 at 0x400535: file test.c, line 6.
(gdb) run
...
Breakpoint 1, main () at test.c:6
warning: Source file is more recent than executable.
6 x = (int *)&x;
(gdb) n
7 *x = 3;
(gdb) p x
$1 = (int *) 0x7fffffffdab0
(gdb) n
9 printf("%d\n", x);
(gdb) p x
$2 = (int *) 0x7fff00000003
(gdb) n
3
12 y = (double *)&y;
(gdb) n
13 *y = 4.0;
(gdb) p y
$3 = (double *) 0x7fffffffdab8
(gdb) n
14 printf("%lf\n", y);
(gdb) p y
$4 = (double *) 0x4010000000000000
(gdb) n
0.000000
15 return 0;
(gdb)
Basically what you're doing is messing up with the pointers values by using themselves in the process. When doing *x = 3; you can see you wiped out the least significat 32 bits of x by writing 0x00000003 instead. After that, when you do *y = 4.0; you overwrite the whole pointer value with the internal double representation of 4.0. Intuitively, the second printf should print 4.0, so I guess the issue stands within printf itself. If you do:
double test;
memcpy(&test, &y, sizeof(double));
printf("%lf\n", test);
This will output 4.000000.
I just want to assign the value of pow to a variable, I've used this
#include<stdio.h>
#include<math.h>
int main( void )
{
int x;
int y;
int z;
x=10;
y=2;
z = pow(x,y);
printf ("%d" , &z);
return 0;
}
but in output I get -1076813284 , I am sorry, but I just started learning C and in every tutorial everyone just print the value of pow, like
printf("Value 3.05 ^ 1.98 = %lf", pow(3.05, 1.98));
and I don't know how to assign it to a variable
printf ("%d" , &z);
prints the address of z (*), not its value. printf("%d", z) prints the value.
(*) Actually, the behavior is undefined and on a 64-bit CPU it will likely print half of the address.
&z is the address of the variable z. If you want to print out the value of z, then the code is simply
printf("%d", z);
You would use &z when reading a value into z, because scanf needs a pointer in order to modify your variable.
pow returns a double (and not a reference), you need to make your print statement:
printf ("%f" , z);
After changing z to a double:
double z;
pow returns double and it takes arguments of type double.
double pow(double x, double y)
You need %f specifier in printf and also remove & from z.
Another way is to cast the return value of pow to int and use %d
int z = (int)pow(x, y);
printf ("%d" , z);
i'm not even sure if comma operator is the problem here but i didn't want to write "Weird problem with my C code.
#include <stdio.h>
int main() {
int i = 0, x = 0, y = 0, z = 0;
y = 3;
z = 5;
(x&&(y = z), i = 10);
printf("i:%d, x:%d, y:%d, z:%d\n", x, y, z, i);
return 0;
}
Compiled with:
$ gcc -Wall deneme.c -o deneme
deneme.c: In function ‘main’:
deneme.c:9:4: warning: value computed is not used [-Wunused-value]
deneme.c:9:4: warning: value computed is not used [-Wunused-value]
and output is:
i:0, x:3, y:5, z:10
So, here is my questions:
Why i is not 10?
y is 5 and that's okay, but why z is 10?
Why x is 3?
Sorry if it's an easy question but i'm totally confused.
printf("i:%d, x:%d, y:%d, z:%d\n", x, y, z, i);
You printed x as i, y as x, z as y and i as z.
You are specifying wrong order of the arguments in the printf
Um... the order of your arguments to the printf doesn't match the text of the string.
Ie: you print i x y z, but you pass in x y z i.
So i=10, x=0, y=3 z= 5.
The reason for the warnings is not to do with the the comma operator, but rather this sub-expression: x && (y = z) is evaluated but not assigned to anything or used in any way, so the result is discarded.
It does have a side effect that may be intentional by the short circuit evaluation of x. i.e. if x is zero, y will not be assigned z, but that would be funky code best avoided.
In fact the comma operator is also best avoided outside of <expr1> or <expr3> of a `for( ; ; ) construct perhaps. There are few useful or compelling uses for it otherwise.
Stackoverflow,
I'm trying to write a (very) simple program that will be used to show how machine precision and flops effect functions around their root. My code is as follows:
#include <stdio.h>
#include <math.h>
int main(){
const float x = 2.2;
float sum = 0.0;
sum = pow(x,9) - 18*pow(x,8) + 144*pow(x,7) - 672*pow(x,6) + 2016*pow(x,5) -
4032*pow(x,4) + 5376*pow(x,3) - 4608*pow(x,2) + 2304*x - 512;
printf("sum = %d", sum);
printf("\n----------\n");
printf("x = %d", x);
return 0;
}
But I keep getting that sum is equal to zero. At first I thought that maybe my machine wasn't respecting the level of percision, but after printing x I discovered that the value of x is changing each time I run the program and is always huge (abs(x) > 1e6)
I have it declared as a constant so I'm even more confused as to whats going on...
FYI I'm compiling with gcc -lm
printf("sum = %d", sum);
sum is a float, not an int. You should use %f instead of %d. Same here:
printf("x = %d", x);
Reading about printf() format specifiers may be a good idea.