0

I have noticed that pointers are 4 bytes while ints are 2 bytes. When I make a declaration such as:

int * myGreatArray[50];

am I declaring an array of 50 pointers to ints? I thought I was declaring a pointer to an array of integers, which is functionally the same as

int ** myGreatArray = malloc(50 * sizeof(int *));

However, I was informed by this tutorial that such a declaration is actually creating an array of pointers to ints, which seems more inefficient than just simply storing the ints themselves.

https://www.tutorialspoint.com/cprogramming/c_array_of_pointers.htm

Can anyone clarify this for me?

8
  • 2
    Check out cdecl.org. It's a tool that explains C declarations in English. Commented Jun 22, 2017 at 11:29
  • 2
    How do you define efficiency? You also forget that each pointer in any individual array cell can hold the address of an entire buffer. Commented Jun 22, 2017 at 11:30
  • 2
    Small nit - sizes of pointers and ints vary across platforms Commented Jun 22, 2017 at 11:31
  • 2
    int** is not a pointer to an array. It is a pointer to a pointer to an int. BTW, in the malloc, you mean sizeof(int*) instead of sizeof(int), right? Commented Jun 22, 2017 at 11:33
  • 2
    am I declaring an array of 50 pointers to ints? Yes. Commented Jun 22, 2017 at 11:35

5 Answers 5

3

It is a question of precedence of operators.

int * myGreatArray[50]; // array of 50 pointers to int
int (*ptArray)[50];     // pointer to array of 50 ints
Sign up to request clarification or add additional context in comments.

1 Comment

This is exactly what I was hoping I'd discover, so when passing an array into a function, is it more efficient to pass a pointer to an array as opposed to an array of pointers? I'd think yes.
2
int * myGreatArray[50];

is indeed creating an array of pointers to int. If you wanted a pointer to an array of int, it would be written as

int (*myGreatArray)[50];

However, I was informed by this tutorial that such a declaration is actually creating an array of pointers to ints, which seems more inefficient than just simply storing the ints themselves.

Depends on what you are trying to do. It's useful for creating "jagged" 2D arrays, where each "row" can be a different length:

for ( size_t i = 0; i < 50; i++ )
  myGreatArray[i] = malloc( sizeof *myGreatArray[i] * some_length(i) );

where some_length(i) represents the number of elements for a particular "row". It can also be used to point to existing arrays:

int foo[] = {1, 2, 3};
int bar[] = {4, 5, 6, 7, 8};
...
int *myGreatArray[] = {foo, bar, ...};

Comments

1

When you are writing this declaration:

int * myGreatArray[50];

its the same as writing -

int ** myGreatArray = malloc(50 * sizeof(int *));

and you will get an array of 50 pointers to int, while if you will use this line:

int myGreatArray[50];

or:

int* myGreatArray = (int*)malloc(sizeof(int)*50)

you will get an array of 50 int variables. I hope that my comment was helpful for you :D and if you still have questions ask and i will answer you ASAP. Have a great day ;)

1 Comment

When I wrote int** myGreatArray = malloc(50*sizeof(int*)); it should have been int** myGreatArray=(int**)malloc(50*sizeof(int*));
1

Declaring an array:

int * myGreatArray[50];

This is an array that stores 50 pointers to int. Be aware that it does not allocate the storage for those integers, just for the storage of the pointers.

int arr[50];       //array of 50 integers
int * parr = arr;  /*pointer to an int, which may be
                     the beginning of an array*/

Passing to a function:

This is exactly what I was hoping I'd discover, so when passing an array into a function, is it more efficient to pass a pointer to an array as opposed to an array of pointers? I'd think yes. – Michael Hackman

The two function definitions:

void doStuffToArray(int ** array, size_t len)
{
  //dostuff
}

and

void doStuffToArray(int * array[], size_t len)
{
  //dostuff
}

are functionally identical. When you pass an array, the function actually receives a pointer to the array.

To call the functions, you can pass the array (devolves to pointer to the beginning of the array, (recommended) or a pointer to the beginning of the array (not recommended for full arrays, but is useful to pass pointers to sections of arrays):

int arr[10] = {};
doStuffToArray(arr,     sizeof(arr)/sizeof(arr[0])); //functionally identical
doStuffToArray(&arr[0], sizeof(arr)/sizeof(arr[0])); //functionally identical

When passing an array of pointers, there are two function definitions that can be used, e.g. argv is an array of pointers to char arrays:

int main(int argc, char * argv[]){return 0;} //functionally identical
int main(int argc, char ** argv ){return 0;} //functionally identical

My advice is to use the array notation (with the []) as this is a declaration of intent, instead of the equivalent but more ambiguous pointer notation.

If you know how big the array is, then argv could have been defined as an 'array of arrays' char argv[][] which would be great, but can't be done. When defining a function, only the first array dimension can be undefined, any further dimensions have to be defined. If you know how big it is though, there is nothing to stop you from creating a function:

void doStuffToMyArray( int array[][10]){
    /*...*/
}

Comments

0

In fact in this call

malloc(50 * sizeof(int));

there is allocated neither array.:) There is allocated an extent of memory. You can interpret it in various ways.

For example you can write

int *myGreatArray =  malloc(50 * sizeof(int));

char *myGreatArray =  malloc(50 * sizeof(int));

or even like

long *myGreatArray =  malloc(50 * sizeof(int));

provided that sizeof( long ) is equal to 2 * sizeof( int ).

or like

int ( *myGreatArray )[50] =  malloc(50 * sizeof(int));

The only requirement is that there was allocated enough memory for the object(s) you are going to store there.

If you want to allocate dynamically an extent of memory for an array similar to this declaration

int * myGreatArray[50];

then you should write

int ** myGreatArray = malloc(50 * sizeof(int *));
^^^^^^                                   ^^^^^

If you want to allocate dynamically an extent of memory for an array similar to this declaration

int myGreatArray[50];

that is an array of 50 objects of type int then you should write

int * myGreatArray = malloc(50 * sizeof(int));
^^^^^                                   ^^^^^

11 Comments

char *myGreatArray = malloc(50 * sizeof(int)); ? Really?
@Baldrickk It is a valid statement. The function malloc only allocates an extent of memory of the specified size. It knows nothing about what object of what type will occupy the memory.
Sure, but this will (probably) allocate 4* as much as you need.
Ok, If I were to build a car park that is only ever meant to hold up to 50 cars. Nothing else, and no more, then I would want to build a car park large enough for those 50 cars. If instead I were to build it large enough for 50 articulated lorries, then the car park would be bigger than needed - lorries take up a lot more space than cars. If I were to put up to 50 cars in the lorry park, then there would be excess unused space that would be wasted, and in order to build it, I would have to buy more land than the smaller car park wold need.
It's the same with memory, if you want to store 50 chars, and create an array with enough space for 50 ints, the array is bigger than is needed (and an int typically takes four times as many bits, so that's quite a big difference). Also, now I look again; there is a greater sin: long *myGreatArray = malloc(50 * sizeof(int)); long is, on some sytems bigger than int. If you try and store 50 long values in there, you are going to index outside of the array.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.