problem returning pointer from function
Author |
Message |
Victor Fe #1 / 12
|
 problem returning pointer from function
I think that this should work, but it doesn't. Inside the function, *(new_deck + i) prints just fine. Back in main, I only get: 1 1 1 1 2 2 2 2 3 3 3 3 4 4 4 4 872415237 0 1 1244787 0 0 4207541 0 2012894640 2012660170 2147348480 4262560 1244872 4199215 0 4262560 Here's the code: both solutions and general critique are welcome. #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCARDS 40 int * shuffle_cards(void); int main(int argc, char * argv[]) { int deck[MAXCARDS]; int * deck_ptr; int i; deck_ptr = malloc(sizeof(deck[MAXCARDS])); deck_ptr = shuffle_cards(); for (i = 0; i < MAXCARDS; i++) printf("%d\n", *(deck_ptr + i)); return (0); Quote: }
int * shuffle_cards(void) { int i; int * new_deck; int deck[MAXCARDS] = { 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5, 6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10 }; new_deck = deck; for (i = 0; i < MAXCARDS; i++) printf("%d\n", *(new_deck + i)); return new_deck; Quote: }
Please remove obvious characters from my e-mail address when e-mailing me.
|
Sun, 01 Jul 2001 03:00:00 GMT |
|
 |
Jason Lo #2 / 12
|
 problem returning pointer from function
You have misunderstood pointers and the scope of variables. See my comments throughout the code. Email me if you have any further questions. To illustrate my point, move the integer array "deck" before main and make it global. This will now work. This illustrates the "local scope" of the integer array "deck". BUT stay away from global variiables. Keep everything as local as possible. Pass pointers, return values... #include <stdio.h> #include <stdlib.h> #include <string.h> #define MAXCARDS 40 int * shuffle_cards(void); int main(int argc, char * argv[]) { int deck[MAXCARDS]; // not used! int * deck_ptr; int i; // correct! you have allocated memory correctly - you never // use this block of memory however!!! deck_ptr = malloc(sizeof(deck[MAXCARDS])); // with the following statement you've overridden the above // memory pointer deck_ptr = shuffle_cards(); // you are now trying to print an integer array that has // been deallocated from the stack!!! The "garbage" you see // are other variables overwriting the integer array "deck" for (i = 0; i < MAXCARDS; i++) printf("%d\n", *(deck_ptr + i)); return (0); Quote: }
int * shuffle_cards(void) { int i; int * new_deck; int deck[MAXCARDS] = { 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5, 6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10 }; new_deck = deck; for (i = 0; i < MAXCARDS; i++) printf("%d\n", *(new_deck + i)); // you cannot return new_deck like this. // new_deck points to the integer array "deck" which is // deallocated when the function returns. The variable scope // of "deck" is limited to this function!! return new_deck; Quote: }
|
Sun, 01 Jul 2001 03:00:00 GMT |
|
 |
JF_Sebastia #3 / 12
|
 problem returning pointer from function
Quote:
>I think that this should work, but it doesn't. Inside the function, >*(new_deck + i) prints just fine.
[snip] Quote: >Here's the code: both solutions and general critique are welcome. >#include <stdio.h> >#include <stdlib.h> >#include <string.h> >#define MAXCARDS 40 >int * shuffle_cards(void); >int main(int argc, char * argv[]) >{ > int deck[MAXCARDS]; > int * deck_ptr; > int i; > deck_ptr = malloc(sizeof(deck[MAXCARDS])); > deck_ptr = shuffle_cards(); > for (i = 0; i < MAXCARDS; i++) > printf("%d\n", *(deck_ptr + i)); > return (0); >} >int * shuffle_cards(void) >{ > int i; > int * new_deck; > int deck[MAXCARDS] = { > 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5, > 6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10 > }; > new_deck = deck; > for (i = 0; i < MAXCARDS; i++) > printf("%d\n", *(new_deck + i)); > return new_deck; ===> The variable deck is local to the
shuffle_cards() routine ! It is allocated on the stack when the routine is called and removed when the routine returns ! Quote: >}
Bye
|
Sun, 01 Jul 2001 03:00:00 GMT |
|
 |
Stephan Wilm #4 / 12
|
 problem returning pointer from function
Quote:
> // correct! you have allocated memory correctly - you never > // use this block of memory however!!! > deck_ptr = malloc(sizeof(deck[MAXCARDS]));
This might indeed allocate memory, but certainly not the correct amount. "deck[MAXCARDS]" represents one integer, and a nonexistant one at that. Thus if the allocation succeeds it will have allocated memory for exactly one integer. And one more remark: never forget to check the return value of "malloc()" ! Quote: > // with the following statement you've overridden the above > // memory pointer > deck_ptr = shuffle_cards();
Exactly. Something like: "shuffle_cards( deck );" would be more apropriate, for an initialised "deck" of cards. Quote: > // you are now trying to print an integer array that has > // been deallocated from the stack!!! The "garbage" you see > // are other variables overwriting the integer array "deck" > for (i = 0; i < MAXCARDS; i++) > printf("%d\n", *(deck_ptr + i));
The resulting output is in fact an incarnation of Undefined Behaviour. The code might as well crash the program or cause Stanford Wallace to fly out of your ears. Quote: > return (0); > } > int * shuffle_cards(void) > { > int i; > int * new_deck; > int deck[MAXCARDS] = { > 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5, > 6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10 > }; > new_deck = deck;
I do wonder what this statement is meant to achieve. It sets the pointer "new_deck" to point to the local variable "deck", but why ? Quote: > for (i = 0; i < MAXCARDS; i++) > printf("%d\n", *(new_deck + i)); > // you cannot return new_deck like this. > // new_deck points to the integer array "deck" which is > // deallocated when the function returns. The variable scope > // of "deck" is limited to this function!! > return new_deck; > }
Here's a version that might give the original poster a starting point. It will not shuffle anything, but it will do what his code was very likely meant to do, ie. overwrite the array in main with new contents. void shuffle_cards( int *deck ) { int i; int new_deck[MAXCARDS] = { 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5, 6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10 }; /* This overwrites the original deck with the new deck. */ for ( i=0 ; i < MAXCARDS ; i++ ) deck[i] = new_deck[i]; } Stephan (initiator of the campaign against grumpiness in c.l.c)
|
Sun, 01 Jul 2001 03:00:00 GMT |
|
 |
spence #5 / 12
|
 problem returning pointer from function
much good advice here -- just one more thing: don't forget to free your allocations. not all OSs will clean this up for you. -spence Quote:
> I think that this should work, but it doesn't. Inside the function, > *(new_deck + i) prints just fine. > Back in main, I only get: > 1 > 1 > 1 > 1 > 2 > 2 > 2 > 2 > 3 > 3 > 3 > 3 > 4 > 4 > 4 > 4 > 872415237 > 0 > 1 > 1244787 > 0 > 0 > 4207541 > 0 > 2012894640 > 2012660170 > 2147348480 > 4262560 > 1244872 > 4199215 > 0 > 4262560 > Here's the code: both solutions and general critique are welcome. > #include <stdio.h> > #include <stdlib.h> > #include <string.h> > #define MAXCARDS 40 > int * shuffle_cards(void); > int main(int argc, char * argv[]) > { > int deck[MAXCARDS]; > int * deck_ptr; > int i; > deck_ptr = malloc(sizeof(deck[MAXCARDS])); > deck_ptr = shuffle_cards(); > for (i = 0; i < MAXCARDS; i++) > printf("%d\n", *(deck_ptr + i)); > return (0); > } > int * shuffle_cards(void) > { > int i; > int * new_deck; > int deck[MAXCARDS] = { > 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5, > 6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10 > }; > new_deck = deck; > for (i = 0; i < MAXCARDS; i++) > printf("%d\n", *(new_deck + i)); > return new_deck; > } > Please remove obvious characters from my e-mail address when e-mailing me.
|
Sun, 01 Jul 2001 03:00:00 GMT |
|
 |
Jason Lo #6 / 12
|
 problem returning pointer from function
Victor, After listening to the advice from several experienced programmers see if you can re-write the program again. We'll give you more constructive critism until your program is free from bugs and bad programming practises. Re-write your program and post it out again. Jason
|
Sun, 01 Jul 2001 03:00:00 GMT |
|
 |
Lawrence Kir #7 / 12
|
 problem returning pointer from function
Quote:
>much good advice here -- just one more thing: >don't forget to free your allocations. not all OSs will clean this up for >you.
That's certainly good practice in most cases. However be aware that the concepts of freeing malloc'd memory and releasing program resources back to the OS when the program terminates are two essentially unrelated concepts. Can you name an OS that doesn't clean up properly? (this was discussed recently on comp.lang.c.moderated) -- -----------------------------------------
-----------------------------------------
|
Mon, 02 Jul 2001 03:00:00 GMT |
|
 |
Victor Fe #8 / 12
|
 problem returning pointer from function
OK, here's the new and improved code, and it appears to do what I had hoped. I am a bit confused about how to free this memory. I can't free(deck_ptr) before I exit main, can I? #include <stdio.h> #include <stdlib.h> #include <time.h> #define MAXCARDS 40 int * shuffle_cards(int * d_ptr); int main(int argc, char * argv[]) { int deck[MAXCARDS] = { 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5, 6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10 }; int * deck_ptr; int i; deck_ptr = shuffle_cards(deck); for (i = 0; i < MAXCARDS; i++) printf("%d\n", *(deck_ptr + i)); return (0); Quote: }
int * shuffle_cards(int * d_ptr) { int j=0; int pos; int * new_deck; int high_spot = MAXCARDS - 1; srand( (unsigned)time( NULL ) ); j = 0; new_deck=malloc(sizeof(*d_ptr)); /* Randomize the deck */ while (high_spot > 0) { pos = (rand() % high_spot) + 1; *(new_deck + j) = *(d_ptr + pos); *(d_ptr + pos) = *(d_ptr + high_spot); j++; high_spot--; if (high_spot == 0) *(new_deck + j) = *(d_ptr); } return new_deck; Quote: }
Quote:
>Victor, >After listening to the advice from several experienced programmers see >if you can re-write the program again. >We'll give you more constructive critism until your program is free >from bugs and bad programming practises. >Re-write your program and post it out again. >Jason
Please remove obvious characters from my e-mail address when e-mailing me.
|
Mon, 02 Jul 2001 03:00:00 GMT |
|
 |
Greg Lime #9 / 12
|
 problem returning pointer from function
If you are going to exit the program, there is no particular need to free() one or another of your dynamically allocated chunks of memory. But it is a good idea to be in the habit of knowing who is allocating memory and who is responsible for freeing it; larger systems that persist for longer times demand careful management. With this thought in mind, sometimes it is useful to seek algorithms that do not require allocation of memory. Card deck shuffling is one of these, if there is no reason to maintain the image of the deck as it was before you shuffled. I'm assuming that your interest here is to randomize the deck, not to simulate one or another of the actual card shuffling algorithms ... I'd generally pass the number of cards as a parameter to the shuffle routine, but for now let's keep your calling sequence in tact: #define MAXCARDS ... /* your number here */ int * shuffle_cards(int *deck) { int ncard = MAXCARDS; /* cct is how many cards are in the deck to ** be shuffled. Each time around the loop, ** we pull one random card to be the "last" ** card in the deck, then loop back to shuffle ** the rest of them. */ while (ncard-- > 1) { /* "which" may be "lastv" here: we might use the old ** last card as the new last card. Feel free to use ** a random number generator better than "rand". */ int which = rand() % (ncard +1); int lastv = deck[ncard]; deck[ncard] = deck[which]; deck[which] = lastv; } return deck; Quote: }
>OK, here's the new and improved code, and it appears to do what I had >hoped. >I am a bit confused about how to free this memory. I can't >free(deck_ptr) before I exit main, can I? >#include <stdio.h> >#include <stdlib.h> >#include <time.h> >#define MAXCARDS 40 >int * shuffle_cards(int * d_ptr); >int main(int argc, char * argv[]) >{ > int deck[MAXCARDS] = { > 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5, > 6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10 > }; > int * deck_ptr; > int i; > deck_ptr = shuffle_cards(deck); > for (i = 0; i < MAXCARDS; i++) > printf("%d\n", *(deck_ptr + i)); > return (0); >} >int * shuffle_cards(int * d_ptr) >{ > int j=0; > int pos; > int * new_deck; > int high_spot = MAXCARDS - 1; > srand( (unsigned)time( NULL ) ); > j = 0; > new_deck=malloc(sizeof(*d_ptr)); > /* Randomize the deck */ > while (high_spot > 0) { > pos = (rand() % high_spot) + 1; > *(new_deck + j) = *(d_ptr + pos); > *(d_ptr + pos) = *(d_ptr + high_spot); > j++; > high_spot--; > if (high_spot == 0) > *(new_deck + j) = *(d_ptr); > } > return new_deck; >}
|
Mon, 02 Jul 2001 03:00:00 GMT |
|
 |
PEReynol #10 / 12
|
 problem returning pointer from function
Quote:
>I think that this should work, but it doesn't. Inside the function, >*(new_deck + i) prints just fine. >Back in main, I only get: >1 >1 >1 >1 >2 >2 >2 >2 >3 >3 >3 >3 >4 >4 >4 >4 >872415237 >0 >1 >1244787 >0 >0 >4207541 >0 >2012894640 >2012660170 >2147348480 >4262560 >1244872 >4199215 >0 >4262560 >Here's the code: both solutions and general critique are welcome. >#include <stdio.h> >#include <stdlib.h> >#include <string.h> >#define MAXCARDS 40 >int * shuffle_cards(void); >int main(int argc, char * argv[]) >{ > int deck[MAXCARDS]; > int * deck_ptr; > int i; > deck_ptr = malloc(sizeof(deck[MAXCARDS])); > deck_ptr = shuffle_cards(); > for (i = 0; i < MAXCARDS; i++) > printf("%d\n", *(deck_ptr + i)); > return (0); >} >int * shuffle_cards(void) >{ > int i; > int * new_deck; > int deck[MAXCARDS] = { > 1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5, > 6,6,6,6,7,7,7,7,8,8,8,8,9,9,9,9,10,10,10,10 > }; > new_deck = deck; > for (i = 0; i < MAXCARDS; i++) > printf("%d\n", *(new_deck + i)); > return new_deck; >}
The main problem I see is that you declare deck within the function and are trying to pass it back to main. Yet deck is declared on the stack so when you exit that function deck's address may no longer be valid. the address space has been freed from the stack and is available for other C functions and the data in it may be inadvertently over-written. Malloc the area for deck, initialize it, and pass that address back to the calling program which will free it when done.
|
Sun, 15 Jul 2001 03:00:00 GMT |
|
|
|