patterncModerate
Initializing and printing an array using pointers and dynamic allocation in C
Viewed 0 times
initializingarrayprintingusingpointersdynamicandallocation
Problem
I have written a code for basic array creation and printing it's values in C. I would appreciate comments on how it can be improved, and the industry standards.
One issue I'm encountering is having no way to tell printArr() what the size of the array is.
Some questions:
Running the above code (with includes for
One issue I'm encountering is having no way to tell printArr() what the size of the array is.
Some questions:
- Can I use
arr[i]anywhere in the functions instead of**arr? (Gave error when I tried it)
- What is the most common way of dealing with arrays when writing professional code? Is my approach correct?
int * initArr (int ** arr, int n)
{
*arr=(int *) malloc(sizeof(int*)*n);
printf("size is %d\n", sizeof(*arr));
int i;
for (i=0;i<n;i++)
{
*(*arr+i)=i+10;
}
return *arr;
}
void ** printArr (int ** arr, int n)
{
int i;
for (i=0;i<n;i++)
{
printf("Arr element %d is %d\n", i, *(*arr+i));
}
return *arr;
}
int main(void) {
int *arr2;
arr2=initArr(&arr2,10);
printArr(&arr2,10);
return 0;
}Running the above code (with includes for
stdio and stdlib) produces:size is 8
Arr element 0 is 10
Arr element 1 is 11
Arr element 2 is 12
Arr element 3 is 13
Arr element 4 is 14
Arr element 5 is 15
Arr element 6 is 16
Arr element 7 is 17
Arr element 8 is 18
Arr element 9 is 19Solution
There are a number of things I would change here, so I'm going to go through the process incrementally, applying changes to the whole file in passes rather than in chunks. I think this should make it more clear why the changes are implemented.
C99 Note
You should have access to, at the very least, a C99 compiler. If that's not true, you can ignore this first point, but if it is, you should change your counter declarations to be inside the first
Pointers
In
As a side effect of this, since you no longer need a double pointer, you can replace your dereferences with simple array accesses.
Next, why are you passing a double pointer (
This also simplifies the
Next, let's take a look at the allocation itself (the one in
Second of all, you are not actually allocating the right data! You're allocating
Those changes simplify the allocation to this:
Finally, the line just after that—the
Style and Warnings
I'm not sure if you just omitted it from your code, but your code depends on functions declared in external header files in the standard library. Include these at the top of your file.
Next, let's talk about code style. You are writing some very densely-packed expressions in some places. Some whitespace can make code much more readable! For example, change the for loops to this:
Similarly, change your allocation to this:
Proper spacing makes code more readable and therefore more maintainable!
Finally, let's talk about pointer declarations. You are declaring your pointers with the asterisks just sort of "floating". This is actually not a bad compromise. Some people prefer them to be grouped with the type (
Result
Here is all the code as it stands with the above changes implemented! Not only is it more readable due to style, but it's easier to understand the control flow since it no longer unnecessarily indirects variables via reference.
Extra Notes
Can I use
You can! But
This became unnecessary with the other changes, though.
What is the most common way of dealing with arrays when writing professional code? Is my approach correct?
Depends on the situation. Hon
C99 Note
You should have access to, at the very least, a C99 compiler. If that's not true, you can ignore this first point, but if it is, you should change your counter declarations to be inside the first
for clause.for (int i=0;i<n;i++)Pointers
In
initArr, you both return the int array and assign it to the provided out parameter, arr. Why? Out parameters make code confusing and hard to follow! They make sense if you're performing the array allocation somewhere else, but since you're performing the array allocation inside initArr, just drop the arr parameter and return the value.As a side effect of this, since you no longer need a double pointer, you can replace your dereferences with simple array accesses.
int * initArr (int n)
{
int * arr = (int *) malloc(sizeof(int*)*n);
printf("size is %d\n", sizeof(arr));
for (int i=0;i<n;i++)
{
arr[i]=i+10;
}
return arr;
}Next, why are you passing a double pointer (
int**) to printArr? More importantly, why does printArr have a return value if it's a purely side-effectful function? Change the parameter to int* and make the function return void.void printArr (int * arr, int n)
{
for (int i=0;i<n;i++)
{
printf("Arr element %d is %d\n", i, arr[i]);
}
}This also simplifies the
main function.int main(void) {
int * arr2 = initArr(10);
printArr(arr2,10);
return 0;
}Next, let's take a look at the allocation itself (the one in
initArr). First of all, you cast to (int *) manually, which is unnecessary and downright discouraged in C. If you're using C++, it's necessary (though you shouldn't need malloc in C++, anyway), but with a C compiler, just drop it.Second of all, you are not actually allocating the right data! You're allocating
n slots for int* values—int pointers. You actually want int data. This might not matter depending on your architecture and compiler, but it's still poor code. Fortunately, you can actually fool-proof this—don't pass an explicit type of sizeof at all! Just deference arr itself, and the compiler will calculate that value's size.Those changes simplify the allocation to this:
int * arr = malloc(sizeof(*arr)*n);Finally, the line just after that—the
printf line—is useless. It will always print the same value because it's checking the size of a pointer, which is always the same size regardless of type (though it can change on different architectures). That said, the line doesn't make any sense there. A function called initArr shouldn't have side effects, anyway. Just take it out.Style and Warnings
I'm not sure if you just omitted it from your code, but your code depends on functions declared in external header files in the standard library. Include these at the top of your file.
#include
#include Next, let's talk about code style. You are writing some very densely-packed expressions in some places. Some whitespace can make code much more readable! For example, change the for loops to this:
for (int i = 0; i < n; i++)Similarly, change your allocation to this:
int * arr = malloc(sizeof(*arr) * n);Proper spacing makes code more readable and therefore more maintainable!
Finally, let's talk about pointer declarations. You are declaring your pointers with the asterisks just sort of "floating". This is actually not a bad compromise. Some people prefer them to be grouped with the type (
int foo), others with the name (int foo). I prefer the former style, so in my final copy of the code, I changed them accordingly, but this is often merely personal preference.Result
Here is all the code as it stands with the above changes implemented! Not only is it more readable due to style, but it's easier to understand the control flow since it no longer unnecessarily indirects variables via reference.
#include
#include
int* initArr(int n)
{
int* arr = malloc(sizeof(*arr) * n);
for (int i = 0; i < n; i++) {
arr[i] = i + 10;
}
return arr;
}
void printArr(int* arr, int n)
{
for (int i = 0; i < n; i++)
{
printf("Arr element %d is %d\n", i, arr[i]);
}
}
int main(void) {
int* arr2 = initArr(10);
printArr(arr2, 10);
return 0;
}Extra Notes
Can I use
arr[i] anywhere in the functions instead of **arr? (Gave error when I tried it)You can! But
* has lower precedence than array subscript ([]), so you'd need to use grouping operators(*arr)[i]This became unnecessary with the other changes, though.
What is the most common way of dealing with arrays when writing professional code? Is my approach correct?
Depends on the situation. Hon
Code Snippets
for (int i=0;i<n;i++)int * initArr (int n)
{
int * arr = (int *) malloc(sizeof(int*)*n);
printf("size is %d\n", sizeof(arr));
for (int i=0;i<n;i++)
{
arr[i]=i+10;
}
return arr;
}void printArr (int * arr, int n)
{
for (int i=0;i<n;i++)
{
printf("Arr element %d is %d\n", i, arr[i]);
}
}int main(void) {
int * arr2 = initArr(10);
printArr(arr2,10);
return 0;
}int * arr = malloc(sizeof(*arr)*n);Context
StackExchange Code Review Q#78836, answer score: 18
Revisions (0)
No revisions yet.