2

I'm learning about dynamic memory at the moment, but my book is not clear about this. Why does the declaration of the dynArray doesn't not have the [ ] brackets which is used for array declaration when not using malloc. Why is the [ ] not needed when declaring, but needed in the loop.

int * dynArray;
dynArray = malloc(sizeof(int)*5);
srand ( time(NULL) );

for(i=0; i<=myInt; i++){
    dynArray[i] = rand()%100;
  }
Engineer2021
  • 3,288
  • 6
  • 29
  • 51
user3753834
  • 277
  • 2
  • 5
  • 11
  • possible duplicate of [What is the difference between square bracket arrays and pointer arrays?](http://stackoverflow.com/questions/9324995/what-is-the-difference-between-square-bracket-arrays-and-pointer-arrays) – Engineer2021 Jul 18 '14 at 15:35
  • See the C FAQ Section 6: [Arrays and Pointers](http://www.c-faq.com/aryptr/) to understand what a pointer is, and how arrays and pointers are [similar](http://www.c-faq.com/aryptr/aryptrparam.html) yet [different](http://www.c-faq.com/aryptr/aryptr2.html). – mctylr Jul 18 '14 at 17:03

3 Answers3

2

It is not needed in the loop; pointers can be accessed as arrays and arrays can be accessed as pointers

This is equivalent

for(i=0; i<=myInt; i++){
    *(dynArray+i) = rand()%100;
}
abasterfield
  • 2,214
  • 12
  • 17
  • Why is the number of items in that array not needed during deceleration? – user3753834 Jul 18 '14 at 15:23
  • @user3753834 because it is not an "array" _yet_. It's a pointer. You then make it point to an actual array (allocated by `malloc()`). The difference between array and pointer does not fade until indexing : arrays and pointers can be indexed identically. – Quentin Jul 18 '14 at 15:26
  • 1
    Your malloc() returns a pointer to some memory with space for 5 ints in it. You can then access those elements with array notation. – abasterfield Jul 18 '14 at 15:26
  • @user3753834 You accepted the wrong answer. It is certainly true that you can use `[]` and `+` interchangeably, but to shun the use of `[]` merely makes your code hard to follow. No sane programmer chooses `*(arr+i)` over `arr[i]`. – David Heffernan Aug 08 '14 at 14:59
  • @DavidHeffernan what makes pointer arithmetic any harder or easier to follow than array notation? Consistency is the key. Some real examples http://livegrep.com/search/linux?q=pointer+arithmetic – abasterfield Aug 10 '14 at 12:12
  • On top of the poor advice, you did not answer the question that was asked. – David Heffernan Aug 10 '14 at 12:20
  • Possibly I have not been clear; my answer to this question is that in the example provided by the OP the pointer is being iterated using array notation. My example code shows alternatively the pointer can also be iterated with pointer arithmetic. To counter your declaration that any programmer who uses pointer arithmetic is insane I provided examples of such code in the Linux kernel. – abasterfield Aug 10 '14 at 12:57
1

The difference is in when its address is known.

For a simple int a[5] array, the compiler knows where it is, so its address is constant (or stack- or struct-relative, which is the same thing).

OTOH int* a means a is just a variable, not a constant, that happens to point to one or more int. The running program can do its own allocation and set a, and it's up to the programmer to know what he/she is doing.

But indexing a[i] works the same in either case. It takes a as the address of the array, then adds to it i times the size of an int, and that's the address of the actual integer.

Mike Dunlavey
  • 40,059
  • 14
  • 91
  • 135
1

This defines an array of a certain size:

int array1[10];

This defines a pointer to integer:

int * array2;

Both definitions allocate some memory. The first one allocates space to hold 10 ints. The second one allocates space to hold a pointer to integer.

When the array1 is used in an expression as an rvalue, it degenerates to a pointer. So using array1 rvalue is equivalent to taking its address: &array1. In an expression, array1 and array2 rvalues are equivalent: they act as pointer-to-int values. The difference is that you can't use array1 as an lvalue: you can't assign to it, and you can't modify it - because it's not a pointer you can write to. You can certainly, of course, modify the values pointed-to by either array1-acting-as-a-pointer, or by array2.

Both definitions above give you uninitialized variables: the contents of array1 are not defined, neither are the contents of array2. So, for example, it'd be an error to dereference the array2 pointer before a value was assigned to it.

You can set array2 to the address of the 10 integer-long area allocated in array1, and both are then equivalent:

int array1[10];
int * array2 = array1;
array1[0] = 1;
array2[0] ++; // Increment the first item of the array
assert(array1[0] == 2);

But while you can certainly make array2 point to the second item in the first array, you can't change where array1 points to:

array2 ++; // Increment the pointer so that it points to the second item of the array
assert(array2 == &array1[1]);

array1 ++; // Triggers a compile-time error diagnostic

The assert, from #include <assert.h>, is simply a way to assert certain facts. If they prove false at runtime, the program will abort. It's also a way to succinctly express, in the C language, that certain things are true at certain points in the program. It's better than writing comments, since the assertion will be checked for you in a debug build, at runtime.

Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313