Thread: Returning and using pointers to pointers

  1. #1
    Old Fashioned
    Join Date
    Nov 2016
    Posts
    127

    Question Returning and using pointers to pointers

    This is the first time I've ever had to use pointers to pointers aside from the all-so-known char **argv.

    I have a couple of things I want to mention ahead of time. First of all, the intended functionality is to work with "arrays" of struct pointers. However in C, I cannot return an array of struct pointers so I am trying to return a pointer to heap memory which contains a bunch of struct pointers and work with that instead. Lastly, I'm a bit confused about the syntax of
    Code:
    char *argv[]
    for example because this looks like an array of pointers, but I cannot actually create a function which returns an "array of pointers." However, as we know
    Code:
    char *argv[]
    is the same as
    Code:
    char **argv
    so is that actually an array of pointers or is argv a pointer to some heap memory of char pointers?

    In any event, here's my code... I've done something wrong and I am thinking it's with my array of pointers stuff. The program should give us the number 6 when run but instead it gives us the number 0.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int no_of_appearances(int *arr, size_t length, int integer);
    int ip_compute_frequency(int arr[], int num, size_t length);
    struct integer_profile *ip_create(int array[], int num, size_t length);
    int ip_get_most_frequent_number(struct integer_profile **ip_table, size_t length);
    struct integer_profile** create_ip_table(int arr[], size_t length);
    
    struct integer_profile
    {
        int num;
        int frequency;
    };
    int main(void)
    {
        int arr[] = {1,2,3,4,5,5,6,6,6,7};
        struct integer_profile **ip_table = create_ip_table(arr, sizeof(arr));
        int k = ip_get_most_frequent_number(ip_table, sizeof(arr));
        printf("The most frequent number is %d\n", k);
        return EXIT_SUCCESS;
    }
    //Creates and returns a new integer profile with frequency populated.
    struct integer_profile *ip_create(int array[], int num, size_t length)
    {
        struct integer_profile *ip = malloc(sizeof(struct integer_profile));
        ip->num = num;
        
        ip->frequency = ip_compute_frequency(array, num, length);
        return ip;
    }
    
    int ip_compute_frequency(int arr[], int num, size_t length)
    {
        size_t i;
        int counter = 0;
        for(i = 0; i < length; i++)
        {
            if(arr[i] == num) counter++;
        }
        return counter;
    }
    struct integer_profile **create_ip_table(int arr[], size_t length)
    {
        size_t i;
        struct integer_profile **ip_table = malloc(sizeof(struct integer_profile*)*length);
        for(i = 0; i < length; i++)
        {
            ip_table[i] = ip_create(arr, arr[i], length);
        }
        return ip_table;
    }
    int ip_get_most_frequent_number(struct integer_profile **ip_table, size_t length)
    {
        size_t i;
        struct integer_profile *temp = ip_table[0];
        for(i = 1; i < length; i++) // Start at 1 because ip_table[0] won't be greater than its own frequency
        {
            if(ip_table[i]->frequency > temp->frequency) temp = ip_table[i];
        }
        return temp->num;
    }
    If I was homeless and jobless, I would take my laptop to a wifi source and write C for fun all day. It's the same thing I enjoy now!

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    37,490
    > struct integer_profile **ip_table = create_ip_table(arr, sizeof(arr));
    > int k = ip_get_most_frequent_number(ip_table, sizeof(arr));
    You seem to be using sizeof(arr) as a count of the number of array elements.

    Use sizeof(arr)/sizeof(*arr) if you want to count elements, not bytes.
    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.

  3. #3
    Registered User
    Join Date
    Feb 2019
    Posts
    533
    This:
    Code:
    int **pp;
    Is a variable pp which holds an address pointing somewhere in memory which holds an address pointing to an array of ints. And this:
    Code:
    int *pp[];
    Is the same, since pp is still a pointer...

    Notice that arrays with one dimension declarations are made in the form:
    Code:
    TYPE identifier[NUM_ELEMENTS];
    Where NUM_ELEMENTS can be empty for "incomplete arrays" declarations.

    In the previous array syntax, the type TYPE is int *.

    To understand it, this:
    Code:
    int a[3] = { 1, 2, 3 };
    Declares a constant pointer (cannot be changed), a, pointing to an array of 3 ints. Notice the array is read/write.
    and this:
    Code:
    int *a = (int []){ 1, 2, 3 };
    Is also a pointer (not constant - can be changed), but points to a read-only array (compound literal, since C99).

    Second, Salem is right... sizeof() will get you the size of something in bytes, not in elements.

  4. #4
    Old Fashioned
    Join Date
    Nov 2016
    Posts
    127
    Wow flp1969, thank you! Definitely learned something there, especially with that last syntax. The confusion I had stemmed from the fact that I had never seen that last snippet syntax used before. Also, while I knew that an array name was actually a pointer, I became slightly confused on semantics of an "array" vs an allocated section of heap memory, index using bracket notation, which is slightly different in that the latter can of course be returned from a function whereas the former is invalid in a return situation. This became tricky when trying to return a grouping of multiple pointers and that's where I finally hit the pointer-to-pointer use-case.

    Salem, many thanks for pointing out my improper usage of sizeof() in this case... When I wrote the original version, I knew I'd be passing to malloc and was originally thinking in terms of bytes but then later I confused that with elements. Another gotcha that I've fallen into before.

    Glad to have learned some and gotten this thing working too.
    If I was homeless and jobless, I would take my laptop to a wifi source and write C for fun all day. It's the same thing I enjoy now!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Pointers to objects -- passing and returning pointers
    By 1veedo in forum C++ Programming
    Replies: 4
    Last Post: 04-04-2008, 11:42 AM
  2. returning pointers
    By spudval in forum C++ Programming
    Replies: 4
    Last Post: 07-11-2007, 02:12 PM
  3. Returning Pointers
    By Shal in forum C++ Programming
    Replies: 3
    Last Post: 07-12-2006, 02:57 PM
  4. Returning Pointers - need some help
    By Servo888 in forum C Programming
    Replies: 11
    Last Post: 08-31-2004, 08:20 PM
  5. returning pointers
    By subdene in forum C++ Programming
    Replies: 5
    Last Post: 02-02-2003, 03:46 PM

Tags for this Thread