Thread: malloc in function

  1. #1
    Registered User
    Join Date
    Mar 2010
    Posts
    10

    malloc in function

    Hi, I am trying to reach a memory block which is allocated in a function and I use call by reference. I already saw a similar usagae in a thread but it did'nt work for me. The code I try to solve the problem is below. Any help would be appreciated, thanks.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void func(int **tmp, int n);
    
    int main(void){
        int **ptr;
        func(ptr, 8);
        ptr[2][4] = 1;
        getchar();
        return 0;
    }
    
    void func(int **tmp, int en){
        int i;
        tmp = malloc(en * sizeof(int));
        for (i = 0; i < en; i++)
            tmp[i] = malloc( en * sizeof(int));
    }

  2. #2
    Registered User
    Join Date
    Jan 2010
    Posts
    18
    Quote Originally Posted by mugen View Post
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void func(int **tmp, int n);
    
    int main(void){
        int **ptr;
        func(ptr, 8);
        ptr[2][4] = 1;
        getchar();
        return 0;
    }
    
    void func(int **tmp, int en){
        int i;
        tmp = malloc(en * sizeof(int));
        for (i = 0; i < en; i++)
            tmp[i] = malloc( en * sizeof(int));
    }
    Hey,

    first of all, in C you _NEVER_ call by reference. C only allows to call-by-value. Call-by-reference is an enhancement in C++.

    This is how your code should work:

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void func(int ***tmp, int n);
    
    int main(void){
        int **ptr;
        func(&ptr, 8);
        ptr[2][4] = 1;
        getchar();
        return 0;
    }
    
    void func(int ***tmp, int en){
        int i;
        *tmp = (int**)malloc(en * sizeof(int *));
    
        for (i = 0; i < en; i++)
            (*tmp)[i] = (int*)malloc( en * sizeof(int));
    }
    I hope that is what you're searching for ...

    - Andi -
    Last edited by ForzaItalia2006; 03-13-2010 at 10:12 AM.

  3. #3
    Registered User
    Join Date
    Mar 2010
    Posts
    10
    Ohh thanks a lot that worked Could you explain a little bit the logic behind of this if you don't mind?

  4. #4
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    "Three star programming" - not a good idea.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    void func(int **tmp, int n);
    
    int main(void){
        int **ptr;
        func(ptr, 8);
        ptr[2][4] = 1;
        getchar();
        return 0;
    }
    
    void func(int **tmp, int en){
        int i;
        tmp = malloc(en * sizeof(int)); // try puting (en * sizeof(*tmp));
        for (i = 0; i < en; i++)
            tmp[i] = malloc( en * sizeof(int));
    }

  5. #5
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    This will fix it.

    I'd advise you to ignore using three stars. Who's gonna read that code?
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    
    int **func(int **tmp, int n);
    
    int main(void){
        int **ptr;
        ptr = func(ptr, 8);
        ptr[2][4] = 25;
        getchar();
        return 0;
    }
    
    int **func(int **tmp, int en){
        int i;
        tmp = (int **) malloc(en * sizeof(*tmp));
        for (i = 0; i < en; i++)
            tmp[i] = (int *) malloc( en * sizeof(tmp));
        return tmp;
    }
    Gotta return adress to ptr.

    Also, add checking for error - malloc could fail. If it fails return NULL.

    And ignore my casting (int **). I got a crapy compiler.
    Last edited by Tool; 03-13-2010 at 10:47 AM.

  6. #6
    Registered User
    Join Date
    Jan 2010
    Posts
    18
    Quote Originally Posted by mugen View Post
    Ohh thanks a lot that worked Could you explain a little bit the logic behind of this if you don't mind?
    That's great to hear that it worked :-) Sure, I could give some kind of background about this.

    Whenever you pass a parameter to a function, this parameter is passed by-value, meaning that its value (opposed to its address) is passed to the function. Though, assume the following code:

    Code:
    int func (int i)
    {
         i = 12;
    
         return 0;
    }
    Variable 'i' has function-scope meaning that it is only valid in the function 'func'.

    Code:
    int main ()
    {
         int b = 0;
         func(b); /* 0 is passed to function 'func' */
      
         return b; /* would be 0 */
    }
    When func(b) is called, 0 is passed to the function; accessible through variable 'i'. BUT, 'i' and 'b' are two distinct variables without inter-dependency. Though, if 'i' is changed, then only the function-local variable is changed, but the variable 'b' remains unchanged.

    In turn, if you pass the variable by-pseudo-reference in C (because call-by-reference does not exists as in C++), e.g.

    Code:
    int func (int *i)
    {
         *i = 12;
    
         return 0;
    }
    
    int main ()
    {
         int b = 0;
         func(&b); /* address of 'b' is passed to function 'func' */
      
         return b; /* would be 12 */
    }
    This is also call-by-value, but the address is passed to function 'func' and within 'func' you don't modify the function-local variable 'i' but the memory location where 'i' points to. Though, basically, you modify variable 'b'. That's a bit simple, but it works the same if you work with pointers ...

    I hope that clarifies the source code

    - Andi -

  7. #7
    Registered User
    Join Date
    Jan 2010
    Posts
    18
    Quote Originally Posted by Tool View Post
    "Three star programming" - not a good idea.
    Why? Sure, it's a possibly harder to read, but formally correct :-)

  8. #8
    Registered User
    Join Date
    Jul 2009
    Location
    Croatia
    Posts
    272
    Can be done much easier and logical using the method i mentioned above.

    Sure, you can do it that way aswell - but i'd say its bad style.
    Last edited by Tool; 03-13-2010 at 10:51 AM.

  9. #9
    Registered User
    Join Date
    Jan 2010
    Posts
    18
    Quote Originally Posted by Tool View Post
    Can be done much easier and logical using the method i mentioned above.

    Sure, you can do it that way aswell - but i'd say its bad style.
    Okay, I agree. You're right :-)

  10. #10
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by ForzaItalia2006 View Post
    In turn, if you pass the variable by-pseudo-reference in C (because call-by-reference does not exists as in C++)
    This is a little bit semantic since languages other than C++ also use references, some of them differently, but there is no point in saying "compared to language X, C++ uses pass by pseudo-reference, since these kinds of references are not quite the same").

    Going by concept, it does make sense to discuss passing an address (&) as a "pass by reference" technique, just don't use the term in an exam answer.

    I think the 3-star guideline is not simply about style but also form: if you find yourself needing to do this, it's probably because your functions are not modular enough. If a function does one thing well, it can use the return value. It hard to conceive of a situation where you need to pass in a 2D pointer, reassign it, and use the return value for some other purpose.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #11
    Registered User
    Join Date
    Mar 2010
    Posts
    10
    Thanks Tool your corrections also worked =) Also thanks ForzaItalia2006 for explanations =) Generally I know the idea of pointers but just couldn't get the logic of three stars.

    In this piece of code, basically I would like to access any value that is stored in memory that allocated in functions, because I will need this kind of things in a bigger school project... At first I thought, the allocated memory blocks in a function will be freed as local variables but thanks to you now I can use this

    I am new here and I wonder if I could ask opinions about which ways to follow for a programming project?

  12. #12
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Three stars isn't any harder to understand than two. Or four, for that matter. If I have type X, I need a pointer to that type, if I'm going to change the value of it when I pass it to a function. That's all. It's the same if you want to change an int, or a pointer to an int, or a pointer to a pointer to a pointer to an int.

    Whatever it is, if you want to change its value, you need a pointer to it.


    Quzah.
    Hope is the first step on the road to disappointment.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,158
    Quote Originally Posted by quzah
    Three stars isn't any harder to understand than two. Or four, for that matter. If I have type X, I need a pointer to that type, if I'm going to change the value of it when I pass it to a function. That's all. It's the same if you want to change an int, or a pointer to an int, or a pointer to a pointer to a pointer to an int.
    See this discussion on Three Star Programmers. I pretty much agree with MK27, though not so much in terms of modularity of functions, but in terms of abstraction. It is not difficult to understand three levels of indirection when you understand even just one level of indirection, but using three or more levels of indirection often indicates a failure to apply an abstraction appropriately.
    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

  14. #14
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Code:
    matrix = makematrix( X, Y );
    Or...
    Code:
    makematrix( &matrix, X, Y );
    ...both are clear as to what they do. There's not really much difference. Inside the function it may be a bit ugly. But it doesn't have to be:
    Code:
    void makematrix( type ***m, size_t x, size_t y )
    {
        type **t;
    
        t = malloc( sizeof(*t) * y );
        if( t )
        {
            size_t row = y;
            while( row-- )
            {
                t[ row ] = malloc( sizeof( **t ) * x );
            }
            *m = t;
        }
    }
    That looks about right, I've been up forever. But you don't really need to actually use the third star for anything, and still be able to pass the address of a double star. (edit: bugfix with x/y-- to row-- [Z_Z])


    Quzah.
    Last edited by quzah; 03-14-2010 at 11:32 AM.
    Hope is the first step on the road to disappointment.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Compiling C in Visual Studio 2005
    By emanresu in forum C Programming
    Replies: 3
    Last Post: 11-16-2009, 04:25 AM
  2. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM
  3. C++ compilation issues
    By Rupan in forum C++ Programming
    Replies: 1
    Last Post: 08-22-2005, 05:45 AM
  4. Please Help - Problem with Compilers
    By toonlover in forum C++ Programming
    Replies: 5
    Last Post: 07-23-2005, 10:03 AM
  5. qt help
    By Unregistered in forum Linux Programming
    Replies: 1
    Last Post: 04-20-2002, 09:51 AM