I don't understand how pointer-pointsArray changed from a pointer to a
pointer array in the above for loop. I have knowledge on rvalue and
Ivalue in variable. I would appreciate if you may include these
concept in the answer.
- At what line did pointsArray become a pointer array? pointsArray = (int *) malloc(howMany * sizeof(int)); should only increase the memory
size of pointsArray.
First, let's start with the basics. A pointer is not an array, and an array is not a pointer, they are two separate types in C. An array type is converted to a pointer to the first element of the array on access as provided in C11 Standard - 6.3.2.1 Lvalues, arrays, and function designators(p3)
int * pointsArray;
...
pointsArray = (int *) malloc(howMany * sizeof(int));
What is pointsArray
? (it is a pointer to type int
).
Well, What is a Pointer?
A pointer is simply a normal variable that holds the address of something else as its value. In other words, a pointer points to the address where something else can be found. Where you normally think of a variable holding an immediate values, such as int a = 5;
, a pointer would simply hold the address where 5
is stored in memory, e.g. int *b = &a;
declares b
as a pointer to type int
and initializes its value to the address where 5
is stored in memory (e.g. b
points to a
-- where 5
is currently stored). It works the same way regardless what type of object the pointer points to.
Pointer arithmetic will work the same for all pointers regardless of the type because the type
of the pointer controls the pointer arithmetic, e.g. with a char *
pointer, pointer+1
points to the next byte after pointer
. For an int *
pointer (normal 4-byte integer), pointer+1
will point to the next integer at an offset 4-bytes after pointer
. (so a pointer, is just a pointer.... where arithmetic is automatically handled by the type
)
- At what line did pointsArray become a pointer array? pointsArray = (int *) malloc(howMany * sizeof(int)); should only increase the memory
size of pointsArray.
Recall, "a pointer is not an array and an array is not a pointer." An array is declared either with:
type name[CONST]; /* declares an array of type with CONST elements */
type name[var]; /* declares a VLA C99+ with var no. of elements */
type name[] = { 1, 2, 3 }; /* declares & initializes an array of 3 elements */
Constrast with:
type *name; /* declares a pointer to type */
In the case of an array with a constant number of elements or with an initialization list, automatic-storage is provided for the array. Storage for the variable-length array (VLA) is similar but within another segment (generally within .bss [block stated by symbol]). On access (except when "it is the operand of the sizeof
operator, the _Alignof
operator, or the unary &
operator, or is a string literal used to initialize an array") an array is converted pointer to type that points to the initial element of the array object and is not an lvalue. 6.3.2.1(p3) (You will often see the phrase an "Array decays to a pointer" -- which is referring to this conversion)
(Note: it does not work in reverse, a pointer is never converted to an array)
The declaration type *name;
declares name
as a pointer to type
. It is uninitialized and it holds an indeterminate address. Any attempt to access or otherwise make use of an uninitialized pointer invokes Undefined Behavior (frequently leading to a Segmentation Fault). The pointer must hold a valid address (e.g. it must point to valid storage) before you can access the memory. The easiest way to provide valid storage for a pointer is to dynamically allocate a block of memory and assign the starting address for the block to the pointer. This is done in your code with:
pointsArray = (int *) malloc(howMany * sizeof(int));
(note: there is no need to cast the return of malloc
, it is unnecessary. See: Do I cast the result of malloc?)
A better approach would be:
pointsArray = malloc (howMany * sizeof *pointsArray);
(pointsArray
is type int*
, so *pointsArray
is type int
. If you use the derefernced pointer as your type-size, you will eliminate the potential for type-size error)
Above, malloc
reserves a valid block of memory guaranteed to be at least howMany * sizeof *pointsArray
bytes in size. The starting address for the block of memory is assigned to pointsArray
(e.g. pointsArray
now points to that block) The memory has allocated storage duration and remains valid until you free()
it, or the program ends. YOU are responsible for preserving a pointer holding the starting address of the block of memory so it can be freed when no longer needed.
You can now store up to howMany
integers in the block of memory pointed to by pointsArray
. To access the first address for an integer, you can use *(pointArray + 0)
(which is just *pointsArray
) using pointer notation or you can use pointsArray[0]
using array index notation. (the key is to understand that []
acts as a defeference just the same as the '*'
in *(name + offset)
does. So to access the second element, you can use either *(pointsArray + 1)
or pointsArray[1]
, etc.. While you can use array index notation with a pointer -- that does NOT make the pointer an array or cause it to be converted to one.
- Why complier knows how to input value in array when complier sees
&pointsArray[n]
?
That has more to do with the requirements of scanf
than anything funny with pointsArray
. Think about it. From man 3 scanf() when using the %d
format conversion specifier, scanf
:
Matches an optionally signed decimal integer; the next pointer
must be a pointer to int.
So if instead you wanted to read an integer into the variable declared with int a;
, your use of scanf
would be:
if (scanf ("%d", &a) == 1) {
/* you have a good integer */
}
else {
/* a matching or input failure occurred */
}
For the integer value to be placed by scanf
in a
, you must provide a pointer to a
. It is no different when you want to put the value in the integer pointsArray[n]
. How do you provide a pointer to (address of) pointsArray[n]
? (answer: you prefix it with the unary '&'
address of operator -- &pointsArray[n]
)
Hopefully this will take care of your No. 3 as well. Look things over and let me know if you have further questions.