1

I'm fairly new to C, so please bear with me :) I'm trying to learn the language, and I have found trouble when trying to make changes to elements of the same struct.

Consider the following code:

#include <stdio.h>

struct aStruct{
  int someNum;
};//end wordGuessResources struct

int updateSomeNumber(struct aStruct thing){
  printf("\nBefore updating someNum is %d.", thing.someNum);
  thing.someNum++;
  printf("\nAfter updating someNum is %d.", thing.someNum);
  return 0;
}

int main(){
  struct aStruct thing;
  thing.someNum = 2;
  updateSomeNumber(thing);
  printf("\nIn main, someNum is now %d.", thing.someNum);
  updateSomeNumber(thing);
  printf("\nIn main, someNum is now %d.", thing.someNum);

  return 0;
}//end main

Running this code will produce the output:

Before updating someNum is 2.
After updating someNum is 3.
In main, someNum is now 2.
Before updating someNum is 2.
After updating someNum is 3.
In main, someNum is now 2.

So obviously when I pass thing to updateSomeNumber the first time, it is accepting the same copy of thing because it already knows someNum is 2 (see first line of output).

But what seems to be occurring is that after it affects that value of thing, when we return back to the main function none of the changes seem to have been recorded (because in main the someNum is still 2, not 3).

So I theorize that updateSomeNumber must be taking in a copy of thing that was initially edited in main, but is not modifying the original instance?

If that is indeed the case, how do I pass the exact instance of thing that main uses into a function so that it will affect that instance?

Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
Guy
  • 979
  • 1
  • 11
  • 21
  • Your teacher should have made clear from the beginning that C is **strictly** pass by value - no exceptions. In case you don't have a teacher: a good C book will help; don' try to learn C from particular internet resources. – too honest for this site Mar 21 '17 at 03:06
  • 1
    The structure is passed by value; a copy of the structure in `main()` is passed to the function. The function modifies the copy; it does not, and cannot, affect the original in `main()`. You need to pass a pointer to the structure to the function so you can modify the original. There are consequential notational changes (`.` to `->` etc). – Jonathan Leffler Mar 21 '17 at 03:07
  • Ouch, why the downvote? I read through "How do I ask a good question?" before posting this and tried to make sure everything was as the guide described. I apologize that I did not know about this "pass by value." How do I pass a pointer to a structure in a function? – Guy Mar 21 '17 at 03:11
  • 2
    In `main`, do `updateSomeNumber(&thing);`. Then, change definition of fnc to: `int updateSomeNumber(struct aStruct *thing)`. Then, within fnc, `thing.` --> `thing->` When passing `struct`, virtually all code passes around a pointer. Pass by value, for this, is almost never used, for the reason you ran into. If your struct had 50 different items, with pass-by-value, they would all have to be pushed onto the stack, making the code slow. – Craig Estey Mar 21 '17 at 03:15
  • 1
    @CraigEstey Okay, perfect! That makes sense. I see now, so I pass the address of the struct to the function, and then use only refer to pointers of values within the function while editing them. I understand now, thank you! – Guy Mar 21 '17 at 03:25
  • 1
    I do apologize for whatever I did wrong in the question that brought the downvote, though. Could someone explain to me what I did wrong so I can fix it? – Guy Mar 21 '17 at 03:26
  • @Guy what is your source that you are learning from? The `void main` and the `printf` with the `\n` at the beginning instead of the end of the strings are very suspicious of a certain dangerous book full of complete nonsense. – Roland Illig Mar 21 '17 at 03:31
  • @RolandIllig I just used `void main()` since is was just some short example code and not a full program. Usually for full programs I write `int main()` and return a 0 if everything completed successfully. I didn't realize, is void main() bad? I had just thought it didn't matter much since it didn't affect the program. – Guy Mar 21 '17 at 03:36
  • 1
    https://stackoverflow.com/questions/204476/what-should-main-return-in-c-and-c – Roland Illig Mar 21 '17 at 03:42
  • A-ha, I see! Thank you for informing me, I will remember that from now on! – Guy Mar 21 '17 at 03:46
  • 1
    Re the downvote. Some users nitpick over the littlest thing and DV quickly [e.g. 60 secs]. There are some chatrooms expressly for DV. That is, one member of a "cabal" finds a question that they don't like, DV it, then ask other cabal members to do the same. One can get DV'ed quickly then. At least one of the commenters here is known [by me, at least] to have a hair trigger. So, to compensate, I upvoted [IMO, your post met the criteria]. Those with "trigger fingers" usually leave [unhelpful] cmts pointing out a flaw but no help. _Most_ people here _are_ helpful. You were just unlucky ... – Craig Estey Mar 21 '17 at 04:03
  • Okay, thank you very much. I think I've had experience with these "trigger fingers" before, that's why I try to be so extremely careful when posting questions here any more because a lot of times I just get downvoted for one small thing, and then get threatened by Stack Exchange to ask more well-received questions. – Guy Mar 21 '17 at 04:12
  • 1
    ... DV continued. Valid reason to DV is for non-responsive, snide, arrogant OPs that refuse to fix a bad question, even after someone gives suggestions in comments. As to snide commenters, I gave an answer on a post, got upvoted/accepted to a question where a commenter was harassing the OP over a nit. I checked back a few hours later and noticed cmt'er went from 20k rep to 1pt. Turns out the user had _just_ gotten a 1 year [max penalty] suspension from SO for such behavior. And, such a suspension requires repeated offences and the user will be warned [in email] first – Craig Estey Mar 21 '17 at 04:12
  • 1
    DV #3. BTW, it happens more because of low rep. As you gain more rep, the heckling tends to stop. My answers have [IMO] always been of the same quality, but I got heckled a bit until I reached about 500 rep. In one case, a cmt'er under an answer of mine went 5 rounds saying I didn't even answer the question correctly. But, OP checked mine as the accepted one [already]. I'm also on slashdot, and there was a post there that referred to this link: https://hackernoon.com/the-decline-of-stack-overflow-7cb69faa575d#.c7zx9rvit that may give insight/comfort – Craig Estey Mar 21 '17 at 04:27
  • @CraigEstey I know that it's bad form to have discussions in the comments, but I have to add one more thing: Wow is it encouraging to see that other people view this site in the same way I do, and have experienced the exact same stuff I have. I have had all those exact same things described in that article happen to me. I'm glad to know that among all the overzealous trolls, though, there are still a few legitimately kind and reasonable people like you trying to help people out with their coding questions :) – Guy Mar 21 '17 at 04:59
  • @CraigEstey: if you are sure there are "cabals" of downvoters, do get in touch with Stack Overflow and let them know. There is one chatroom (on SO itself) that allows collective close/deletion votes, but that is expressly permitted by SO staff as they have a positive impact on site quality (I help them out from time to time). – halfer Jan 19 '18 at 21:33
  • Other than that, it's worth noting there is no universally agreed set of guidelines about when one should downvote - the only red line is that one should not vote by user (serial voting). The author of the "Decline" article is welcome to his views, but makes so many errors of fact, it's not worth taking as gospel. The battle about how much we should [Be Nice](https://stackoverflow.com/help/be-nice) will always rage on! – halfer Jan 19 '18 at 21:36
  • My advice to newcomers is generally to ignore the odd downvote, rather than to whip up resentment against it. Voting is all we have to separate us from the likes of Reddit, Quora, or even Yahoo Answers, and they can't touch SO for quality, waffle-free, _maintained_ material. FWIW I'd' like for a new challenger to enter, but it's going to be an uphill battle for any start-up to take on. – halfer Jan 19 '18 at 21:39

1 Answers1

2

You need to use Pointers. Basically, you need to pass the address of your thing struct, instead of thing itself to your update function. And then your update function needs to update the thing at the address received as function argument. See the following example:

#include <stdio.h>

struct aStruct{
  int someNum;
};//end wordGuessResources struct

int updateSomeNumber(struct aStruct * thing){
  printf("\nBefore updating someNum is %d.", thing->someNum);
  thing->someNum++;
  printf("\nAfter updating someNum is %d.", thing->someNum);
  return 0;
}

void main(){
  struct aStruct thing;
  thing.someNum = 2;
  updateSomeNumber(&thing);
  printf("\nIn main, someNum is now %d.", thing.someNum);
  updateSomeNumber(&thing);
  printf("\nIn main, someNum is now %d.", thing.someNum);
}//end main

Here is the output:

Before updating someNum is 2.                                                                                                                                                   
After updating someNum is 3.                                                                                                                                                    
In main, someNum is now 3.                                                                                                                                                      
Before updating someNum is 3.                                                                                                                                                   
After updating someNum is 4.                                                                                                                                                    
In main, someNum is now 4.
VHS
  • 9,534
  • 3
  • 19
  • 43
  • The words _thing itself_ are misleading, since a _copy_ of the main thing is passed. – Roland Illig Mar 21 '17 at 03:24
  • Thank you, this makes sense. This information is the same that @CraigEstey put in his comment, and since he commented it first I'll give him an opportunity to post it as an answer. But if he doesn't post one I will accept yours. Thank you guys both :) – Guy Mar 21 '17 at 03:30
  • @Guy, I didn't read his or anyone's comment before posting my answer. Posting a full fledged answer like above takes time than posting a comment does. But choice is yours. – VHS Mar 21 '17 at 03:32
  • I did upvote the answer regardless, because it answers the question. It doesn't seem like an answer from Craig is forthcoming, though, so I'll accept this. – Guy Mar 21 '17 at 03:38
  • @RolandIllig is it misleading to say `f(5)` passes 5 to `f`? Should I say it passes a copy of 5? – user253751 Mar 21 '17 at 03:55
  • The actual thing is assigned to the parameter - and this assignment creates a new variable with the same value - which of course is a copy. – Antti Haapala -- Слава Україні Mar 21 '17 at 04:29