Thread: returning pointer from function that allocates space using malloc

  1. #1
    Registered User
    Join Date
    Sep 2016
    Posts
    41

    returning pointer from function that allocates space using malloc

    Hey there bells and whistles,


    [purpose of post]
    I am having a little trouble and a few questions, with the following code.


    [background]
    I am teaching myself code and I am up to practicing using malloc.


    [desired outcome of code]
    The following code is supposed to return a pointer to an allocated memory space, then iterate through a
    for loop whilst assigning the value of the counter to the allocated space. Then print the output.






    [problem #1]
    I seem to be able to get the first address value of the allocated space, but I cannot iterate to the next byte in the space.


    [problem #2]
    I cannot seem to assign a value to any address space






    [question #1]
    How do I iterate through this allocated space?


    [question #2]
    Am I not able to assign values because I have only assigned space for a hypothetical something, but have not in fact declared that something. i.e. declaring a
    variable.


    [question #3]
    How do I do that?


    [question #4]
    Am I ultimately unable to assign values because this is space allocated for pointers only?


    [question #5]
    I also tried to dereference the pointer twice, once it was returned. I though that the char* retrunedptr variable would be a pointer to a pointer, hence a double
    dereference, this does not seem to be that case and is very confusing. Could someone please explain why that is not the case?






    [Things I have tried]


    -dereferencing the pointer in the for loop (did not compile)
    -dereferencing the return ptr at the end of the function (did not compile)
    -declaring another pointer and initialising a reference to the first pointer, then returning that pointer (pointer to a pointer)
    -returning by reference to the first pointer (did not compile)
    -using a unary & in the printf statement, all I get is some garbage value.




    Code:
    
        #include <stdio.h>
        #include <stdlib.h>
    
    
        int* returnptr(){
    
    
            int* ptr = (int*)malloc(32 * sizeof(char));
            return ptr;
    
    
        }
    
    
    
        int main() {
    
    
            int* returnedptr = returnptr();
      
            for (uint i = 0; i<32; i++){
    
    
                returnedptr[i] = i;
                printf("%c", *returnedptr);
    
    
            }
    
            return (EXIT_SUCCESS);
        }
    Last edited by MedicineMan25; 09-10-2016 at 10:19 AM.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > int* ptr = (int*)malloc(32 * sizeof(char));
    You need sizeof int (you're allocating int's), not sizeof(char).

    More robustly, one would write
    int *ptr = malloc( 32 * sizeof(*ptr) );

    Casting the result of malloc is unnecessary (if you're doing it right), and a useful warning if you're doing it wrong.

    > printf("%c", *returnedptr);
    Revise your printf formats.
    %c is for chars
    %d is for ints

    So perhaps
    printf("%d ", returnedptr[i] );
    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
    Sep 2016
    Posts
    41
    hey Salem, thanks for the answer...

    > int* ptr = (int*)malloc(32 * sizeof(char));
    You need sizeof int (you're allocating int's), not sizeof(char).
    that seems to be a relic from when I was using char and trying to assign letters... missed that in the re-type





    More robustly, one would write
    int *ptr = malloc( 32 * sizeof(*ptr) );


    So why is there no standard way of writing the pointer symbol? Writing it like this is really confusing and makes me think of is as a unary operator, even though this is clearly a declaration and it's being used as a type. Could I write:

    Code:
    int* ptr = malloc( 32 * sizeof(ptr) );
    


    Or do I need to put a unary * inside the sizeof parameter? Both seem to compile just fine, would there be anything hidden happening here that I can't see at compile time?





    printf("%c", *returnedptr);
    Revise your printf formats.
    %c is for chars
    %d is for ints


    Definitely, this is another artefact. Sorry!





    So perhaps
    printf("%d ", returnedptr[i] );


    Yeh I thought of that as well, when I try to iterate with [i] all I get is a continuous output of zero.

    I have had some success with the following solution:

    Code:
    
    
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    
    /*
     * 
     */
    
    
    int* returnptr(){
        
        int* ptr = (int*)malloc(32 * sizeof(int)); 
    
    
        return ptr;
    
    
    }
    
    
    int main(int argc, char** argv) {
    
    
         int* returnedptr = returnptr();   
        
        for (uint i = 0; i<32; i++){
        
            //returnedptr[i] = i;
            printf("%d \n", returnedptr);
            
        }
        
        return (EXIT_SUCCESS);
    }
    
    
    



    This prints out the first address, but no iteration.

    Again if I try to use:

    Code:
     
    
    for (uint i = 0; i<32; i++){
        
            //returnedptr[i] = i;
            printf("%d \n", returnedptr[i]);
            
        }
    It simply prints out zeros.
    Last edited by MedicineMan25; 09-10-2016 at 11:19 AM.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    *shrug* works for me.
    Code:
    $ cat main.c
    #include <stdio.h>
    #include <stdlib.h>
    
    
    int* returnptr(){
      int* ptr = malloc(32 * sizeof(*ptr));
      return ptr;
    }
    
    int main() {
      int* returnedptr = returnptr();
      for (int i = 0; i<32; i++){
        returnedptr[i] = i;
        printf("%d\n", returnedptr[i]);
      }
    
      return (EXIT_SUCCESS);
    }
    
    $ gcc main.c
    $ ./a.out 
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    $
    > int* ptr = malloc( 32 * sizeof(ptr) );
    > Or do I need to put a unary * inside the sizeof parameter? Both seem to compile just fine, would there be anything hidden happening here that I can't see at compile time?
    Yes, you absolutely need to.
    sizeof(ptr) is the size of the pointer (which is typically a uniform small size on any given machine).
    sizeof(*ptr) is the size of whatever it points to (whether chars, ints, doubles, any structure, etc etc)

    Of course it will compile just fine - it is syntactically valid.
    But at run time, your goose is cooked.
    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.

  5. #5
    Registered User
    Join Date
    Sep 2016
    Posts
    41
    sizeof(ptr) is the size of the pointer (which is typically a uniform small size on any given machine).
    sizeof(*ptr) is the size of whatever it points to (whether chars, ints, doubles, any structure, etc etc)


    As a rule of thumb, on a 64bit machine a pointer is usually 64bits, on a 32bit machine usually 32 bits. There are exceptions however. Since a pointer is just a memory address its always the same size regardless of what the memory it points to contains. So a pointer to a float, a char or an int are all the same size.
    The standard does not guarantee sizeof(double*) == sizeof(int*). For instance, assume a processor with two address buses with different widths (like on some Harvard architecture processors) it could have pointers with different sizes.
    Just did a quick google search and found that... did not know or even consider that. I always understood pointers to be of a size equivalent to the type that they are declared for. A natural assumption however, now that I think about it, a fairly careless one... addresses are addresses, why would that relate to a type? haha ... I know that you must declare a pointer to a specific type for dereferencing purposes, but I don't understand why that is the case. I'll have to do some more research into that.

    Well now that works for me too... I wonder what I was doing that wouldn't let it compile and run properly... probably something really simple and stupid that learning eyes couldn't see.

    I think this was it:

    Code:
        for (uint i = 0; i<32; i++){
    
    
            returnedptr[i] = i;
            printf("%c", *returnedptr); <<<<<<<<<<<<<<<<< //dereferencing the ptr and not iterating with [i] or ++ 
    
        }
    
    



    I could also have done this:

    Code:
      for (uint i = 0; i<32; i++){
        
            returnedptr[i] = i;
            printf("%d \n", *returnedptr);
            (*returnedptr)++;
            
        }
    And it works, but I prefer iterating with: returnedptr[i]. I know that part of the MISRA C standard talks about
    not iterating inside the for loop with ++ operators, as mentioned in the above example.


    Thank you Salem, this was very confusing for me. I have learnt a great deal and I really appreciate your input. Happy coding!

    p.s. One last thing:

    Casting the result of malloc is unnecessary (if you're doing it right), and a useful warning if you're doing it wrong.


    So I was taught this as a way to dereference values inside the allocated space, seeing as you cannot dereference void pointers. Is this faulty teaching?

    Thanks again!

  6. #6
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > So I was taught this as a way to dereference values inside the allocated space, seeing as you cannot dereference void pointers. Is this faulty teaching?
    malloc returns void*, and you are right, void* pointers cannot be dereferenced.

    But the return result of malloc isn't being dereferenced, it is being assigned.
    int *ptr = malloc( someSize );

    What is dereferenced is ptr, and it has a type.

    The C standard guarantees that void* to type* assignments work as expected, without the need for a cast.
    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.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Issues with malloc, returning pointer, conflicting types
    By pointingmachine in forum C Programming
    Replies: 3
    Last Post: 04-04-2013, 08:17 PM
  2. Function returning malloc'ed memory.
    By samus250 in forum C Programming
    Replies: 5
    Last Post: 04-30-2008, 01:33 PM
  3. malloc allocates the same space in the memory
    By myle in forum C Programming
    Replies: 23
    Last Post: 11-20-2007, 07:52 PM
  4. returning allocated space from function
    By BrownB in forum C Programming
    Replies: 4
    Last Post: 07-13-2004, 12:06 PM
  5. function returning pointer
    By blue_gene in forum C Programming
    Replies: 7
    Last Post: 04-19-2004, 02:35 PM

Tags for this Thread