Thread: No change effect

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

    No change effect

    Since my coding work is based more on C++, I'm unclear about how to make changes take effect after function call in C.
    Namely, I have the following struct declartion and function call in C
    Code:
    GenGraph* g; // this is from external lib, and declaration without * is 
                        // not allowed (at least, in my opinion)
    myFunct(g);
    printGraphOpt(g); // prints 0, which is default
    with
    Code:
    void myFunc(GenGraph* g) {
         g.opt=1;
    }
    How could I make the change in myFunc take effect?

    Thanks.

  2. #2
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    This looks like an unallocated pointer to me (just like it would be in C++):

    Quote Originally Posted by onako View Post
    Code:
    GenGraph* g; // this is from external lib, and declaration without * is 
                        // not allowed (at least, in my opinion)
    Why, in your opinion, is it not be allowed? Presuming GenGraph really is a sort of struct, you need either:

    Code:
    GenGraph *g = malloc(sizeof(GenGraph));  // heap allocation
     -- OR --
    GenGraph g;  // locally scoped stack allocation
    If you want to pass the second one to myFunc, use the address of operator:

    Code:
    myFunc(&g);
    How could I make the change in myFunc take effect?
    There is no difference between C and C++ in this regard; the change should have taken effect. There is, however, a problem in myFunc() which should result in a compiler error (ie, this code should not compile):

    Code:
    void myFunc(GenGraph* g) {
         g.opt=1;
    }
    You are using direct notation with a pointer, which requires indirect notation:

    Code:
    g->opt=1;
    Again, this is the same in C as it is C++. Here's three guesses as to the cause of your problem:

    1) Because the original *g is just a pointer to a struct, not a struct, and you did not allocate any memory to it.
    2) Because after you wrote myFunc(), your code no longer compiled because of the error, and you are running an executable compiled earlier from different code. Pay attention to the compiler, it is your friend.
    3) GenGraph is not really a struct type (eg, it may be a typedef'd pointer, in which case you should get various warnings and/or further errors).
    Last edited by MK27; 11-03-2011 at 08:21 AM.
    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

  3. #3
    Registered User
    Join Date
    Mar 2010
    Posts
    43
    Thanks for the message. Bellow is the struct content:
    Code:
    http://www.graphviz.org/pub/graphviz/development/doxygen/html/graph_8h_source.html#l00060
    Using
    Code:
    void myFunct( Agraph_t * g) {
        
        FILE *fp;
        /* say there is some fileName*/
        fp=fopen(fileName.c_str(), "r");
        g=agread(fp);
    }
    int main() {    
       Agraph_t* g;
       myFunct(g);
       Agnode_t *n=agfstnode(g);
    }
    everything compiles, but the change of g=agread(fp) does not take effect.
    Changing as proposed,
    Code:
    Agraph_t g;
    myFunct(&g);
    results the following error message:
    Code:
    error: cannot convert ‘Agraph_t’ to ‘Agraph_t*’ for argument ‘1’ to ‘Agnode_t* agfstnode(Agraph_t*)’
    So, the function agfstnode (from external library, as is Agraph_t) requires Agraph_t* as an argument. That was the reason for using it primarily.

    Setting
    Code:
     Agnode_t *n=agfstnode(&g);
    does compile, but the execution terminates at this point.

    Some thoughts?
    Last edited by onako; 11-03-2011 at 09:10 AM.

  4. #4
    Registered User
    Join Date
    Mar 2009
    Posts
    344
    Quote Originally Posted by onako View Post
    Using
    Code:
    void myFunct( Agraph_t * g) {
        
        FILE *fp;
        /* say there is some fileName*/
        fp=fopen(fileName.c_str(), "r");
        g=agread(fp);
    }
    int main() {    
       Agraph_t* g;
       myFunct(g);
       Agnode_t *n=agfstnode(g);
    }
    everything compiles, but the change of g=agread(fp) does not take effect.
    Sure it does, but it's lost as soon as the function ends. That due to C being call by value - the pointer value is copied for the called function and then lost when the function ends.

    Changing as proposed,
    Code:
    Agraph_t g;
    myFunct(&g);
    results the following error message:
    Code:
    error: cannot convert ‘Agraph_t’ to ‘Agraph_t*’ for argument ‘1’ to ‘Agnode_t* agfstnode(Agraph_t*)’
    What's the C operator to get the pointer address of a variable? Hint - you're using it in the call for myFunct. Use it when you call agfsnode also.

  5. #5
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by onako View Post
    everything compiles, but the change of g=agread(fp) does not take effect.
    As KCfromNC hints, this:

    Code:
    g->opt = 1;
    is significantly different from:

    Code:
    g = whatever...
    The first is assigning a value to a member of the struct pointed to by g, but the second re-assigns g locally to something else. If you want to do something like that, myFunc would need a prototype like:

    Code:
    void myFunct( Agraph_t **g);
    Ie, you'd need a pointer to a pointer (**), then you can dereference that and the assignment will not just be local:

    Code:
    *g = whatever;
    This is exactly the same as if you were trying to pass an int value in for assignment:

    Code:
    void myFunc (int *n) {
        *n = 666;
    }
    int x;
    myFunc(&x); 
    // x is now 666
    Changing as proposed,
    Code:
    Agraph_t g;
    myFunct(&g);
    results the following error message:
    Code:
    error: cannot convert ‘Agraph_t’ to ‘Agraph_t*’ for argument ‘1’ to ‘Agnode_t* agfstnode(Agraph_t*)’
    As KCfromNC also hints, this error does not match with the code you've quoted; the function name is different. Don't paraphrase, quote the actual code you are really using. Otherwise, it is hard to say what the problem really is.

    So, the function agfstnode (from external library, as is Agraph_t) requires Agraph_t* as an argument. That was the reason for using it primarily.
    Okay:

    Code:
    void agfstnode(Agraph_t*)
    Agraph_t mygraph;
    agfstnode(&mygraph);
    "&mygraph" is a Agraph_t* (it's the address of an Agraph_t), so if everything is as you say, this should not result in an error.

    Setting
    Code:
     Agnode_t *n=agfstnode(&g);
    does compile, but the execution terminates at this point.
    How do you know that is where the execution terminates, and how does it terminate?
    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

  6. #6
    Registered User
    Join Date
    Mar 2010
    Posts
    43
    The code:
    Code:
    void myFunct(Agraph_t * g, GVC_t * gvc) {
        FILE *fp;
        Agnode_t *v;
        Agedge_t *e;
    
        gvc=gvContext();
        
        // certain fileName
        fp=fopen(fileName.c_str(), "r");
        g=agread(fp);
        
        int assignedID=0; 
        for(v=agfstnode(g); v; v=agnxtnode(g,v)) {
    	v->id=assignedID; ++assignedID;
        } 
    }
    
    int main() {
    Agraph_t g;
    GVC_t* gvc;  
    
    myFunct(&g, gvc);
    Agnode_t *n;
        std::cout<<"Got here 0"<<std::endl;
        n=agfstnode(&g);
        std::cout<<"Got here 1"<<std::endl;
    
    }
    The above code does compile, but the execution produces:
    Code:
    Got here 0
    Segmentation fault
    This is why I think this is the termination point.
    I believe things would be easier with my implementation of data structures, but I'm required to use already existing ones.

  7. #7
    Registered User
    Join Date
    Mar 2009
    Posts
    344
    Why are you not doing what MK27 said you should?

    Code:
    void myFunct( Agraph_t **g);
    Ie, you'd need a pointer to a pointer (**), then you can dereference that and the assignment will not just be local:

    Code:
    *g = whatever;
    This is exactly the same as if you were trying to pass an int value in for assignment:
    Same thing with your other variable.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. How does ++ effect a variable such as var++?
    By JiWiz in forum C++ Programming
    Replies: 1
    Last Post: 07-27-2008, 04:39 PM
  2. Disable 3D effect
    By underline_bruce in forum Windows Programming
    Replies: 1
    Last Post: 08-11-2007, 04:10 PM
  3. cin.get() twice for effect
    By 74466 in forum C++ Programming
    Replies: 16
    Last Post: 03-02-2006, 11:27 AM
  4. effect of following code
    By cruzinny in forum C Programming
    Replies: 2
    Last Post: 10-22-2002, 04:44 PM
  5. What is the effect of this?
    By correlcj in forum C Programming
    Replies: 6
    Last Post: 07-31-2002, 05:26 PM