943,431 Members | Top Members by Rank

Ad:
  • C Discussion Thread
  • Unsolved
  • Views: 2947
  • C RSS
Sep 19th, 2004
0

A puzzl about function

Expand Post »
I don't how to description this puzzle, just like this:

  1. int *fun_num()
  2. {
  3. int b = 123;
  4. return &b;
  5. }
  6.  
  7. char *fun_char()
  8. {
  9. char *b = "123";
  10. return b;
  11. }
  12.  
  13. int main(int argc, char *argv[])
  14. {
  15. int *pfun;
  16. char *pchar;
  17. pfun = fun_num();
  18. pchar = fun_char();
  19.  
  20. cout << *pfun << endl;
  21. cout << *fun_num() << endl;
  22. cout << pchar << endl;
  23. cout << fun_char() << endl;
  24. }
//===============Result==============
4335768 // this is right to delete object "b"
123 // this is the return value
123 // why the object "b" isn't deleted? <---puzzle at here
123
Similar Threads
Reputation Points: 15
Solved Threads: 0
Newbie Poster
XianBin is offline Offline
24 posts
since Aug 2004
Sep 19th, 2004
0

Re: A puzzl about function

Greeting XianBin,

Pointers can be somewhat confusing, but let's see if we can go through this code one step at a time. It may help the understanding of how it works, and how useful these techniques can be.

Let's disect the functions first:

int *fun_num() {
	int b = 123;
	return &b;
}
» What this does, is it creates an integer b, and returns the memory address of this variable. That's why the function's return-type is "int *".

char *fun_char() {
	char *b = "123";
	return b;
}
» This does almost the same thing, as it creates a variable "char *" and returns it. Not the memory address since an array name is a pointer. If you were to send the memory address, then you would need to change the return-type to "char **". Oh, and the b variable would need a real block of memory, since right now it is only staticly created.

Now moving inside main, lets take a look at our routines:
int *pfun;
char *pchar;
» These are your local variables. One is a pointer to an integer, and the other, a char array [or pointer]. The "char *" array only needs data, though the integer pointer needs the memory address to look at the data we send.

  1. pfun = fun_num();
» Ah, the messy stuff. Well, this is quite simple, so I'll explain it as simple as possible. This contains pfun. If you may know, pfun is not the actual data itself, its the address. Remember in fun_num() we returned the address of our local variable b, well that address will be sent directly to pfun. Now in order to read the data passed through the address we would be smart to use the unary operator "*".

The reason you need the unary (*) operator, is because we sent the memory address to our function. Let me clarify. If a variable contains data here (d) and its memory address is here (m), I would need to get to (m)->(d) to access the data from the address sent. Likewise, the * operator allows me to read the data from the address. Using the * will point to the data instead of looking or modifying the address. So overall, pfun is our address, and *pfun is our data from our address.

  1. pchar = fun_char();
» This is somewhat the same, but different. Remember that this will only contain the data without touching the address. This syntax is correct since with the previous line of code we sent address to address, but now we are sending data to data.

  1. cout << *pfun << endl;
» Ah, we are reading our data here.

  1. cout << *fun_num() << endl;
» Same address, doesn't matter where we call it. Reading the same data as *pfun.

  1. cout << pchar << endl;
» Remember, pchar is now reading whatever fun_char() holds. They aren't exactly linked like pointers and addresses, but you sent the data from our function to our variable. As long as that occurs, the data will still be there. It can't be delete either, since b isn't exactly our property to touch in fun_char(). It's dynamically out there somewhere.

  1. cout << fun_char() << endl;
» Same data, but not same address. If this function were to have allocated a memory block we could possibly send the address anywhere we want.

Conclusion
Though it isn't recommended to do a statement like so:
char *b = "123";
I don't want to be harsh or anything telling you it isn't safe or anything like that. Using malloc() may save you some headache down the line, but I'll explain that when you're ready or have learned it and/or have further questions about it.

I hope this information has helped you in great detail. If you have any further questions, please feel free to ask.


- Stack Overflow
Reputation Points: 26
Solved Threads: 4
Junior Poster
Stack Overflow is offline Offline
185 posts
since Sep 2004
Sep 19th, 2004
0

Re: A puzzl about function

Quote originally posted by Stack Overflow ...
Now moving inside main, lets take a look at our routines:
int *pfun;
  char *pchar;
» These are your local variables. One is a pointer to an integer, and the other, a char array [or pointer].
An array is not a pointer. The fewer times folks are told this, the better.
Team Colleague
Reputation Points: 2780
Solved Threads: 312
long time no c
Dave Sinkula is offline Offline
4,790 posts
since Apr 2004
Sep 19th, 2004
0

Re: A puzzl about function

>Though it isn't recommended to do a statement like so
Right answer, wrong reason. Assigning a string literal to a pointer to char is a deprecated feature in C++. The correct way would be:
  1. const char *b = "123";
>why the object "b" isn't deleted? <---puzzle at here
Not to take away from Stack Overflow's answer, but I can summarize. The memory for b is released, but the memory for what b points to is not. The reason is that string literals have static storage duration. In other words, the memory exists and can be accessed (but never modified) for the duration of the program as long as you have a pointer to it.
Administrator
Reputation Points: 6442
Solved Threads: 1393
Bad Cop
Narue is offline Offline
11,807 posts
since Sep 2004
Sep 27th, 2004
0

Re: A puzzl about function

a net friend suggested me to try to make the assemble file and reading it,so I try to do it,then I konw clearly what the promgram does.
I try to introduce it, I hope everyone to understand what I said, because my English so poor.


==================The problem description==================
  1. [....]
  2. _TEXT segment byte public 'CODE'
  3. _fun_num proc near
  4. [...]
  5. mov word ptr [bp-2],123 ; The Number '123' is saved in the [bp-2] addr.
  6.  
  7. lea ax,word ptr [bp-2] ; Address is saved in AX reg.
  8. [...]
  9. ret
  10. _fun_num endp
  11. _TEXT ends
  12.  
  13. [...]
  14.  
  15. _TEXT segment byte public 'CODE'
  16. _fun_char proc near
  17. push si ; Now the SP pointer is pointing to the Number '123' 's addr.
  18. mov si,offset DGROUP:s@ ; Will Load the "123" strings.
  19. mov ax,si ; Loading the "123" strings. It overwrited the '123' numbers.This is why the result is unknown.
  20. [...]
  21. ret
  22. _fun_char endp
  23. _TEXT ends
  24.  
  25. _TEXT segment byte public 'CODE'
  26. _main proc near
  27. push bp
  28. mov bp,sp
  29. push si
  30. push di
  31.  
  32. call near ptr _fun_num
  33. mov si,ax
  34.  
  35. call near ptr _fun_char
  36. mov di,ax
  37. [...]
  38.  

==============Writing By C Code==============
  1. #include<stdio.h>
  2.  
  3. int *fun_num()
  4. {
  5. int b = 123;
  6. return &b;
  7. }
  8.  
  9. char *fun_char()
  10. {
  11. char *b = "123";
  12. return b;
  13. }
  14.  
  15. int main(int argc, char *argv[])
  16. {
  17. int *pfun;
  18. char *pchar;
  19. pfun = fun_num();
  20. pchar = fun_char();
  21.  
  22. printf("pfun=%d\n",*pfun);
  23. printf("fun_num()=%d\n",*fun_num());
  24. printf("pchar=%s\n",*pchar);
  25. printf("fun_char()=%s\n",*fun_char());
  26.  
  27. return 0;
  28. }
----------------Assemble Code----------------
  1. ifndef ??version
  2. ?debug macro
  3. endm
  4. endif
  5. ?debug S "function.c"
  6. _TEXT segment byte public 'CODE'
  7. DGROUP group _DATA,_BSS
  8. assume cs:_TEXT,ds:DGROUP,ss:DGROUP
  9. _TEXT ends
  10. _DATA segment word public 'DATA'
  11. d@ label byte
  12. d@w label word
  13. _DATA ends
  14. _BSS segment word public 'BSS'
  15. b@ label byte
  16. b@w label word
  17. ?debug C E99DBA3B310A66756E6374696F6E2E63
  18. _BSS ends
  19. _TEXT segment byte public 'CODE'
  20. ; ?debug L 1
  21. _fun_num proc near
  22. push bp
  23. mov bp,sp
  24. sub sp,2
  25. ; ?debug L 3
  26. mov word ptr [bp-2],123
  27. ; ?debug L 4
  28. lea ax,word ptr [bp-2]
  29. jmp short @1
  30. @1:
  31. ; ?debug L 5
  32. mov sp,bp
  33. pop bp
  34. ret
  35. _fun_num endp
  36. _TEXT ends
  37. _DATA segment word public 'DATA'
  38. _DATA ends
  39. _TEXT segment byte public 'CODE'
  40. ; ?debug L 7
  41. _fun_char proc near
  42. push si
  43. ; ?debug L 9
  44. mov si,offset DGROUP:s@
  45. ; ?debug L 10
  46. mov ax,si
  47. jmp short @2
  48. @2:
  49. ; ?debug L 11
  50. pop si
  51. ret
  52. _fun_char endp
  53. _TEXT ends
  54. _DATA segment word public 'DATA'
  55. _DATA ends
  56. _TEXT segment byte public 'CODE'
  57. ; ?debug L 13
  58. _main proc near
  59. push bp
  60. mov bp,sp
  61. push si
  62. push di
  63. ; ?debug L 17
  64. call near ptr _fun_num
  65. mov si,ax
  66. ; ?debug L 18
  67. call near ptr _fun_char
  68. mov di,ax
  69. ; ?debug L 20
  70. push word ptr [si]
  71. mov ax,offset DGROUP:s@+4
  72. push ax
  73. call near ptr _printf
  74. pop cx
  75. pop cx
  76. ; ?debug L 21
  77. call near ptr _fun_num
  78. mov bx,ax
  79. push word ptr [bx]
  80. mov ax,offset DGROUP:s@+13
  81. push ax
  82. call near ptr _printf
  83. pop cx
  84. pop cx
  85. ; ?debug L 22
  86. mov al,byte ptr [di]
  87. cbw
  88. push ax
  89. mov ax,offset DGROUP:s@+27
  90. push ax
  91. call near ptr _printf
  92. pop cx
  93. pop cx
  94. ; ?debug L 23
  95. call near ptr _fun_char
  96. mov bx,ax
  97. mov al,byte ptr [bx]
  98. cbw
  99. push ax
  100. mov ax,offset DGROUP:s@+37
  101. push ax
  102. call near ptr _printf
  103. pop cx
  104. pop cx
  105. ; ?debug L 25
  106. xor ax,ax
  107. jmp short @3
  108. @3:
  109. ; ?debug L 26
  110. pop di
  111. pop si
  112. pop bp
  113. ret
  114. _main endp
  115. _TEXT ends
  116. ?debug C E9
  117. _DATA segment word public 'DATA'
  118. s@ label byte
  119. db 49
  120. db 50
  121. db 51
  122. db 0
  123. db 112
  124. db 102
  125. db 117
  126. db 110
  127. db 61
  128. db 37
  129. db 100
  130. db 10
  131. db 0
  132. db 102
  133. db 117
  134. db 110
  135. db 95
  136. db 110
  137. db 117
  138. db 109
  139. db 40
  140. db 41
  141. db 61
  142. db 37
  143. db 100
  144. db 10
  145. db 0
  146. db 112
  147. db 99
  148. db 104
  149. db 97
  150. db 114
  151. db 61
  152. db 37
  153. db 115
  154. db 10
  155. db 0
  156. db 102
  157. db 117
  158. db 110
  159. db 95
  160. db 99
  161. db 104
  162. db 97
  163. db 114
  164. db 40
  165. db 41
  166. db 61
  167. db 37
  168. db 115
  169. db 10
  170. db 0
  171. _DATA ends
  172. _TEXT segment byte public 'CODE'
  173. extrn _printf:near
  174. _TEXT ends
  175. public _fun_char
  176. public _fun_num
  177. public _main
  178. end
Reputation Points: 15
Solved Threads: 0
Newbie Poster
XianBin is offline Offline
24 posts
since Aug 2004

This thread is more than three months old

No one has posted to this discussion for at least three months. Please let old threads die and do not reply to them unless you feel you have something new and valuable to contribute that absolutely must be added to make the discussion complete. Otherwise, please start a new thread in this forum instead.
Message:
Previous Thread in C Forum Timeline: Using a for loop to sum an integer n and call function add_it
Next Thread in C Forum Timeline: Problem with working with math in C





About Us | Contact Us | Advertise | Acceptable Use Policy
Forum Index | Build Custom RSS Feed


Follow us on Twitter


© 2011 DaniWeb® LLC