int **ptr; 
*ptr = (int *)malloc(10 * sizeof (*val));

First statement declares a double pointer.
Second dereferences the pointer. In order that you are able to dereference it the pointer should point to some valid memory. it does not hence the seg fault.

If you need to allocate enough memory for array of pointers you need:

ptr = malloc(sizeof(int *) * 10); 

Now ptr points to a memory big enough to hold 10 pointers to int.
Each of the array elements which itself is a pointer can now be accessed using ptr[i] where,

i < 10
Answer from Alok Save on Stack Overflow
Discussions

How to dynamically allocate an array of pointers in C++? - Stack Overflow
Stack Overflow chat opening up to all users in January; Stack Exchange chat... Modernizing curation: A proposal for The Workshop and The Archive · -1 How to initialize an array of pointers to string in the constructor · 0 Dynamic Allocation of an Array of Pointers to Objects More on stackoverflow.com
🌐 stackoverflow.com
c - Dynamic array of pointers to structs - Stack Overflow
I think it is a poor question, you do understand that an array could be defined in such way, since you do try allocating a space for it, so what are you asking?, it is not sufficient to allocate a space for the pointer to struct, which is btw pStudentRecord and not pSt...ord *, in-order to use it ... More on stackoverflow.com
🌐 stackoverflow.com
Dynamically allocate an array of Pointers to class objects
Also if I change it to the way ... use that array as well right? I'll do some more reading... -P ... Well then you'll have to show me more code. ... Well.. okay. But I don't know if you'll find anything useful. Since you have BaseballPlayer* team;, this indicates you have one of two possible situations: 1) a pointer to a single ... More on cplusplus.com
🌐 cplusplus.com
February 23, 2010
Initializing and printing an array using pointers and dynamic allocation in C - Code Review Stack Exchange
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 havi... More on codereview.stackexchange.com
🌐 codereview.stackexchange.com
January 29, 2015
🌐
Swarthmore College
cs.swarthmore.edu › ~newhall › unixhelp › C_arrays.html
Arrays in C
Dynamically allocated arrays are allocated on the heap at run time. The heap space can be assigned to global or local pointer variables that store the address of the allocated heap space (point to the first bucket). To dynamically allocate space, use calls to malloc passing in the total number ...
🌐
Cprogramming
cboard.cprogramming.com › c-programming › 136477-create-array-pointers-dynamically.html
Create array of pointers dynamically
April 1, 2011 - It doesn't matter what you point ... on the road to disappointment. ... Well, if you want to create array of char dynamically, declare pointer to char, and allocate with malloc....
🌐
IncludeHelp
includehelp.com › code-snippets › declare-and-print-dynamic-array-using-c-pointer.aspx
C - Declare and Print Dynamic Array using C Pointer - IncludeHelp
August 3, 2016 - In this code snippet, we will learn how to declare dynamic memory for one dimensional integer array. In this example, we will declare dynamic array for 5 integer elements, assigning values to them and print values of all elements. //C - Declare and Print Dynamic Array using C Pointer.
🌐
DEV Community
dev.to › denvercoder1 › c-pointers-and-dynamic-memory-allocation-1emi
C++ Pointers and Dynamic Memory Allocation - DEV Community
December 23, 2020 - In C++, arrays must have a constant size which can't be changed, but with pointers, you can allocate just the space you need, allowing you to improve your program's space efficiency and make the shape of your data as flexible as the user needs.
🌐
GeeksforGeeks
geeksforgeeks.org › c language › how-to-create-a-dynamic-array-of-strings-in-c
How to Create a Dynamic Array of Strings in C? - GeeksforGeeks
July 23, 2025 - To create a dynamic array of strings in C, we can use the concept of double pointer and dynamic memory allocation. The double pointer is the pointer that stores the memory address of another pointer.
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › c language › dynamic-array-in-c
Dynamic Array in C - GeeksforGeeks
July 23, 2025 - We can use this function to create a dynamic array of any type by simply allocating a memory block of some size and then typecasting the returned void pointer to the pointer of the required type.
🌐
Iifx
iifx.dev › en › articles › 460043151 › a-guide-to-c-arrays-and-pointers-the-static-and-dynamic-difference
A Guide to C Arrays and Pointers: The Static and Dynamic Difference
In C, the name of an array (like a or b in your example) can often be treated as a pointer to its first element. This is why you can use pointer arithmetic on array names. Both a[i] and *(a + i) are essentially doing the same thing they're ...
🌐
tutorialpedia
tutorialpedia.org › blog › how-to-make-an-array-with-a-dynamic-size-general-usage-of-dynamic-arrays-maybe-pointers-too
Dynamic Arrays in C: How to Create with Dynamic Size, Store User Input & Access Elements (Using Pointers) — tutorialpedia.org
Enter dynamic arrays: flexible, resizable data structures whose size is determined at runtime. Dynamic arrays solve the "unknown size" problem by leveraging the heap memory (instead of the stack) and pointers to manage memory dynamically.
🌐
Quora
quora.com › What-is-a-dynamic-array-and-how-do-you-create-one-using-a-pointer-in-C
What is a dynamic array and how do you create one using a pointer in C++? - Quora
Answer (1 of 2): The fact that arrays and pointers are similar (not the same), pointers can be used to create dynamic arrays, since the name of the is the address of the first element of the array.
Top answer
1 of 4
3

EDIT: updated the "BIG MISTAKE" section.

A quick lesson on C-style (different from C++!) typedefs, and why it is how it is, and how to use it.

Firstly, a basic typedef trick.

typedef int* int_pointer;
int_pointer ip1;
int *ip2;
int a;    // Just a variable
ip1 = &a; // Sets the pointer to a
ip2 = &a; // Sets the pointer to a
*ip1 = 4; // Sets a to 4
*ip2 = 4; // Sets a to 4

ip1 and ip2 are the same type: a pointer-to-type-int, even though you didn't put a * in the declaration of ip1. That * was instead in the declaration.

Switching topics. You speak of declaring arrays as

int array1[4];

To do this dynamically at runtime, you might do:

int *array2 = malloc(sizeof(int) * 4);
int a = 4;
array1[0] = a;
array2[0] = a; // The [] implicitly dereferences the pointer

Now, what if we want an array of pointers? It would look like this:

int *array1[4];
int a;
array1[0] = &a; // Sets array[0] to point to variable a
*array1[0] = 4; // Sets a to 4

Let's allocate that array dynamically.

int **array2 = malloc(sizeof(int *) * 4);
array2[0] = &a; // [] implicitly dereferences
*array2[0] = 4; // Sets a to 4

Notice the int **. That means pointer-to pointer-to-int. We can, if we choose, use a pointer typedef.

typedef int* array_of_ints;
array_of_ints *array3 = malloc(sizeof(array_of_ints) * 4);
array3[0] = &a; // [] implicitly dereferences
*array3[0] = 4; // Sets a to 4

See how there's only one * in that last declaration? That's because ONE of them is "in the typedef." With that last declaration, you now have an array of size 4 that consists of 4 pointers to ints (int *).

It's important to point out OPERATOR PRECEDENCE here. The dereference operator[] takes preference over the * one. SO to be absolutely clear, what we're doing is this:

*(array3[0]) = 4;

Now, let's change topics to structs and typedefs.

struct foo { int a; }; // Declares a struct named foo
typedef struct { int a; } bar; // Typedefs an "ANONYMOUS STRUCTURE" referred to by 'bar'

Why would you ever typedef an anonymous struct? Well, for readability!

struct foo a; // Declares a variable a of type struct foo
bar b;        // Notice how you don't have to put 'struct' first

Declaring a function...

funca(struct foo* arg1, bar *arg2);

See how we didn't have to put 'struct' in front of arg2?

Now, we see that the code you have to use defines a structure IN THIS MANNER:

typedef struct { } * foo_pointers;

That is analogous to how we did an array of pointers before:

typedef int* array_of_ints;

Compare side-by-side

typedef struct { } * foo_pointers;
typedef int* array_of_ints;

The only difference is that one is to a struct {} and the other is to int.

With our foo_pointers, we can declare an array of pointers to foo as such:

foo_pointers fooptrs[4];

Now we have an array that stores 4 pointers to an anonymous structure that we can't access.

TOPIC SWITCH!

UNFORTUNATELY FOR YOU, your teacher made a mistake. If one looks at the sizeof() of the type foo_pointers above, one will find it returns the size of a pointer to that structure, NOT the size of the structure. This is 4 bytes for 32-bit platform or 8 bytes for 64-bit platform. This is because we typedef'd a POINTER TO A STRUCT, not a struct itself. sizeof(pStudentRecord) will return 4.

So you can't allocate space for the structures themselves in an obvious fashion! However, compilers allow for this stupidity. pStudentRecord is not a name/type you can use to validly allocate memory, it is a pointer to an anonymous "conceptual" structure, but we can feed the size of that to the compiler.

pStudnetRecord g_ppRecords[2]; pStudentRecord *record = malloc(sizeof(*g_ppRecords[1]));

A better practice is to do this:

typedef struct { ... } StudentRecord;  // Struct
typedef StudentRecord* pStudentRecord; // Pointer-to struct

We'd now have the ability to make struct StudentRecord's, as well as pointers to them with pStudentRecord's, in a clear manner.

Although the method you're forced to use is very bad practice, it's not exactly a problem at the moment. Let's go back to our simplified example using ints.

What if I want to be make a typedef to complicate my life but explain the concept going on here? Let's go back to the old int code.

typedef int* array_of_ints;
int *array1[4];
int **array2 = malloc(sizeof(int *) * 4); // Equivalent-ish to the line above
array_of_ints *array3 = malloc(sizeof(array_of_ints) * 4);
int a, b, c, d;
*array1[0] = &a; *array1[1] = &b; *array1[2] = &c; *array1[3] = &d;
*array2[0] = &a; *array2[1] = &b; *array2[2] = &c; *array2[3] = &d;
*array3[0] = &a; *array3[1] = &b; *array3[2] = &c; *array3[3] = &d;

As you can see, we can use this with our pStudentRecord:

pStudentRecord array1[4];
pStudentRecord *array2 = malloc(sizeof(pStudentRecord) * 4);

Put everything together, and it follows logically that:

array1[0]->firstName = "Christopher";
*array2[0]->firstName = "Christopher";

Are equivalent. (Note: do not do exactly as I did above; assigning a char* pointer at runtime to a string is only OK if you know you have enough space allocated already).

This only really brings up one last bit. What do we do with all this memory we malloc'd? How do we free it?

free(array1);
free(array2);

And there is a the end of a late-night lesson on pointers, typedefs of anonymous structs, and other stuff.

2 of 4
2

Observe that pStudentRecord is typedef'd as a pointer to a structure. Pointers in C simply point to the start of a memory block, whether that block contains 1 element (a normal "scalar" pointer) or 10 elements (an "array" pointer). So, for example, the following

char c = 'x';
char *pc = &c;

makes pc point to a piece of memory that starts with the character 'x', while the following

char *s = "abcd";

makes s point to a piece of memory that starts with "abcd" (and followed by a null byte). The types are the same, but they might be used for different purposes.

Therefore, once allocated, I could access the elements of g_ppRecords by doing e.g. g_ppRecords[1]->firstName.

Now, to allocate this array: you want to use g_ppRecords = malloc(sizeof(pStudentRecord)*(g_numRecords+1)); (though note that sizeof(pStudentRecord*) and sizeof(pStudentRecord) are equal since both are pointer types). This makes an uninitialized array of structure pointers. For each structure pointer in the array, you'd need to give it a value by allocating a new structure. The crux of the problem is how you might allocate a single structure, i.e.

g_ppRecords[1] = malloc(/* what goes here? */);

Luckily, you can actually dereference pointers in sizeof:

g_ppRecords[1] = malloc(sizeof(*g_ppRecords[1]));

Note that sizeof is a compiler construct. Even if g_ppRecords[1] is not a valid pointer, the type is still valid, and so the compiler will compute the correct size.

🌐
Cplusplus
cplusplus.com › forum › general › 20044
Dynamically allocate an array of Pointers to class objects
February 23, 2010 - What you want is a pointer to an array of BaseballPlayer or derived types. So you need the **. You'll also need to allocate each team member individually and assign them to the array: ... #include "BaseballPlayer.h" #include "Pitcher.h" #include "Hitter.h" #ifndef PLAYERDATABASE_H #define PLAYERDATABASE_H using namespace std; class PlayerDatabase { public: ~PlayerDatabase(); void print_team() const; PlayerDatabase& operator=(const PlayerDatabase&); PlayerDatabase(const PlayerDatabase&); PlayerDatabase(); void load_team(ifstream&); void print_team(); virtual void get_inningsPitched(){}; private
🌐
Quora
quora.com › How-do-you-dynamically-allocate-an-array-of-struct-pointers-in-C
How to dynamically allocate an array of struct pointers in C - Quora
Answer (1 of 5): To dynamically allocate memory for pointer to array of struct you have to: * Create a pointer to pointer to the struct. * Then for example into a loop, allocate memory for any array member.
🌐
Medium
medium.com › @sohaib.arshid101 › dynamic-arrays-in-c-an-implementation-guide-4a959de94332
Dynamic arrays in C: An implementation guide | by curious&dumb | Medium
March 5, 2024 - In a 32-bit computer machine the size of a pointer would be four bytes while for a 64-bit computer machine, it would be eight bytes. So, when I execute the function init_array(array, 10), the resulting array has a size of eighty bytes (I have a 64-bit machine) rather than one hundred and twenty bytes (10 * 3 * sizeof(int)), which causes the problem when reallocating memory in the array_push macro.
Top answer
1 of 3
18

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 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 <stdlib.h>
#include <stdio.h>

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 <stdlib.h>
#include <stdio.h>

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. Honestly, the best away to handle arrays is to not use them—if you're using a language with any more power than C, you should have higher-level language constructs (std::vector, ArrayList, etc.). However, if you have to use C, abstracting them behind an API is a good start.

One issue I'm encountering is having no way to tell printArr() what the size of the array is.

Yes, in C, arrays are just blocks of memory, so you can't get their length at runtime because it's not stored anywhere! If you wanted to do this, though, you could encapsulate your array in a struct.

typedef struct my_array {
    unsigned int length;
    int* data;
} my_array_t;

You could then return a my_array_t from initArr and pass a my_array_t to printArr, which could use arr.length to get the length.

2 of 3
6
  • Return values

    • initArr communicates the start address via both the return value and a pass-by-reference parameter. It surely is redundant. Normally you'd pick one of two possible signatures:

      int * initArr(int size);
      void initArr(int ** arr, int size);
      

    and stick to it.

    • printArr, as the name suggests, only produces a side effect of values being printed. It has nothing to report back except possibly errors encountered while printing. Make it void printArr(int *, int).
  • (Ab)use of sizeof

    initArr allocates an array of n units of a pointer size. This works by coincidence: in pretty much any platform space taken by a pointer is enough to accomodate an integer. However it is not guaranteed.

    printf("size is %d\n", sizeof(*arr)) is totally misleading. It is equivalent to printf("size is %d\n", sizeof(int *)), and doesn't depend on how many bytes are actually allocated. Try to pass size 0 to initArr.

🌐
Florida State University
cs.fsu.edu › ~myers › cop3330 › notes › dma.html
Dynamic Allocation in Classes
For a dynamically created array, the pointer attaches to the starting position of the array, so can act as the array name: ... Just like basic types, objects can be allocated dynamically, as well. But remember, when an object is created, the constructor runs.
🌐
TutorialsPoint
tutorialspoint.com › cprogramming › c_dynamic_array_resizing.htm
Dynamic Array Resizing in C
To manage dynamic arrays in C, memory is allocated at runtime using pointers and functions from the <stdlib.h> header file. Specifically, malloc() and calloc() are the two primary functions used to allocate memory for dynamic arrays.