-6

I was learning pointers and tried experimenting with it! Here is my code..

#include<stdio.h>

int main() {
int a[2]={1,2};
int* p=a;
int* q=&a;
int *r=&a[0];
printf("%d %d %d",p,q,r);
return 0;
}

The output for the code is :

-20578720 -20578720 -20578720  

Now when I change q to an integer variable , the addresses are not negative:

#include<stdio.h>

int main() {
int a[2]={1,2};
int* p=a;
int q =*a;//this is the change
int *r=&a[0];
printf("%d %d %d",p,q,r);
return 0;
}

Output now:

1822271664 1 1822271664

I tried searching on the web and found this memory address positive or negative value in c? It told to use %p and I did and I got positive hexadecimal address values as :

0x7ffc4b5dbb90 0x7ffc4b5dbb90 0x7ffc4b5dbb90  

Now I have the correct answer but don't know

  1. why %p works but not %d and
  2. why after making q integer the addresses were positive.

For the first one I got this but I am not able to understand the answers:Difference between %d and %p printf format string directives in c language?

kalpaj agrawalla
  • 878
  • 1
  • 9
  • 19
Alex
  • 1
  • 2
  • please format your code properly – roschach Jan 18 '19 at 20:12
  • 1
    To put it simply, using `%d` with pointers is incorrect and invokes [undefined behavior](https://stackoverflow.com/questions/2397984/undefined-unspecified-and-implementation-defined-behavior). Hence, your question technically makes no sense: _anything_ can happen in both of your programs. – yeputons Jan 18 '19 at 20:14
  • %d is a 32-bit signed integer, that's how you asked the address to be printed. %u is a 32-bit unsigned integer. You could also try printing a 64-bit integer, signed or unsigned. That is your homework assignment, get back to me when done. – TheGreatContini Jan 18 '19 at 20:15
  • @TheGreatContini `"%d"` is for `int`. The `int` bit width is not important here. – chux - Reinstate Monica Jan 18 '19 at 22:47
  • Quite likely, in your C implementation, pointers are eight bytes, and `int` is four bytes. When you incorrectly printed pointers using `%d`, it happened that the low four bytes of the pointers were used for the `int`. (This is just what happened, not behavior you can rely on.) The low four bytes are the most variable, and the system varies program layouts to make it harder for malicious software to attack. So they varied in the “sign bit” of the `int`. – Eric Postpischil Jan 19 '19 at 00:05

2 Answers2

2

Pointers should be printed with %p not %d: the number might be too big and so it is overflowing.


EDIT Let me be clearer on this: types such as int char etc. have a fixed number of bits/bytes. Even if two types have the same number of bits the difference is how the computer interprets them. For integers, including characters, with n bits can represent 2^n values. Signed integer use some of this to represent negative numbers: particularly you can represent the number in the range -2^(n/2) to 2^(n/2) - 1. On the contrary unsigned int represents numbers from 0 to 2^n - 1. The biggest integer has all bits set to 1 except the msb. To get the correspondent positive number the steps are exactly the same

Negative numbers are calculated using Two's complement: you take the bit-representation of the positive number, do a bit-per-bit negation and then sum 1 to the result. Negative numbers have the most significant bit set to 1.

Let's consider 2 bits: you can represent 4 values with it. If you use an unsigned representation the binary number 10 corresponds obviously to 1. On the contrary if you interpret it as a signed number its value is -2.

Another example is the following consider for example an integer with 8 bits: 00001011. This is a positive number. Suppose you cast it to an integer type of smaller size, for example 4 bits. According to this answer, the most common behaviour, which is actually implementation dependent, is to discard the most significant bits. So your number will become 1011 but using an int representation it is now considered a negative number.


You might try to print is as an unsigned %u:

printf("%u %u %u",(unsigned int)(p),(unsigned int)(q),(unsigned int)(r));

Also note that I am getting the warning: warning: incompatible pointer types initializing 'int *' with an expression of type 'int (*)[2]' [-Wincompatible-pointer-types]

for

int *q  = &a;

EDIT

For example in this program run on my computer returns a size of 8 byte for pointers (of type int) and 4 bytes for int:

#include<stdio.h>
#include<stdlib.h>
int main(void)
{
    printf("size of int*: %lu\n", sizeof(int*));
    printf("size of int: %lu\n", sizeof(int));
    return 0;


}

From this it seems you are following in the second case of the examples I gave.

PLEASE NOTE Being the pointer size bigger, also the cast to unsigned int might not be enough.

roschach
  • 8,390
  • 14
  • 74
  • 124
  • yes and I don't know why this warning is coming since afaik `&a` is same as `a`. Am I wrong somewhere? – Alex Jan 18 '19 at 20:36
  • What are you trying to assign to `q`? the address of `a` or `a` itsself (aka the address of the array)? – roschach Jan 18 '19 at 20:38
  • I was experimenting..hence I thought `&a is same as a` and tried both but the former gave the warning as you mentioned – Alex Jan 18 '19 at 20:42
  • Don't think so `&a` is the address of `a`, `a` is the at that address, which is an address but to the array. – roschach Jan 18 '19 at 20:49
-1

There is nothing to do with turning it into integer variable. You ran the program twice, each time the variable allocated in different address.

When using %d, it will print the signed integer representation of that value, but it can hold 16 or 32 bits

SomoKRoceS
  • 2,934
  • 2
  • 19
  • 30