Why Size is different for different pointers - c

#include <stdio.h>
#define R 10
#define C 20
int main()
{
int *p;
int *p1[R];
int *p2[R][C];
printf("%d %d %d", sizeof(*p),sizeof(*p1),sizeof(*p2));
getchar();
return 0;
}
Why is the output: 4 8 160? Why does size of p1 becomes 8 and not 4?

Consider the types.
sizeof(*p) ==> sizeof(int)
sizeof(*p1) ==> sizeof(int *)
sizeof(*p2) ==> sizeof((int [20]))
Note: Depending on your platform and compiler, you'll get different results.
Also, as we know, sizeof produces a result of type size_t, it's advised to use %zu format specifier to print the result.

Related

C getting the size of an array

the code:
int arr[5] = {10, 20, 30, 40, 50};
printf("%lu %lu\n", *(&arr + 1), arr); // 6422036 6422016
printf("%lu\n", *(&arr + 1) - arr); // 5
Why the second printf prints 5 instead of 20?
There are two points in your interesting question :
How does operation on pointers work ?
What is the difference between arr and &arr ?
1 : How does operation on pointers work ?
Try the following code :
#include <stdio.h>
#include <inttypes.h>
int main(int argc, char **argv) {
int simpleInt= 10 ;
printf("Output 1 : %p %p \n", &simpleInt+1, &simpleInt); // 61FE20 and 61FE1C
printf("Output 2 : %lld \n", &simpleInt+1 - &simpleInt); // 1
printf("Output 3 : %lld\n", (uint64_t)(&simpleInt+1) - (uint64_t)(&simpleInt)); // 4
}
Output 1 : Clearly, the difference between the two printed pointer values is 4
Output 2 : You are performing operation on int *. 1 is added to an operand of type int * and after an operand of type int * is substracted. From an " int * point of view" (if I could simplify it like that), only one is added. So, the output is 1.
Ouput 3 : Each operands of the substraction are casted to a long long unsigned int. So the substraction is done on integers and not on pointers. The ouput is 4, as expected.
2. What is the difference between arr and &arr ?
Let's have a look to the following code
int arr[5] = {10, 20, 30, 40, 50};
printf("Output 1 : %p %p %p \n", arr, &arr, *(&arr) ); //Seems to be the same thing but NOT. int*, int*[5], int*, respectively
// printf("%lld\n", arr - &arr ); // compilation error : int * and int(*)[5]
printf("Output 2 : %lld\n", arr - *(&arr) );
//printf("%lld\n", &arr - *(&arr) ); // compilation error : int(*)[5] and int *
printf("Output 3 : %p %p %p \n", (arr + 1), (&arr + 1), *(&arr + 1) ); // +4, +20, +20
printf("Output 4 : %lld\n", *(&arr + 1) - arr);
printf("Output 5 : %lld\n", (uint64_t)(*(&arr + 1)) - (uint64_t)(arr));
Ouput 1 : The value are the same but not the type of arguments. And this point is very important. The name of an array is a pointer to its first element. In your case, your array is an array of int, so arr is a pointer to int : int*. &arr is the address of your variable arr which is an array of 5 integers. So the type of &arr is int(*)[5]. And the type of *(&arr) is int*
Output 2 : Some lines give compilation errors because of the explanation above. And you could do operations on the same pointer type : arr and *(&arr)
Output 3 : Depending which kind of pointer is incremented, +4 or +20 is obtained. +20 because 1 is added to an operand of type int(*)[5] : 5 * 4 (sizeof int = 4)
Output 4 & 5 : As, in the first point (operation on pointer), your are performing a substraction with int* as operand
Why the second printf prints 5 instead of 20?
Code is living on the edge.
&arr is the address of the array, so + 1 is the address of the next array: 5 int later. So far, this is good.
*(&arr + 1) de-references that address. So we get that next array. Not so good #RobertS supports Monica Cellio. An array passed to a ... function like printf() is converted to the address of the first element, an int *.
*(&arr + 1) - arr subtracts two pointers of the same type int * that are 5 int apart leading to difference of 5 of type intptr_t. Recall that pointer subtraction is the difference of the number of the referenced types (int in this case), not the difference of the pointer values. 5 not 20.
Code attempts to print a intptr_t as an unsigned long with "%lu", which might work, might not (UB). Not so good. Better to use "%td".
printf("%td\n", *(&arr + 1) - arr);

Functionality of sizeof

Why dose the folowing code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("Hello world!\n");
int x;
long l;
double d;
printf("\n%d",sizeof(x+l+d));
return 0;
}
prints on the console 8?
I originaly thought that will convert x and l to double and display 24.
Why 8?
sizeof returns the number of bytes used to store its argument. In this case its argument is x+l+d. x is an int, l a long, and d a double. When you add integer types to doubles, the result is promoted to form a double. So what you have written is the equivalent of sizeof(double). A double takes 8 bytes to store, so you are seeing 8 as the result.
You are only passing one argument to sizeof, and that single argument's type is double. If you wrote sizeof(x) + sizeof(l) + sizeof(d), that would be something different (although still not 24, because not each argument is double).

Substracting pointers: how variable j is getting this value?

So I have a program in C. its running but I don't understand how the output is generated ??
Here is the program :
#include <stdio.h>
int c;
void main() {
int a=10,b=20,j;
c=30;
int *p[3];
p[0]=&a;
p[1]=&b;
p[2]=&c;
j=p[0]-p[2];
printf("\nValue of p[0] = %u\nValue of p[2] = %u\nValue of j = %d\n\n",p[0],p[2],j);
}
and Here is the output :
Value of p[0] = 3213675396
Value of p[2] = 134520860
Value of j = -303953190
Can anyone tell me how j got this value i.e. -303953190 ?? It is supposed to be 3079154536
You are doing 3213675396 - 134520860. If you want to get the value use *p[0]. If your intention is to substract the address(which doesnt make sense but still) the expected answer should be 3079154536. But since the number if too large to hold hence you get the answer -303953190. Consider char for simplicity on number line
-128 -127 -126 -125 ... 0 1 2 ... 125 126 127
Now if you try to store 128 it out of range so it will give value -128. If try to assign value 130 you will get -126. So when the right hand side limit is exceeded you can see the counting starts from the left hand side. This is just for explanation purpose only the real reason for this behavior is owed due the fact that it is stored as two's compliment. More info can be found here
You should compute the difference of the pointed objects rather than of the pointers:
j=(*(p[0]))-(*(p[2]));
p is array of pointers to int - so its storing pointers to int and not ints. Hence, p[0] and p[2] are pointers - subtracting them will give you an integer which may overflow that you are trying to store in an int where the problem lies. Also addresses are to printed using %p not %d.
Dereference the value and you will get what you are looking for, like this:
j=p[0][0]-p[2][0];
or like this:
j=*(p[0])-*(p[2]);
Substracting two pointers results in a signed integer.
From the C Standard chapter 6.56:
6.5.6 Additive operators
[...]
9 When two pointers are subtracted, both shall point to elements of the same array object,
or one past the last element of the array object; the result is the difference of the
subscripts of the two array elements. The size of the result is implementation-defined,
and its type (a signed integer type) is ptrdiff_t defined in the < stddef.h> header.
And assigning the pointer difference to an int overflows the int.
To get around this overflow instead of
int j;
use
ptrdiff_t j;
and then print the value using %td.
From the C Standard chapter 7.17:
7.17 Common definitions < stddef.h>
[...]
2 The types are
ptrdiff_t
which is the signed integer type of the result of subtracting two pointers;
Also (unrelated)
void main()
is wrong. It shall be
int main(void)
So the correct code would look like this:
#include <stdio.h>
#include <stddef.h> /* for ptrdiff_t */
int c;
int main(void)
{
int a=10, b=20;
ptrdiff_t j;
int * p[3];
c=30;
p[0]=&a;
p[1]=&b;
p[2]=&c;
j=p[0]-p[2];
printf("\nValue of p[0] = %p\nValue of p[2] = %p\nValue of j = %td\n\n",
(void *) p[0],
(void *) p[2],
j);
return 0;
}
You're printing it as an integer instead of an unsigned. Use %u instead of %d.
Try this:
#include <stdio.h>
int c;
void main() {
int a=10,b=20;
unsigned j;
c=30;
int *p[3];
p[0]=&a;
p[1]=&b;
p[2]=&c;
j=(unsigned)p[0]-(unsigned)p[2];
printf("\nValue of p[0] = %u\nValue of p[2] = %u\nValue of j = %u\n\n",(unsigned)p[0],(unsigned)p[2],j);
}

Int Address in memory increasing by 4

#include<stdio.h>
int main()
{
int x = 1,*t;
float y = 1.50,*u;
char k = 'c',*v;
t = &x;
u = &y;
v = &k;
printf("%p %p %p", t, u, v);
t++;
u++;
v++;
printf(" %p %p %p", t, u, v);
return 0;
}
Hi i have made this code but here something unusual is happening , i am printing the addresses , when i increase the address of all then from my view increment in int would be 2 , float would be 4 and char would be 1 but i got the following :
0xbffa6ef8 0xbffa6ef0 0xbffa6eff 0xbffa6efc 0xbffa6ef4 0xbffa6f00
For float and char i think its correct but for int i don't know why it is giving so
You are assuming the sizeof(int) is 2 on your system/envrionment.
However, Your assumption is not correct. The standard does not require the size of int to be 2 or anything specific.
As your program shows the size of int is 4 on your system/envrionment.
Lesson to Learn:
Never rely or assume on size of an type, always use sizeof to determine the size, that is the reason the standard provides sizeof.
The memory address increment for t is given by sizeof(int).
If sizeof(int) is different than what you expect t to be incremented by then your assumption is wrong.
An int data type is usually 4 bytes. a short or a short int data type is 2 bytes;
The actual size of integer types varies by implementation. The only guarantee is that the long long is not smaller than long, which is not smaller than int, which is not smaller than short.
or
sizeof ( short int ) <= sizeof ( int ) <= sizeof ( long int )
But you can be sure that it will be atleast 16 bits in size.
This will be helpful,detailed informations regarding the size of basic C++ types.

Difference between "pointer to int" and "pointer to array of ints"

int main()
{
int (*x)[5]; //pointer to an array of integers
int y[6] = {1,2,3,4,5,6}; //array of integers
int *z; //pointer to integer
z = y;
for(int i=0;i<6;i++)
printf("%d ",z[i]);
x = y;
for(int i=0;i<6;i++)
printf("%d ",(*x)[i]);
return 0;
}
Both the above printfs print numbers 1 through 6.
If both "pointer to array of integers" and "pointer to integer" can do the same thing, do they have the same internal representation?
EDIT: This code does give warnings when compiled as pointed out by the answers below, however it does print the values correctly both the time on my x86_64 machine using gcc
Firstly, your code will not compile. The array has type int[6] (6 elements), while the pointer has type int (*)[5]. You can't make this pointer to point to that array because the types are different.
Secondly, when you initialize (assign to) such a pointer, you have to use the & on the array: x = &y, not just a plain x = y as in your code.
I assume that you simply typed the code up, instead of copy-pasting the real code.
Thirdly, about the internal representation. Generally, in practice, you should expect all data pointers to use the same internal representation. Moreover, after the above assignments (if written correctly), the pointers will have the same numerical value. The difference between int (*)[5] and int * exists only on the conceptual level, i.e. at the level of the language: the types are different. It has some consequences. For example, if you increment your z it will jump to the next member of the array, but if you increment y, it will jump over the whole array etc. So, these pointers do not really "do the same thing".
The short answer: There is a difference, but your example is flawed.
The long answer:
The difference is that int* points to an int type, but int (*x)[6] points to an array of 6 ints. Actually in your example,
x = y;
is undefined** behavior, you know these are of two different types, but in C you do what you want. I'll just use a pointer to an array of six ints.
Take this modified example:
int (*x)[6]; //pointer to an array of integers
int y[6] = {1,2,3,4,5,6}; //array of integers
int *z; //pointer to integer
int i;
z = y;
for(i = 0;i<6;i++)
printf("%d ",z[i]);
x = y; // should be x = &y but leave it for now!
for(i = 0;i<6;i++)
printf("%d ",x[i]); // note: x[i] not (*x)[i]
First,
1 2 3 4 5 6
Would be printed. Then, we get to x[0]. x[0] is nothing but an array of 6 ints. An array in C is the address of the first element. So, the address of y would be printed, then the address of the next array in the next iteration. For example, on my machine:
1 2 3 4 5 6 109247792 109247816 109247840 109247864 109247888 109247912
As you can see, the difference between consecutive addresses is nothing but:
sizeof(int[6]) // 24 on my machine!
In summary, these are two different pointer types.
** I think it is undefined behavior, please feel free to correct my post if it is wrong.
Hope this code helps:
int main() {
int arr[5] = {4,5,6,7,8};
int (*pa)[5] = &arr;
int *pi = arr;
for(int i = 0; i< 5; i++) {
printf("\n%d %d", arr[i], (*pa)[i]);
}
printf("\n0x%x -- 0x%x", pi, pa);
pi++;
pa++;
printf("\n0x%x -- 0x%x", pi, pa);
}
prints the following:
4 4
5 5
6 6
7 7
8 8
0x5fb0be70 -- 0x5fb0be70
0x5fb0be74 -- 0x5fb0be84
UPDATE:
You can notice that pointer to integer incremented by 4 bytes (size of 32 bit integer) whereas pointer to array of integer incremented by 20 bytes (size of int arr[5] i.e. size of 5 int of 32 bit each). This demonstrates the difference.
To answer your question from the title, from the comp.lang.c FAQ: Since array references decay into pointers, if arr is an array, what's the difference between arr and &arr?
However, the code you've posted has other issues (you're assigning y, not &y to x, and y is a 6-element array, but *x is a 5-element array; both of these should generate compilation warnings).
Who knows - this code exhibits undefined behavior:
printf("%d ",(*x)[i]);
Hope this code helps.
#include <stdio.h>
#include <stdlib.h>
#define MAXCOL 4
#define MAXROW 3
int main()
{
int i,j,k=1;
int (*q)[MAXCOL]; //pointer to an array of integers
/* As malloc is type casted to "int(*)[MAXCOL]" and every
element (as in *q) is 16 bytes long (I assume 4 bytes int),
in all 3*16=48 bytes will be allocated */
q=(int(*)[MAXCOL])malloc(MAXROW*sizeof(*q));
for(i=0; i<MAXROW; i++)
for(j=0;j<MAXCOL;j++)
q[i][j]=k++;
for(i=0;i<MAXROW;i++){
for(j=0;j<MAXCOL;j++)
printf(" %2d ", q[i][j]);
printf("\n");
}
}
#include<stdio.h>
int main(void)
{
int (*x)[6]; //pointer to an array of integers
int y[6] = {11,22,33,44,55,66}; //array of integers
int *z; //pointer to integer
int i;
z = y;
for(i = 0;i<6;i++)
printf("%d ",z[i]);
printf("\n");
x = &y;
for(int j = 0;j<6;j++)
printf("%d ",*(x[0]+j));
return 0;
}
//OUTPUT::
11 22 33 44 55 66
11 22 33 44 55 66
Pointer to an array are best suitable for multi-dimensional array. but in above example we used single dimension array. so, in the second for loop we should use (x[0]+j) with * to print the value. Here, x[0] means 0th array.
And when we try to print value using printf("%d ",x[i]);
you will get 1st value is 11 and then some garbage value due to trying to access 1st row of array and so on.
One should understand the internal representation of (*x)[i]. Internally, it is represented as
*((*x)+i), which is nothing but the ith element of the array to which x is pointing. This is also a way to have a pointer pointing to 2d array. The number of rows is irrelevant in a 2d array.
For example:
int arr[][2]={{1,2},{3,4}};
int (*x)(2);
x=arr; /* Now x is a pointer to the 2d array arr.*/
Here x is pointing to a 2d array having 2 integer values in all columns, and array elements are stored contiguously. So (*x)[0] will print arr[0][0] (which is 1), (*x)[1] will print the value of arr[0][1] (which is 2) and so on. (*x+1)[0] will print the value of arr[1][0] (3 in this case) (*x+1)[1] will print the value of arr[1][1] (4 in this case) and so on.
Now, a 1d array could be treated as nothing but a 2d array having only one row with as many columns.
int y[6] = {1,2,3,4,5,6};
int (*x)[6];
x =y;
This means x is a pointer to an array having 6 integers. So (*x)[i] which is equivalent to *((*x)+i) will print ith index value of y.

Resources