How is pointer to array different from array names? - c

I was reading more about arrays vs pointers in C and wrote the following program.
#include <stdio.h>
int arr[10] = { } ;
typedef int (*type)[10] ;
int main()
{
type val = &arr ;
printf("Size is %lu\n", sizeof(val)) ;
printf("Size of int is %lu\n", sizeof(int)) ;
}
If, I execute this program, then sizeof(val) is given to be 8 and sizeof(int) is given to be 4.
If val is a pointer to the array with 10 elements, shouldn't it's size be 40. Why is the sizeof(val) 8 ?

If val is a pointer to the array...
Yes, it is, and sizeof(val) produces the size for the "pointer to the array", not the array itself.
...shouldn't it's size be 40.?
No, sizeof(val) calculates the size of the operand, the "pointer" here. In your platform, the size of a pointer seems to be 64 bits, i.e., 8 bytes. So, it gives 8.
Also, as I mentioned, use %zu to print size_t, the type produced by sizeof operator.

First of all this initialization of an array
int arr[10] = { } ;
is invalid in C. You may not use emplty braces in C (in C++ they are allowed). You have to write
int arr[10] = { 0 } ;
In C the corresponding initializer is defined the following way
initializer:
{ initializer-list }
{ initializer-list , }
while in C++
braced-init-list:
{ initializer-list ,opt }
{ }
As for this statement
printf("Size is %lu\n", sizeof(val)) ;
then val is a pointer because it has type type defined like
typedef int (*type)[10] ;
Change this statement to
printf( "Size is %zu\n", sizeof( *val ) );
if you want to get the size of the object (that is of the array) pointed to by the pointer.

sizeof returns the size of the pointer itself. In 64bit system it is 8 bytes.
Pointers have no knowledge of the size of buffer they points to.

A pointer is a distinct data type and always has a fixd size. Think of a pointer as a sign that points to the actual data, and the sign always the same size - regardless if it points to a single character or a larger array.

val is pointer and its size is equivalent to address bus size of system.
so, sizeof(val) or sizeof(anyPointer) will give you 8 as output.
if you want 40 then try sizeof(arr).
Pointer to an array is simple pointer where you can write val++ while array name is constant pointer you cannot write arr++.
you can also check this link

Most probably you are in a 64 bit PC where memory address need 64 bits or 8 byte space for representation.
Now the pointer actually holds the memory address, whereas it may hold an address of int or maybe an address of int[], doesn't matter.
So, when you execute,
printf("Size is %lu\n", sizeof(val)) ;
it shows 8 as because the pointer holds address which need 64 bits space.
And
printf("Size of int is %lu\n", sizeof(int)) ;
this line just print the size of int which is 4 bytes.

Related

Incorrect size of a pointer

I am studying pointers and found I get incorrect size of a pointer.
What I learned is that since p_num is a pointer to an int, it should show 4 bytes but is shows 8.
What could the possible reason for it?
#include <stdio.h>
int main()
{
int num = 0;
int * p_num = NULL;
num = 10;
printf("num address: %p\n", &num);
printf("num size: %zd\n", sizeof(num));
printf("num value: %d\n\n", num);
p_num = &num;
printf("p_num address: %p\n", (void*)&p_num);
printf("p_num size: %zd\n", sizeof(p_num));
printf("p_num value: %p\n", p_num);
printf("p_num value pointed: %d\n", *p_num);
return 0;
}
Output:
num address: 0x7fffcb0e8ffc
num size: 4
num value: 10
p_num address: 0x7fffcb0e8ff0
p_num size: 8
p_num value: 0x7fffcb0e8ffc
p_num value pointed: 10
What could the possible reason for it?
The size of a pointer is dependent upon the architecture. On 32-bit architectures, a pointer usually occupies 4 byte in memory, on 64-bit architectures commonly 8 byte.
So there is nothing wrong with the program or your system itself, if you use a 64-bit architecture as you said in the comments. You just had an incorrect assumption of:
What I learned is that ... a pointer to an int ... should show 4 bytes.
Furthermore, this is usually valid for all pointer types, not only pointers to int. They usually have the same size in memory, but the standard does not require that as you can see in the quote from ISO/IEC 9899:2011 (C11) in this answer regarding to the exact question for that.
The size of a pointer may be also different from the size of the object the pointer point to. So differ between the size of a pointer object and the size of an object the pointer point to.
What I learned is that since p_num is a pointer to an int, it should show 4 bytes but is shows 8.
Your assumption is incorrect.
The int is one variable.
The int pointer is another variable.
So two different variables and these two variables do not need to have the same size.
In other words:
printf("p_num size: %zu\n", sizeof(p_num)); // Gives you the size of the pointer
printf("p_num size: %zu\n", sizeof(*p_num)); // Gives you the size of the pointed to object
^
notice the *
In your case you see that size of int is 4 while size of int pointer is 8. This is perfectly legal.
Most likely, you could have made the size difference even bigger by looking at a char and a char pointer. Then you would most likely see 1 for char and still 8 for char pointer.
sizeof(p_num) is the size of the pointer, not the size of the thing it points to.
sizeof(*p_num) is the size of the thing it points to.
Also, the parentheses are unnecessary. sizeof p_num and sizeof *p_num work fine. Parentheses are needed only to take the sizes of types (rather than expressions) or of complicated expressions.
In order to address more than 4gb in memory the pointers should be 8 bytes of size. Addresses of Memory more than 4gb cannot be represented using 32 bits i.e. 4 bytes.
In the 64-bit machines, the size of pointer is 8 bytes, because a pointer is a memory address. The pointer p_num pointes to the varibale num that is just one of several integer types. In the 64-bits system, sizeof(int) = 4.

C function malloc() does not work as I expected [duplicate]

This is my code.
#include<stdio.h>
typedef struct {
int a,b;
} integers;
void main() {
integers *ptr = (integers *)malloc(10*sizeof(integers));
printf("%d",sizeof(*ptr)); // prints 8
}
From what I understand about Malloc, the above code should actually reserve 10x8=80 bytes of memory for ptr to point to.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
Because you're using sizeof(*ptr) you're actually asking for the size of the first element in the allocated buffer, thus sizeof will return the size of the first element in ptr (i.e. 2x4 bytes integers on 32bits system) rather than the allocated size.
Also, please note that even if you'd use sizeof(ptr) you'd get the size of the ptr pointer which on 32bits system would be 4 bytes.
Well, I know that this question is pretty outdated but finding no suitable answer, I decided to write one.
When specifying sizeof(*ptr), you're actually trying to reach out for the size of data type you've stored in the variable that the pointer is pointing to( here its the first element of the array). Here, that's quite evidently 8.
Even when you'll try to print sizeof(ptr), you'll be again printing the size of the pointer address which by default is 8 bytes in GCC compilers as the data type is long unsigned int.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
The type of the expression *ptr is integers - thus,
sizeof *ptr == sizeof (integers) == sizeof (int) + sizeof (int)
You cannot determine the size of the allocated buffer by looking at the pointer (it doesn't store any metadata about the buffer size). You will have to keep track of that information separately.
Edit
Note that you can do something like the following:
integers (*foo)[10] = malloc( sizeof *foo );
if ( foo )
printf( "sizeof *foo = %zu\n", sizeof *foo );
and that will give you the result you're expecting. In this case, foo is a pointer to an array of integers, not to a single instance of integers, so sizeof *foo will give you the size of the allocated array. The downside is that you have to expliticly dereference foo before applying the subscript:
(*foo)[i].a = some_value(); // or foo[0][i].a
(*foo)[i].b = some_other_value(); // or foo[0][i].b
This is normally done when you want to allocate an NxM array and make sure all the rows are contiguous:
integers (*foo)[10] = malloc( 10 * sizeof *foo );
will allocate a 10x10 array of integers such that the rows are all adjacent in memory.
Also, a pointer to a 10-element array of integers is not compatible with a pointer to an 11-element array of integers, making it more difficult to write functions that can work with pointers to arrays of different sizes. IOW, if you have a function declared as
void bar( integers (*foo)[10] ) { ... }
it can only work with Nx10 arrays of integers. There are ways around this that involve varying levels of pain, but that's a topic for another day.

Size of pointer, pointer to pointer in C

How can I justify the output of the below C program?
#include <stdio.h>
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
char *a;
char **cp[] = {c+3, c+2, c+1, c};
char ***cpp = cp;
int main(void) {
printf("%d %d %d %d ",sizeof(a),sizeof(c),sizeof(cp),sizeof(cpp));
return 0;
}
Prints
4 16 16 4
Why?
Here is the ideone link if you want to fiddle with it.
char *c[] = {"Mahesh", "Ganesh", "999", "333"};
c is an array of char* pointers. The initializer gives it a length of 4 elements, so it's of type char *[4]. The size of that type, and therefore of c, is 4 * sizeof (char*).
char *a;
a is a pointer of type char*.
char **cp[] = {c+3, c+2, c+1, c};
cp is an array of char** pointers. The initializer has 4 elements, so it's of type char **[4]. It size is 4 * sizeof (char**).
char ***cpp = cp;
cpp is a pointer to pointer to pointer to char, or char***. Its size is sizeof (char***).
Your code uses %d to print the size values. This is incorrect -- but it happens to work on your system. Probably int and size_t are the same size. To print a size_t value correctly, use %zu -- or, if the value isn't very large, you can cast it to int and use %d. (The %zu format was introduced in C99; there might still be some implementations that don't support it.)
The particular sizes you get:
sizeof a == 4
sizeof c == 16
sizeof cp == 16
sizeof cpp == 4
are specific to your system. Apparently your system uses 4-byte pointers. Other systems may have pointers of different sizes; 8 bytes is common. Almost all systems use the same size for all pointer types, but that's not guaranteed; it's possible, for example, for char* to be larger than char***. (Some systems might require more information to specify a byte location in memory than a word location.)
(You'll note that I omitted the parentheses on the sizeof expressions. That's legal because sizeof is an operator, not a function; its operand is either an expression (which may or may not be parenthesized) or a type name in parentheses, like sizeof (char*).)
a is an usually pointer, which represents the memory address. On 32-bit operating system, 32bit (4 Byte) unsigned integer is used to represent the address. Therefore, sizeof(a) is 4.
c is an array with 4 element, each element is a pointer, its size is 4*4 = 16
cp is also an array, each element is a pointer (the first *, wich point to another pointer (the second *). The later pointer points to an string in the memory. Therefore its basic element size should represent the size of a pointer. and then sizeof(cp) = 4*4 = 16.
cpp is a pointer's pointer's pointer. It is as well represent the 32bit memory address. therefore its sizeof is also 4.
a is a pointer. cpp is also a pointer just to different type (pointer to pointer to pointer).
Now c is an array. You have 4 elements, each is a pointer so you have 4 * 4 = 16 (it would be different if you would run it on x64).
Similar goes for cp. Try changing type to int and you will see the difference.
So the reason you got 4 16 16 4, is because 'a' is simply a pointer, on its own, which only requires 4 bytes (as a pointer is holding a 32bit address depending on your architecture) and so when you have a **pointer which is == to a *pointer[], your really making an array of pointers, and since you initalized 4 things that created 4 pointers, thus the 4x4 = 16. And for the cpp you may ask "well wouldn't it then be 16 as it was initalized?" and the answer is no, because a ***pointer is its own separate variable and still just a pointer(a pointer to a pointer to a pointer, or a pointer to an array of pointers), and requires only 4bytes of memory.

Why am I not getting the correct size after using malloc and printing using sizeof?

This is my code.
#include<stdio.h>
typedef struct {
int a,b;
} integers;
void main() {
integers *ptr = (integers *)malloc(10*sizeof(integers));
printf("%d",sizeof(*ptr)); // prints 8
}
From what I understand about Malloc, the above code should actually reserve 10x8=80 bytes of memory for ptr to point to.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
Because you're using sizeof(*ptr) you're actually asking for the size of the first element in the allocated buffer, thus sizeof will return the size of the first element in ptr (i.e. 2x4 bytes integers on 32bits system) rather than the allocated size.
Also, please note that even if you'd use sizeof(ptr) you'd get the size of the ptr pointer which on 32bits system would be 4 bytes.
Well, I know that this question is pretty outdated but finding no suitable answer, I decided to write one.
When specifying sizeof(*ptr), you're actually trying to reach out for the size of data type you've stored in the variable that the pointer is pointing to( here its the first element of the array). Here, that's quite evidently 8.
Even when you'll try to print sizeof(ptr), you'll be again printing the size of the pointer address which by default is 8 bytes in GCC compilers as the data type is long unsigned int.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
The type of the expression *ptr is integers - thus,
sizeof *ptr == sizeof (integers) == sizeof (int) + sizeof (int)
You cannot determine the size of the allocated buffer by looking at the pointer (it doesn't store any metadata about the buffer size). You will have to keep track of that information separately.
Edit
Note that you can do something like the following:
integers (*foo)[10] = malloc( sizeof *foo );
if ( foo )
printf( "sizeof *foo = %zu\n", sizeof *foo );
and that will give you the result you're expecting. In this case, foo is a pointer to an array of integers, not to a single instance of integers, so sizeof *foo will give you the size of the allocated array. The downside is that you have to expliticly dereference foo before applying the subscript:
(*foo)[i].a = some_value(); // or foo[0][i].a
(*foo)[i].b = some_other_value(); // or foo[0][i].b
This is normally done when you want to allocate an NxM array and make sure all the rows are contiguous:
integers (*foo)[10] = malloc( 10 * sizeof *foo );
will allocate a 10x10 array of integers such that the rows are all adjacent in memory.
Also, a pointer to a 10-element array of integers is not compatible with a pointer to an 11-element array of integers, making it more difficult to write functions that can work with pointers to arrays of different sizes. IOW, if you have a function declared as
void bar( integers (*foo)[10] ) { ... }
it can only work with Nx10 arrays of integers. There are ways around this that involve varying levels of pain, but that's a topic for another day.

Why does my homespun sizeof operator need a char* cast?

Below is the program to find the size of a structure without using sizeof operator:
struct MyStruct
{
int i;
int j;
};
int main()
{
struct MyStruct *p=0;
int size = ((char*)(p+1))-((char*)p);
printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);
return 0;
}
Why is typecasting to char * required?
If I don't use the char* pointer, the output is 1 - why?
Because pointer arithmetic works in units of the type pointed to. For example:
int* p_num = malloc(10 * sizeof(int));
int* p_num2 = p_num + 5;
Here, p_num2 does not point five bytes beyond p_num, it points five integers beyond p_num. If on your machine an integer is four bytes wide, the address stored in p_num2 will be twenty bytes beyond that stored in p_num. The reason for this is mainly so that pointers can be indexed like arrays. p_num[5] is exactly equivalent to *(p_num + 5), so it wouldn't make sense for pointer arithmetic to always work in bytes, otherwise p_num[5] would give you some data that started in the middle of the second integer, rather than giving you the sixth integer as you would expect.
In order to move a specific number of bytes beyond a pointer, you need to cast the pointer to point to a type that is guaranteed to be exactly 1 byte wide (a char).
Also, you have an error here:
printf("\nSIZE : [%d]\nSIZE : [%d]\n", size);
You have two format specifiers but only one argument after the format string.
If I don't use the char* pointer, the output is 1 - WHY?
Because operator- obeys the same pointer arithmetic rules that operator+ does. You incremented the sizeof(MyStruct) when you added one to the pointer, but without the cast you are dividing the byte difference by sizeof(MyStruct) in the operator- for pointers.
Why not use the built in sizeof() operator?
Because you want the size of your struct in bytes. And pointer arithmetics implicitly uses type sizes.
int* p;
p + 5; // this is implicitly p + 5 * sizeof(int)
By casting to char* you circumvent this behavior.
Pointer arithmetic is defined in terms of the size of the type of the pointer. This is what allows (for example) the equivalence between pointer arithmetic and array subscripting -- *(ptr+n) is equivalent to ptr[n]. When you subtract two pointers, you get the difference as the number of items they're pointing at. The cast to pointer to char means that it tells you the number of chars between those addresses. Since C makes char and byte essentially equivalent (i.e. a byte is the storage necessary for one char) that's also the number of bytes occupied by the first item.

Resources