sizeof() + arrays

Let's say we have "array a[] = {1,2,3,4,5};".

If in the main method, we use sizeof() on a, we get 20 bytes.

I made the sizeof() into a method outside of the main method and called it from inside the main method. I tried to just pass the array to the method outside and then find the sizeof() it, but it seems to only return the size of the first index and not the whole thing. I tried using arrays and pointers. Is there a way?
No.

The difference is:
1
2
int a[5]; //a is of type 'int array' and has a size of 5*sizeof(int)
int b[] = a; //b is of type 'pointer to int' and has a size of sizeof(int*) 
Unfortunately you have to pass the size of the array to the function or use a global constant.
Last edited on
Not sure why what you said was a pointer... I don't see a pointer being declared or initialized. Kind of confusing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
using namespace std;

int arraySize(int array[]){
    cout << sizeof(array) << endl;
    int aSize = sizeof(array);
    int iSize = sizeof(int);
    int size = aSize/iSize;
    cout << aSize << " - " << iSize << " - " << size << endl;
    return size;
}

int main(){

    int c[] = {1,2,3,4,5,6,7,8,9};
    cout << sizeof(c) << endl; //Prints out 36
    arraySize(c); //Prints out 4, how can we pass the array and make it find the whole size?

/*
   int *d;
   d = c;
   arraySize(c); //Prints out 4, I under stand why, but is it possible to find the whole size?
*/


    return 0;
}

Can you explain that the array part(outside of comment) and the pointer part(inside of comments)?
When you pass int[] to a function, it (as LB said) passes a pointer to an integer, not the whole array. You need to pass the size of the array as a separate parameter to the function.
> I don't see a pointer being declared or initialized. Kind of confusing.

There are two different, orthogonal, concepts involved here and the confusion might be because both are in play together. Understanding each one separately on its own, before trying to understand the interplay between the two might alleviate the confusion.

1. A parameter may be passed by value or passed by reference to a function.
http://www-cs-students.stanford.edu/~sjac/c-to-cpp-info/references

1
2
3
4
5
6
7
8
9
void passed_by_reference( double& arg ) ; // arg is passed by reference

void passed_by_value( double arg ) ; // arg is a double passed by value

// if we call this function like this:

int i = 98 ; // 'i' is an int
passed_by_value(i) ; // what is required here is the value of a double
// the int 'i' is implicitly converted to a double, and arg is initialized with the result of the conversion 



2. An array, when used in the context of a value (used where a value is required) decays to (is implicitly converted to) a pointer to the first element in the array.


Now let us put these two together: An array passed by value to a function is used in the context of a value; it is therefore implicitly converted to a pointer to its first element.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <iostream>

enum { N = 16 } ;

// array_type is an alias (another name) for: an array of 16 objects of type double
typedef double array_type[N] ;

void foo( array_type& arg ) // arg is passed by reference
{
    // the type of arg is: reference to an array of 16 objects of type double
    // prints 16 * sizeof(double)
    std::cout << "foo - sizeof(arg) == " << sizeof(arg) << '\n' ;
}

void bar( array_type arg ) // arg is passed by value
{
    // when bar is called with the actual parameter being an array of double,
    // the array is used in the context of a value;
    // it decays to a pointer to the first double in the array;
    // the type of arg is: pointer to double
    // prints size of pointer to double
    std::cout << "bar - sizeof(arg) == " << sizeof(arg) << '\n' ;
}

int main( int argc, char* argv[] )
{
    array_type a ; // 'a' is an array containing 16 doubles

    std::cout << sizeof(a) << '\n' ; // prints 16 * sizeof(double)

    // here, the array 'a' (in expression '+a') is used in the context of a value
    // it decays to a pointer to double having the value &(a[0])
    std::cout << sizeof( + a ) << '\n' ;  // prints size of pointer to double

    // here, 'b' is initialized with the value of 'a'
    // because 'a' is used in the context of a value, the array decays
    // to a pointer to the first object in the array; &(a[0])
    auto b = a ; // type of 'b' is pointer to double
    std::cout << sizeof(b) << '\n' ;  // prints size of pointer to double

    foo(a) ; // the array 'a' is passed by reference; foo gets a reference to 'a'
    // prints: foo - sizeof(arg) ==  size of array 'a' ( 16 * sizeof(double) )

    bar(a) ; // the array 'a' is passed by value; bar gets a copy of the value
    // because 'a' is used in the context of a value, the array decays
    // to a pointer to the first object in the array; &(a[0])
    // prints: bar - sizeof(arg) ==  size of pointer to double
}


Based on what I read,
1
2
3
4
void abc(int a[]){} //Pointer to the first element in the array is passed

void bcd(int &a){} //Reference of the array, does that mean the whole array is passed?
// or would it be void bcd(int &a[]){} - added the [] after a 


Is the above correct?
Last edited on
No, function bcd takes a reference to a single integer.
Last edited on
sing integer?

Still not understanding it... Can you say which part is right or wrong?
Sorry, I meant "single integer".
If abc is a pointer to the first element, can you make the pointer point to a different element in the array within that function or is it the pointer being passed only contains that one element? Basically, does it get passed a pointer to the first element of the array with access to the whole array or does it get passed a pointer to the first element of the array with only access to the first element?

Lets say, we have an array:
[10] [20] [30] [40] [50] <--- array of 5 indexes with the values insides
170 174 178 182 186 <--- address of each element in the array
Since, bcd gets pass the reference(address) of a single integer, will it be passed 170 since it is the first element in the array?

Is void bcd(int &a[]) valid?
> void abc( int arg[] ){} //Pointer to the first element in the array is passed

Type of arg is a pointer to an int (which can be a pointer to the first element in an array of int). abc could equivalently be declared as void abc( int* arg ) ;. Or equivalently as void abc( int arg[999] ) ; - the 999 is simply ignored; an array when used in a value context decays to a pointer to the first element, and the function takes arg by value.


> void bcd( int& arg ){}

Type of arg is a reference to int (a single int, not an array of int)


void cde( int (&arg)[15] ){}

Type of arg is a reference to an array of int which has 15 elements ( int[15] )


void def( int (&arg)[132] ){}

Type of arg is a reference to an array of int which has 132 elements ( int[132] )


void efg( int (*arg)[132] ){}

Type of arg is a pointer to an array of int which has 132 elements.


The number of elements in an array is part of the type of the array


EDIT:
> If abc is a pointer to the first element, can you make the pointer point to a different element in the array within that function

Yes, If p is a pointer to the first element, ++p would make p point to the second element. p[20] is well defined if the array has at least 21 elements and would yield a reference to the element at position 20.


> Is void bcd(int &a[]) valid?

No. Arrays of references are not allowed.

Because an array, when used in a value context, decays to a pointer to (the address of) its first element; and the address of a reference is something that simply does not exist.

Conceptually, a reference does not have a location in memory - it is an abstract alias for some object somewhere in memory. Pass-by-reference in C++ (or for that matter in any language that has the notion of a reference) does not conceptually mean 'pass a reference by value' as a thread in the Lounge seems to suggest - but then, that is the Lounge. Try to take the address of a reference and we get the address of another object; try to take the value of a reference and we get the value of another object.


void bcd( int (&a)[] ) is also incorrect; the number of elements in an array must be specified (constexpr)

Last edited on
Thanks for taking your time to write this. This helped a lot in understanding it. A few things I wanted to clarify.

----------

void abc( int arg[] ){}
Passed a pointer pointing to first element for the array.
Allowed to move to any elements.

void bcd( int& arg ){}
Passed a pointer pointing to the address of the arg.
Anything else we can do with this?

----------

void efg( int (*arg)[132] ){}
Passed a pointer pointing to the whole array?
Can we use the function int xyz[] = arg; to store the array given into a xyz variable?


void cde( int (&arg)[15] ){} and void def( int (&arg)[132] ){}
Passed the address of the whole array or the block of memory being used for the array? Which address would it be passed, since each element in the array has its own address?

----------
> void abc( int arg[] ){}
> Passed a pointer pointing to first element for the array.

Passed a pointer to int. Period. It may be a pointer to any int anywhere, or it may be a nullptr.
1
2
3
4
5
6
7
8
[code]void abc( int arg[] ){}

// ...
int i = 89 ;
int a[] = { 1, 2, 3 } ;
abc( &i ) ; // pointer to int 'i'
abc( a ) ; // pointer to first element of 'a'
abc( nullptr ) ; // does not point to any object 


> Allowed to move to any elements.

Yes. Provided the pointer actually points to an element in an array.



> void bcd( int& arg ){}
> Passed a pointer pointing to the address of the arg.

Passed an alias for an integer. Do not - repeat DO NOT, repeat DO NOT - think of a reference as 'a pointer that is automagically dereferenced'.

> Anything else we can do with this?

It is an alias for an int. You can do anything with it that you can do with the int it refers to; whatever you do with it would be done on the int that it is an alias for. You could assign a value to the int, you could take the adress of that int, you could compare that int with another int, and so on.



> void efg( int (*arg)[132] ){}
Passed a pointer pointing to the whole array?

Yes.

> Can we use the function int xyz[] = arg; to store the array given into a xyz variable?

No. arg is a pointer to an array; it is not an array; and it is not a pointer to the first element of the array. You can store its value in another pointer to an array.
1
2
3
4
void efg( int (*arg)[132] )
{
    int(*xyz)[132] = arg ;
}



> void cde( int (&arg)[15] ){} and void def( int (&arg)[132] ){}
> Passed the address of the whole array or the block of memory being used for the array?

No. NO. NO. Passed an alias for an array.
You could do anything using the alias that could be done on the array for which it is an alias.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
int a = 89 ;
int* p = &a ; // p is a 'pointer to int'; it holds an adress 
int& r = a ; // r is a 'reference to int'; it is an alias for i (another name by which i can be refereed to)

// the value of 'p' is an address; the address of 'p' &p is the address of the pointer - 
// a 'pointer to a pointer to an int'.

// 'r' does not have either an address or a value of its own 
// address of 'r' &r would yield the address of 'i' &i. it is a 'pointer to int - 'r' is an alias for 'i'

// the value of 'r' would yield the value of 'i';  'r' is an alias for 'i'
int j = r ; // equivalent to int j = i ; 
r = 4567 ; // equivalent to i = 4567 ;
// conceptually, whenever and where ever you use 'r' after its initialization, 
// the implementation would substitute 'i' in the place of 'r'  



I think I will just give up on understanding this because I seem to get more and more confused...

I will just leave it to when I actually need it.

Thanks for trying anyways.
Last edited on
Topic archived. No new replies allowed.