A doubt about sizeof - c++

I was trying to do something using sizeof operator in c++.
Please refer to the following code snippet.
http://ideone.com//HgGYB
#include <iostream>
using namespace std;
int main()
{
int *pint = new int[5];
int temp = sizeof(*pint);
cout << "Size of the int array is " << temp << endl;
return 0;
}
I was expecting the output as 5*4 = 20. Surprisingly it comes to 4. Any ideas ?

Here is pint is an int*. So,
sizeof(*pint) == sizeof(int)
Compiler doesn't know about new int[5], when it does sizeof(*pint) (because sizeof() is a compile time operator).
[Note: Try the same test with statically declared array, int pint[5]; and will see the expected result.
Additionally, sizeof() returns size_t (which is an unsigned value), so it should be:
size_t temp = sizeof(...);
]

Dynamically sized arrays lose their size information- the size is only the size of one integer, as pint is a pointer to int, and *pint is an integer, not an array type of any size.

There is no way for C++ to know the size of the array.
In your case,
*pint
returns an int, and sizeof(int) is 4 on your machine.

All fine. You ask for the size of an int which will be 4 bytes.

pint is a pointer to int that just happens to point to the beginning of an array. It contains no information about this array.

It is giving you the size of what the pointer points to - the first location in the array.

In the current case sizeof(*pint) is giving the sizeof(int), so its returning 4 . But, even if you will try sizeof(pint), it will return you the size of a pointer. Which will most probably be 4 if yours is a 32 bit machine else it will be 8, if 64 bit machine.
Now you have asked, why it is not returning 4*5 = 20. Since pint points to an integer array. Yes, pint points to an integer array, but its not an array. The difference is :
Array have a fixed size. you can redectare it at all. While pointers can point to any object of any size.
Since sizeof operator is evaluated at compile time, so compiler dont have any way to know at which size of array this pointer is pointing and so cant tell the size of that object and so it always return only the size of pointer. now you can understand, why in case of pointers compiler gives size of the pointer (ie space occupied by pointer in memory), but in case of array it gives full size.

Related

C++ error in malloc

I am new to C/C++ and trying to test my understanding of pointers. For this I created the following simple program to create an integer array to store 10 numbers and print it out.
#include<iostream>
#include <cstdlib>
// #include <cstdint>
int main(){
int numberOfItems = 10;
int *array;
// int *array = malloc((int*)numberOfItems*sizeof(int));
array = malloc((int*)numberOfItems*sizeof(int));
for(int i=0;i<numberOfItems;i++){
*array = i;
array++;
i++;
}
std::cout<<"The size of the array is : "<<sizeof(array)<<std::endl;
for(int i=0;i<numberOfItems;i++){
std::cout<<*array<<std::endl;
array++;
i++;
}
return 0;
}
I ran the program using the command g++ main.cpp.
But it gives me the following error:
main.cpp:8:47: error: invalid operands of types ‘int*’ and ‘long unsigned int’ to binary ‘operator*’
array = malloc((int*)numberOfItems*sizeof(int));
Tried and Failed
I tried to change the int to uint64_t but still it gave me similar kind of error.
I do not understand what I am doing wrong.
The error is due to the fact that your syntax is incorrect in the following line.
array = malloc((int*)numberOfItems*sizeof(int));
The right syntax would be as follows:
array = (int*) malloc(numberOfItems*sizeof(int));
You need to typecast the return value of malloc as it returns a (void *) pointer. So, you need to specify what type of data you would be pointing when you access the memory.
Let's go through your code step by step:
int *array;
array = malloc((int*)numberOfItems*sizeof(int));
Here you have two problems:
malloc is C, not C++. Yes, malloc is supported in C++, but for backwawrds compatibility with legacy code. Do not use it.
You cast numberOfItems to a pointer, then multiply the pointer with an integer. That's undefined behavior. Your compiler might even do the right thing here, but you cannot know and you cannot trust any result you're getting.
Let's continue:
for(int i=0;i<numberOfItems;i++){
*array = i;
array++;
i++;
}
The for declaration looks fine. You initialize an integer i to 0, and you increment it using the ++ operator as long as it is smaller than numberOfItems, that's good. But:
You increment i again inside your loop. That means you actually increment i by 2, so i goes 0, 2, 4, 6, 8, 10, and your loop is only executed 5 times.
You increment your array pointer. While technically perfectly valid code, this will bite you further down.
So you write the values 0, 2, 4, 6 and 8 into memory at the initial location of your array pointer, and 1*sizeof(int), 2*sizeof(int), 3*sizeof(int), 4*sizeof(int) bytes further down each.
Next problem:
std::cout<<"The size of the array is : "<<sizeof(array)<<std::endl;
This will not print what you meant it to print. array is a pointer type, so sizeof(array) will return the size of a pointer, which is probably either 4 or 8 bytes depending on the bitnes of your application/OS.
And last but not least your last loop:
for(int i=0;i<numberOfItems;i++){
std::cout<<*array<<std::endl;
array++;
i++;
}
You do the same thing with i as in your first loop. This time, this saves your neck, because...
...since you incremented the pointer array already in your first loop, you're now continuing at 5*sizeof(int) bytes further down in the memory. You're therefore not printing the values you set in the first loop (which was probably your intention), but uninitialized values that reside in the second half of the memory originally allocated at array.

Why does this yield different values on using sizeof operator? [duplicate]

This question already has answers here:
Why isn't the size of an array parameter the same as within main?
(13 answers)
Closed 7 years ago.
#include <iostream>
using namespace std;
int main (void)
{
int * p = new int(40); // here `p` points to an array having space for 40 ints or space allocated is 40 bytes?
for (int i = 0; i < 2; i++)
cin>>p[i];
cout<<sizeof(p)<<"\n"; // here, the output should be size of array since p points to an array
int arr[5] = {1,2,3,4,5}; // since, here it will output 20 (space allocated for the entire array)
cout<<sizeof(arr)<<"\n";
return 0;
}
So, I have two questions (the first two comments in the program)
Here p points to an array having space for 40 ints or space allocated is 40 bytes?
Here, the output should be size of array since p points to an array because technically speaking, arr is also a pointer and when we do *arr it references to the first element of the array.
In your code, p is defined as a pointer, so sizeof(p) is the same as sizeof(int*), with is 4 on 32bit systems and 8 on 64bit systems.
In the second case, arr is a static array, so sizeof(arr) is the same as sizeof(int[5]) which returns 5*sizeof(int), assuming there's no padding or other complex work happening "under the hood".
Note that when you pass an array name as an argument to a function which accepts a pointer as a formal function parameter, the array "decays" to a pointer, so calling sizeof on an argument yields behavior you likely did not expect. For example:
Code Listing
#include <stdio.h>
void printSize(int* arg);
int main(void)
{
int *p;
int arr[10];
printf("sizeof p:%d\n", sizeof(p));
printf("sizeof arr:%d\n", sizeof(arr));
printSize(p);
printSize(arr);
return 0;
}
void printSize(int* arg)
{
printf("sizeof arg:%d\n", sizeof(arg));
}
Sample Output
sizeof p:8
sizeof arr:40
sizeof arg:8
sizeof arg:8
When you say int *p = new int(40); you are actually allocating space for a single integer and filling that space with the integer 40. If you want an array of 40 integers, you should use square brackets:
int *p = new int[40];
So, to answer question #1: neither. The space allocated is the size of one int on your system.
To answer question #2: the first line of output is the size of a single pointer on your system (because p is just a pointer). This will probably be the same as the size of an int, which is likely 4 bytes. The second line of output will be the total allocation size of your array of integers, so it will be 40*sizeof(int), or 160.
Your two uses of sizeof are querying the size of the types int* and int[5] respectively.
(also, you have a bug and meant new int[40], not new int(40), but that doesn't affect the results of sizeof)

How does this pointer typecasting work?

Can anyone please explain how the following code works? I wish to know what is exactly the value returned to variable p and how?
#define MR 3
#define MC 4
int (*p)[MC];
p=(int(*)[MC])malloc(MR*sizeof(*p));
Thanks in advance.
From top to bottom (noting MC 4 and MR 3)
int (*p)[MC];
declares p as a pointer to an array of 4 int.
sizeof(*p)
size of an array of 4 int
MR*sizeof(*p)
3 * (size of an array of 4 int), i.e. 12 contiguous int values.
Finally, the cast:
p=(int(*)[MC])malloc(MR*sizeof(*p));
is simply forcing the underlying void* returned by malloc tothe pointer-type that of the lvalue of the assignment, the pointer p.
In the end, this dynamically allocates an array (dim=3) of arrays (dim=4) of int, in a single dynamic contiguous block of memory. Were this allocated as an automatic variable it would be equivalent to:
int p[MR][MC]
And since you asked how it works. poorly. This is C++. It should be done as:
std::vector<std::array<int,MC>> ar(MR);
p is a variable of type "pointer to int array of size MC". sizeof(*p) is the size of MC ints. Effectively, p is now the pointer to a 2D array with MR rows and MC columns.

sizeof operator and multidimensional table

I've got a problem because i dont know how sizeof operator works. Could anyone tell me why it gives me 4 in below code?
int tab[2] = {1, 5};
int *filePathTab[1] = {NULL};
filePathTab[0] = tab;
cout << sizeof(filePathTab[0]);
filePathTab[0] has a int * as its element. The sizeof an int * on your machine is 4 bytes. If you want to know the sizeof what the int * is pointing to, an int, you have to dereference the pointer:
cout << sizeof(*filePathTab[0]);
It may turn out that the sizeof an int on your machine is also 4 bytes.
Because filePathTab[0] is of type int* (filePathTab is an array of pointers, you are considering the zeroth element) and the size of a pointer to int on your machine happens to be 4 bytes.
Sizeof gives you the size of the argument in bytes. Since pointers to int are 4 bytes long (this depends on the system), the output of sizeof is 4.

What does (int **array;) create?

I want to know what is happening in memory when you declare:
int **array;
If I am not mistaken...
You have a multidimensional array arr[i][j] and
**arr addresses to arr[0][0]
*((*arr)+1) addresses to arr[0][1]
*(*(arr+1)+1) addresses to arr[1][1]
Sample code in C++
#include <iostream>
using namespace std;
int main()
{
int **arr;
arr = new int*[5];
for(int i = 0; i < 5; i++)
arr[i] = new int[5];
arr[0][1] = 1;
cout << *((*arr)+1); // prints 1
cout << arr[0][1] = 1; // prints 1
}
It creates a variable to store a pointer to an int pointer.
The compiler reserves four bytes (on a 32bit system, eight bytes on 64bit) to store a pointer (that would point to another pointer, that would point to an int). No further memory allocation is done, it is left to the programmer to actually set the pointer to point to some other memory location where the int*/array/... is stored.
You're declaring a pointer variable, so you're allocating enough space for one memory address (depends on your platform/compiler/etc.)
The type system will ensure that the only addresses you assign into it contain other memory addresses, and that these addresses represent the actual address of an integer variable.
To use your pointer-to-pointer, you dereference it once (to get the address that actually points to the integer), and then a second time (to get the actual integer).
You can bypass the type system by explicitly casting to something else (e.g., i=&pDouble) but that is not recommended unless you're sure you know what you're doing.
If you have a two-dimensional array, you can think of it conceptually as one single-dimensional array of single-dimensional arrays representing rows. The first level of indirection would be to pick the row, and the other one to pick the cell in the row.
It's a pointer to an int pointer. This is often used to declare a 2D array, in which case each int pointer is an array and the double pointer is an array of arrays.