If I did not compile the code I'd say that 1 and 2 give the same result as both of them have an int pointer p pointing to variable age. Dereferencing age in both 1 and 2 should give the same result. I also understand that 3 will just give me the first byte of variable age as it's of type char. I can't explain why 1 and 2 give different results and why 2 and 3 give the same result.
1
int age = 20;
int* p = (int *)0x66FC9C;
printf("You're : %d\n", *p );
2
int age = 20;
int *p = &age;
printf("You're : %d\n", *p );
3
int age = 20;
char* p = (char *)0x66FC9C;
printf("You're %d\n", *p );
Follow-up
It's weird because when I do :
int age1 = 20;
int age2 = 19;
int* p = &age2;
printf("You're %d %d %d %d\n", *p, *(p+1), &age1, &age2 );
and I actually print the addresses I always get the p+1 right (meaning I can predict the address) but if I do :
int age1 = 20;
int age2 = 19;
int* p = &age2;
printf("You're %d %d\n", *p, *(p+1) );
I can never guess it. It's like C knows is being watched... cough cough double slit experiment
You are trying to cheat the compiler, and it looks to be smarter than you...
More seriously, except if you really know the internals of a compiler, never try to guess how it will translate your source. Typically in your last example, a compiler can easily see that the age1 variable is never used (at least never in a conformant way). So it can optimize it out. If you really want to better understand what happens here, you will have to ask the compiler to produce the assembly language that it has internally generated, and read it. You will see whether a variable has been optimized out (because it is not generated), or whether it was not consecutive to the other variable.
And anyway, it is nice to try to better understand what a compiler does, but please never do that in production code.
Who do you know that the address of age is 0x66FC9C? If it's not then you will not be guaranteed the same result in 1 and 2. Equivalent reasoning can be given to 2 and 3.
Related
Please read the code below.
#include <stdio.h>
int main(void)
{
char* a[4];
int i=0;
while(i<3)
{
char b[50];
scanf(" %s",b);//Assume user enters one two three
a[i++]=b;
}
i=0;
while(i<3)
printf(" %s ",a[i++]);//Why does it always print three three three
return 0;
}
Clarify the following:
Is it that b gets allocated same 50 bytes in memory each time so that all the elements of array a point to same 50 bytes and thus we get only three printed three times(i.e. what's entered last)
Since after the completion of while, array b can be removed very well but no it remains there every single time printing only three's. Why?
Is it not at all a coincidence that this code prints only three's when it could print one two three, one three three as well. What's wrong?
I know the question is very wrongly put. Forgive me for that. I am new here.
QUESTION #1:
The variable b is a variable that is strictly local to the
while loop.
Therefore, do not reference via a pointer any memory formerly used by b outside (after) the while loop.
Storage for b will be reallocated 3 times.
At the end of the while loop, b will go out of scope.
QUESTION #2:
After the while loop, a is not a valid pointer anymore
because a was assigned to point to b,
and b has gone out of scope after the while loop.
NEVERTHELESS, the memory allocated to b may still
not have been modified. You cannot predict what the value of dereferencing a will be after the while loop - since a is only assigned based on b.
QUESTION #3:
(Please see #2) The code that is dereferencing a after the while loop is using a stale pointer - I would not rely on the output.
The code in the question exhibits undefined behaviour because the second loop attempts to access the data that was only valid in the first loop. Therefore, there is very little that can usefully be said.
The question title is "does a variable declared in a loop get the same address each time the loop executes". Here's a proof by counter-example that the address of the variables in a loop need not always be the same, even in a single invocation of a non-recursive function.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
srand(time(0));
for (int i = 0; i < 3; i++)
{
int n = rand() % 30 + 5;
char a[n];
for (int j = 0; j < n - 1; j++)
a[j] = rand() % 26 + 'a';
a[n-1] = '\0';
printf("a: %p %2d [%s]\n", (void *)a, n, a);
char b[50+n];
scanf("%s", b);
printf("b: %p %2d [%s]\n", (void *)b, n+50, b);
}
return 0;
}
On a Mac running macOS Sierra 10.12.4 (using GCC 7.1.0), one run of the program (lv83) produced:
$ ./lv83 <<< 'androgynous hermaphrodite pink-floyds-greatest-hits-dark-side-of-the-moon'
a: 0x7fff507e53b0 23 [sngrhgjganmgxvwahshvzt]
b: 0x7fff507e5360 73 [androgynous]
a: 0x7fff507e53c0 9 [wblbvifc]
b: 0x7fff507e5380 59 [hermaphrodite]
a: 0x7fff507e53b0 26 [pqsbfnnuxuldaactiwvjzvifb]
b: 0x7fff507e5360 76 [pink-floyds-greatest-hits-dark-side-of-the-moon]
$
The address at which the two arrays are allocated varies depending on how big they are. By using different formulae for the sizes of the two arrays, the base addresses could be tweaked. It looks as though the compiler rounds the base address of the arrays to a multiple of 16.
I was tried to print values of a float array with 7 elements. I assigned only 3 values and they are belong to float, double and integer.
Code:
#include <stdio.h>
int main(){
float array [7];
float f = 3.24;
double d = 23.5;
int i = 4;
array[0] = f;
array[1] = i;
array[2] = d;
int n = sizeof(array)/sizeof(float);
printf("Number of Elements : %d \n\n\n",n);
for(int j = 0; j < n ; j++){
printf("%.2f ,",array[j]);
}
printf("\b ");
}
I got an output as follows :
Number of Elements : 7
3.24 ,4.00 ,23.50 ,-1.#R ,96627196995476105000000000000000.00 ,96629547147269436000000000000000.00 ,0.00
I want to clear is my code correct? And why last four values are different to each other. What are these values?
The last values are known as garbage values in C.
If you do not initialize a variable explicitly in C, it's value could be anything before you explicitly assign something to it. This anything could be garbage; the language standard does not specify what it should be.
You can read this blog for How C compiler decides garbage values: http://blog.aditech.info/2008/02/how-c-compiler-decides-garbage-values.html.
First.
Yes, your code is correct (add return 0 command at the end of your main() function though). However, it needs to be more specific, which leads to your second question.
Second.
C is a language that allows a programmer to do lots of things, but it also requires the programmer to do lots of manual coding.
So, when you declare an array of 7 items, C compiler marks a region of memory to accommodate those items (in this case of the type of float). But it doesn't actually check what that region of memory contains until you explicitly assign the values. In your case the last four values (which you have not assigned yourself) are just garbage left in the region of memory marked for your array.
Once again, compiler does not clear the memory for you when you declare the array, it just marks the region of memory. It's your responsibility to assign default values to the array.
Your possible solution is to manually initialize all of the elements of your array to some default value (for example, a 0), like this:
float array[7] = {0}
I am trying to understand why the following code does not work... please help:
void incme(double *p)
{
printf("%x,%x\n",p,*p);
*p = *p + 1;
printf("%x,%x\n",p,*p);
}
int main()
{
int i = 1;
incme((double *)&i);
printf("%x,%x",&i,i);
}
the output is:
ff99a348,1
ff99a348,1
ff99a348,1
I am expecting:
ff99a348,1
ff99a348,2
ff99a348,2
it breaks everything I know about pointers...
Thanks.
EDIT:
the main question i am asking the the type cast in incme((double *)&i); why isit not casting it to double and pass it to the function ? ... sorry for not pointing out eailer ....
Because of undefined behavior. Integers are not floating point, and floating point is not integers. Besides that, I think you will find that sizeof(int) != sizeof(double).
You're also breaking the strict aliasing rule.
Unrelated to your question, you should use the "%p" format if you want to print pointers.
When you do *p = *p + 1; with p beeing a double* there is a lot going under the hood, indeed, double are represented using a custom format (wiki), when you use printf to display it as a integer after that, the internal representation of the memory at this address has changed (to a double representation), this is why you obtain such a result.
I ran the code and obtained the following output:
205afc2c,205afd28
205afc2c,593b4ab0
205afc2c,0
It shows use that the value is invalid as a double, and when it's incremented, it does not update the sizeof(int) first bits of the double (as it print 0 in the last line).
Hope I made myself clear !
Edit
I changed the code a little to show you what actually happen:
void incme(double *p)
{
printf("%x,%lf\n",p,*p);
*p = *p + 1;
printf("%x,%lf\n",p,*p);
}
int main()
{
int i = 1;
incme((double *)&i);
printf("%x, %lf, %d",&i,i, i);
}
Gives me the following output:
cb90990c,0.000000
cb90990c,1.000000
cb90990c, 1.000000, 0
As you can see, if you print them as double, the value is indeed correct (but the binary representation of 1.0000 is not 00000000001 as I said previously, this is why the hex formatting gives you a large number).
Back in the main, if you display the value as a double (event if i is supposed to be a int) as the incme function changed the memory layout of it, it does print 1.0000, but the first 32bits of the memory at this address are 0 hence, printing it as an int gives you 0.
The main reason, the printf statements should read -
printf( "%p,%f", p, *p );
This will show your increment of the double.
Also - as stated, an int is generally 4 bytes and a double uses 8 bytes. (on most systems)
This is a C code
int (*a)[3];
a is a pointer to an array of 3 integers
a=(int (*)[3])malloc(sizeof(int)*3);
note the Typecast used here; the number of elements must be specified in the typecast shown. Also, the brackets around the * is necessary.
printf("brrbrrbrr %d %d %d %d\n",&a,a,a+1,a+2);
*(a+0)[0]=40;
*(a+0)[1]=41;
*(a+0)[2]=42;
printf("noobnoob %d %d %d \n",a[0][0],*(a+0)[1],(*(*(a+0)+2)));
The output is:
brrbrrbrr -7077000 29278656 29278668 29278680
noobnoob 40 41 0
I am not getting why the last number is 0 instead of 42?
Indexation has higher precedence than dereferencing a pointer. Your assignments don't do what you want. They are evaluated like:
*((a+0)[0])=40;
*((a+0)[1])=41;
*((a+0)[2])=42;
If you want to keep your syntax, you shall use parenthesis like:
(*(a+0))[0] = 40;
(*(a+0))[1] = 41;
(*(a+0))[2] = 42;
The same applies for printing the second element of the array. *(a+0)[1] shall be (*(a+0))[1].
What you are looking for is
int (*a)[3] = malloc(sizeof(int) *3);
(*a)[0] = 40;
(*a)[1] = 41;
(*a)[2] = 42;
printf("%d %d %d\n",(*a)[0],(*a)[1],(*a)[2]);
a is a pointer to an array of 3 int members. So allocate memory for the pointer and store values as shown above.
If you want the address of where the values are stored then you should do
printf("%p\n",(void*)(a)[0]);
So, I'm just practicing something in C language (I'm a beginner), but I'm now stuck on this program:
#include <stdio.h>
#include <string.h>
int main(){
int numbers[12] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37};
int i;
int *point;
point = numbers;
while(i){
printf("Write number in ranging 1 - 40: \n");
scanf("%d", &numbers);
if (numbers, point){
printf("Your number is prime number.\n");
}
else if ((numbers <= 0) || (numbers >= 41)){
printf("Only numbers: 1 - 40.\n");
}
else{
printf("Try again.\n");
}
i;
}
return 0;
}
When I want to compile it, I just get this error message:
test.c: In function ‘main’:
test.c:19:38: warning: comparison between pointer and integer [enabled by default]
I looked around Stack Overflow, but I found nothing of similar topic and didn't help me.
Even if you're a beginner, you should still take the effort to tell us which lines are giving you errors, since it's not easy to tell exactly what line is number 19.
I think this line is giving you trouble.
if (numbers, point){ // bad
You probably meant to call some function that takes numbers and point as an argument. As it is right now, this if statement will always evaluate to true because you are using the comma operator, which just uses the value of the thing on its right, which happens to be a non-null pointer (point). How about something like:
if is_a_prime(numbers, point)
Moving on, the line that actually is causing the error is most likely this line:
else if ((numbers <= 0) || (numbers >= 41)){ // bad
Since numbers is an array, it doesn't make much sense to write numbers <= 0. Perhaps you meant to write numbers[0] <= 0, or *point <= 0, or maybe you wanted to use a for loop to iterate over each number in the array to make sure it is positive.
Also, (thanks to isedev for seeing this), you never set i to any value before accessing it, so your program will have undefined behavior. Try writing something like i = 1; near the top.
First of all, this program will most likely not run. Specifically because you are saying while (i) when i is uninitialized (i.e garbage). It might be zero or any other value its initial address happens to point to.
Secondly, what do you mean by if (numbers, point) ? That doesn't mean anything.
Also, point is numbers, so there's no reason to compare them.
Thirdly, if you want to check for a prime number use the modulo operator. Like this.
Lastly, a pointer is not an integer or an array. When you say point = numbers that just stores the address of numbers in memory into point, and using pointer arithmetic (and because pointer[3] and array[3] mean the same thing ~ pointer + (3 * sizeof(datatype))), you might think that a pointer is an array, but it's not. Here's an example:
int h, *p;
h = 5;
*p = &h;
printf("*p: %d\n", *p);
h = 8;
printf("*p: %d\n", *p);
Here, *p is the value of h, and for a really simple reason.
p stores the address of h in memory, and when you say h = 5 the computer changes the value found at the address of h in memory. And because p happens to store the address itself in it, it can simply get the value found there. In short, p has no relation to h, dot.
There are a couple of problems in this code:
Your i value variable is uninitialized
If the garbage value of i is non zero its an infinite loop
In the if condition you need to do a logical operation
You are using scanf() not with pointer you use are using pointer to pointer