You are close, but you have used int *array_ptr []
in int* print_array (int *array_ptr [], int *size_ptr)
incorrectly. You further have no pointer in main()
to hold the address returned by int *record_array (int *size_ptr)
to use in main()
and free
when it is no longer needed. print_array
simply prints the array and returns nothing (it shouldn't return anything) so it should just be type void
, e.g. void print_array (int *array_ptr, int *size_ptr)
On access, (subject to 4-exceptions not relevant here), an array is converted to a pointer to the first element C11 Standard - 6.3.2.1 Other Operands - Lvalues, arrays, and function designators(p3). When you want to pass an array, you simply pass the array as a parameter and it is converted to a pointer automatically.
Also note, there is NO array in the entirety of your code. You declare a pointer and then allocate a block of memory to hold your integer values and you assign the starting address for that block to your pointer. (e.g. the pointer holds the starting address for the allocated block as its value, it "points" to that block of memory)
For starters, in main()
, you need a pointer to hold the address returned by record_array
, e.g.
int size = 0;
int *array = NULL; /* you need a pointer to hold the address of your array */
In record_array
(and for every allocation), you must check the return of malloc()
to validate whether it succeeded or failed, e.g.
int *record_array (int *size_ptr)
{
int *array_ptr = malloc (*size_ptr * sizeof *array_ptr);
if (!array_ptr) { /* validate EVERY allocation */
perror ("malloc-array_ptr");
return NULL;
}
...
(note: the use of the dereferenced pointer to set the type-size for the allocation. Using the dereference pointer -- you will never get it wrong. In C, there is no need to cast the return of malloc
, it is unnecessary. See: Do I cast the result of malloc?)
With input, you must validate every input, e.g. in record_array()
that would be:
for (int index = 0; index < *size_ptr; index++)
{
printf ("Enter element at index %d: ", index);
if (scanf ("%d", &array_ptr[index]) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return NULL;
}
}
Expanding a bit on the validations, every time you do something in your code that can fail (like take user input or allocation memory), it is imperative that you validate the return before using the results in your code. Above, if you simply do scanf ("%d", &array_ptr[index])
a simply slip and tapping 'r'
instead of '5'
would go unnoticed but lead to invalid results in your code (and perhaps Undefined Behavior if it occurred on the first character)
So to prevent using invalid data, you check the return of the function you are using. With scanf
it returns the number of successful conversions or EOF
if failure occurs before the first conversion takes place. So when taking input with scanf
you always check that the return matched the number of conversions you specify in your format-string. With "%d"
-- one conversion to int
will take place. So to validate the input, you use:
if (scanf ("%d", &array_ptr[index]) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return NULL;
}
(which just say if the return from scanf()
isn't 1
-- handle the error -- which is to return failure (or NULL
) in this case)
Finally in main()
, you will validate the return of record_array
is not NULL
before using the allocated block in print_array()
, e.g.
if ((array = record_array (&size))) { /* validate record_array succeeds */
print_array (array, &size); /* print array */
free (array); /* free array */
}
(the comparison is shorthand for: if ((array = record_array (&size)) != NULL) {...
. You could have done the assignment separately, e.g. array = record_array (&size);
and then if (array != NULL) {...
so long as you validate the return :)
Making those corrections (and providing a space in the prompt to separate the prompt and the input) you would have:
#include <stdio.h>
#include <stdlib.h>
int *record_array (int *size_ptr);
void print_array (int *array_ptr, int *size_ptr);
int *record_array (int *size_ptr)
{
int *array_ptr = malloc (*size_ptr * sizeof *array_ptr);
if (!array_ptr) { /* validate EVERY allocation */
perror ("malloc-array_ptr");
return NULL;
}
for (int index = 0; index < *size_ptr; index++)
{
printf ("Enter element at index %d: ", index);
if (scanf ("%d", &array_ptr[index]) != 1) {
fputs ("error: invalid integer input.\n", stderr);
return NULL;
}
}
return array_ptr;
}
void print_array (int *array_ptr, int *size_ptr)
{
for (int index = 0; index < *size_ptr; index++)
printf ("%d ",array_ptr[index]);
putchar ('\n'); /* tidy up with newline */
}
int main()
{
int size = 0;
int *array = NULL; /* you need a pointer to hold the address of your array */
printf("How many elements do you want? ");
if (scanf("%d", &size) != 1) { /* validate EVERY input */
fputs ("error: invalid integer input.\n", stderr);
return 1;
}
if ((array = record_array (&size))) { /* validate record_array succeeds */
print_array (array, &size); /* print array */
free (array); /* free array */
}
}
Example Use/Output
$ ./bin/readarrayfunc
How many elements do you want? 5
Enter element at index 0: 1
Enter element at index 1: 2
Enter element at index 2: 3
Enter element at index 3: 4
Enter element at index 4: 5
1 2 3 4 5
Note also with declarations the '*'
goes with the variable, not the type. Why? Readability. Look at:
int* a, b, c;
That certainly does not declare 3-pointers to int
, it declares one pointer to int
and two integers:
int *a, b, c;
makes that clear.
Look things over and let me know if you have further questions.