Thread: What is the difference between types: int **n, *n[3], (*n)[3].

  1. #1
    Registered User
    Join Date
    Jun 2020
    Posts
    2

    What is the difference between types: int **n, *n[3], (*n)[3].

    And how can I use malloc and calloc to dynamically allocate memory to them?

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You're looking at declarations of a pointer to a pointer, of an array of pointers, and of a pointer to an array, respectively.

    As for how to dynamically allocate memory for them: first, you need to ask yourself what you're trying to allocate, e.g., are you trying to allocate space for a dynamic 1D array, a dynamic rectangular 2D array, a dynamic jagged 2D array, etc?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    int **n
    You can synthesise any n[x][y] kind of array, and each y can be different (ragged)
    Code:
    n = malloc(x*sizeof(*n));
    for(i = 0 ; i < x ; i++)
        n[i] = malloc(y*sizeof(*n[i]));
    int *n[3]
    You can synthesis any n[3][y] kind of array, and each y can be different (ragged)
    Code:
    for(i = 0 ; i < 3 ; i++)
        n[i] = malloc(y*sizeof(*n[i]));
    int (*n)[3]
    You can synthesis any n[x][3] kind of array
    Code:
    n = malloc(x*sizeof(*n));
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Dec 2017
    Posts
    1,628
    Assuming they are all supposed to be transformed into some kind of 2-d array, here are some possibilities.
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
     
    // For allocation of triangular array data block.
    int sum1ToN(int n) { return (n * (n + 1)) / 2; }
     
    // Allocator that exits on failure.
    void *alloc(size_t size) {
        void *p = calloc(1, size);
        if (!p) {
            perror("alloc");
            exit(EXIT_FAILURE);
        }
        return p;
    }
     
    // Macro so allocator can be called ALLOC(count, type)
    #define ALLOC(count, type) alloc((count) * sizeof(type))
     
     
    int main() {
        srand(time(0)); // Jagged array row lengths are random.
     
    // Rectangular 2-d array
    {
        const int Rows = 5, Cols = 10;
     
        int **a = ALLOC(Rows, *a);               // array of row pointers
        a[0] = ALLOC(Rows * Cols, **a);          // data block
        for (int row = 1; row < Rows; ++row)     // set row pointers to
            a[row] = a[row - 1] + Cols;          // point into data block
     
        for (int row = 0; row < Rows; ++row) {
            for (int col = 0; col < Cols; ++col)
                printf("%d ", a[row][col]);
            putchar('\n');
        }
        putchar('\n');
        
        free(a[0]);
        free(a);
    }
     
     
    // Triangular array (short row first)
    {
        const int Size = 8;
     
        int **a = ALLOC(Size, *a);
        a[0] = ALLOC(sum1ToN(Size), **a);
        for (int row = 1; row < Size; ++row)
            a[row] = a[row - 1] + row;
     
        for (int row = 0; row < Size; ++row) {
            for (int col = 0; col < row + 1; ++col)
                printf("%d ", a[row][col]);
            putchar('\n');
        }
        putchar('\n');
        free(a[0]);
        free(a);
    }
     
     
    // Triangular array (long row first)
    {
        const int Size = 8;
     
        int **a = ALLOC(Size, *a);
        a[0] = ALLOC(sum1ToN(Size), **a);
        for (int row = 1; row < Size; ++row)
            a[row] = a[row - 1] + (Size + 1) - row;
     
        for (int row = 0; row < Size; ++row) {
            for (int col = 0; col < Size - row; ++col)
                printf("%d ", a[row][col]);
            putchar('\n');
        }
        putchar('\n');
        free(a[0]);
        free(a);
    }
     
     
    // Jagged 2-d array
    {
        const int Rows = 5;
     
        int **a = ALLOC(Rows, *a);
        for (int row = 0; row < Rows; ++row) {
            // assigning random number of columns to each row
            int size = rand() % 9 + 1; // 1 to 9
            a[row] = ALLOC(size + 1, **a); // + 1 for a sentinel
            a[row][size] = -1; // set sentinel (assuming -1 is unused value)
        }
        // Instead of a sentinel you could store the size in the first element.
     
        for (int row = 0; row < Rows; ++row) {
            for (int col = 0; a[row][col] != -1; ++col)
                printf("%d ", a[row][col]);
            putchar('\n');
        }
        putchar('\n');
        
        for (int row = 0; row < Rows; ++row)
            free(a[row]);
        free(a);
    }
     
     
    // If the jagged row sizes are unchanging you could still allocate
    // the data in a single block and set the row pointers to point into it.
    // In that case you could also use the start pointer of the next
    // row to detect the end of the current row. This makes the last row
    // a problem, but you could allocate one extra row pointer.
     
    // Jagged 2-d array; single data block
    {
        const int Rows = 5;
     
        // Generate random row sizes.
        int *sizes = ALLOC(Rows, *sizes);
        int total_size = 0;
        for (int row = 0; row < Rows; ++row)
            total_size += sizes[row] = rand() % 9 + 1; // 1 to 9
     
        // Allocate 1 extra row pointer for a "one-past-the-end" address.
        int **a = ALLOC(Rows + 1, *a);
        a[0] = ALLOC(total_size, **a);
        for (int row = 1; row < Rows + 1; ++row)
            a[row] = a[row - 1] + sizes[row - 1];
     
        free(sizes);
     
        for (int row = 0; row < Rows; ++row) {
            for (int col = 0; &a[row][col] != &a[row+1][0]; ++col)
                printf("%d ", a[row][col]);
            putchar('\n');
        }
        putchar('\n');
        
        free(a[0]);
        free(a);
    }
     
     
    // Array of 3 pointers-to-int
     
    // This is basically a preallocated set of 3 "row pointers", so we need to
    // allocate the data block (e.g.) and point the row pointers into it,
    // or allocate each row separately.
    {
        const int Rows = 3, Cols = 5;
        int *a[Rows];
     
        a[0] = ALLOC(Rows * Cols, *a);
        for (int row = 1; row < Rows; ++row)
            a[row] = a[row - 1] + Cols;
     
        for (int row = 0; row < Rows; ++row) {
            for (int col = 0; col < Cols; ++col)
                printf("%d ", a[row][col]);
            putchar('\n');
        }
        putchar('\n');
     
        free(a[0]);
    }
     
     
    // Pointer to array of 3 ints.
     
    // Points to one or more array(s) of 3 ints.
    // Each allocated element allocates a row of 3 data columns.
    {
        const int Rows = 5, Cols = 3;
        int (*a)[Cols];
     
        a = ALLOC(Rows, *a);
     
        for (int row = 0; row < Rows; ++row) {
            for (int col = 0; col < Cols; ++col)
                printf("%d ", a[row][col]);
            putchar('\n');
        }
        putchar('\n');
     
        free(a);
    }
     
        return 0;
    }
    Code:
    0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 0 
    
    0 
    0 0 
    0 0 0 
    0 0 0 0 
    0 0 0 0 0 
    0 0 0 0 0 0 
    0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 
    
    0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 
    0 0 0 0 0 0 
    0 0 0 0 0 
    0 0 0 0 
    0 0 0 
    0 0 
    0 
    
    0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 
    0 0 0 0 
    0 0 0 0 0 0 0 
    
    0 0 0 0 
    0 0 0 0 
    0 0 0 0 0 
    0 0 0 0 0 0 0 0 
    0 0 0 0 0 0 0 0 0 
    
    0 0 0 0 0 
    0 0 0 0 0 
    0 0 0 0 0 
    
    0 0 0 
    0 0 0 
    0 0 0 
    0 0 0 
    0 0 0
    Last edited by john.c; 06-23-2020 at 09:59 AM.
    A little inaccuracy saves tons of explanation. - H.H. Munro

  5. #5
    Registered User
    Join Date
    Jun 2020
    Posts
    2
    Thank you!!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. User-defined types to built in types
    By Zeus_ in forum C++ Programming
    Replies: 1
    Last Post: 12-30-2019, 09:31 PM
  2. Replies: 7
    Last Post: 01-22-2014, 09:48 AM
  3. How to convert integral types into pointer types?
    By rohit99 in forum C++ Programming
    Replies: 3
    Last Post: 03-20-2008, 09:57 AM
  4. Types, Integral Types, Bytes?!?!?!
    By Kaidao in forum C++ Programming
    Replies: 3
    Last Post: 03-21-2006, 08:15 AM
  5. whats the difference between these types
    By *ClownPimp* in forum C++ Programming
    Replies: 3
    Last Post: 06-21-2003, 04:54 PM

Tags for this Thread