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

int *fun_num()
{
   int b = 123;
  return &b;
}

char *fun_char()
{
  char *b = "123";
  return b;
}

int main(int argc, char *argv[])
{
  int *pfun;
  char *pchar;
  pfun = fun_num();
  pchar = fun_char();
  
  cout << *pfun << endl;
  cout << *fun_num() << endl;
  cout << pchar << endl;
  cout << fun_char() << endl;
}

//===============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

Recommended Answers

All 4 Replies

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.

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.

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.

cout << *pfun << endl;

» Ah, we are reading our data here.

cout << *fun_num() << endl;

» Same address, doesn't matter where we call it. Reading the same data as *pfun.

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.

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

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.

>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:

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.

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==================

[....]
_TEXT	segment	byte public 'CODE'
_fun_num	proc	near
	[...]
	mov	word ptr [bp-2],123  ; The Number '123' is saved in the [bp-2] addr. 

	lea	ax,word ptr [bp-2]   ; Address is saved in AX reg.
	[...]
	ret	
_fun_num	endp
_TEXT	ends

[...]

_TEXT	segment	byte public 'CODE'
_fun_char	proc	near
	push	si	; Now the SP pointer is pointing to the Number '123' 's addr.
	mov	si,offset DGROUP:s@	; Will Load the "123" strings.
	mov	ax,si	; Loading the "123" strings. It overwrited the '123' numbers.This is why the result is unknown.
	[...]
	ret	
_fun_char	endp
_TEXT	ends

_TEXT	segment	byte public 'CODE'
_main	proc	near
	push	bp
	mov	bp,sp
	push	si
	push	di

	call	near ptr _fun_num
	mov	si,ax

	call	near ptr _fun_char
	mov	di,ax
[...]

==============Writing By C Code==============

#include<stdio.h>

int *fun_num()
{
   int b = 123;
  return &b;
}

char *fun_char()
{
  char *b = "123";
  return b;
}

int main(int argc, char *argv[])
{
  int *pfun;
  char *pchar;
  pfun = fun_num();
  pchar = fun_char();

  printf("pfun=%d\n",*pfun);
  printf("fun_num()=%d\n",*fun_num());
  printf("pchar=%s\n",*pchar);
  printf("fun_char()=%s\n",*fun_char());

  return 0;
}

----------------Assemble Code----------------

ifndef	??version
?debug	macro
	endm
	endif
	?debug	S "function.c"
_TEXT	segment	byte public 'CODE'
DGROUP	group	_DATA,_BSS
	assume	cs:_TEXT,ds:DGROUP,ss:DGROUP
_TEXT	ends
_DATA	segment word public 'DATA'
d@	label	byte
d@w	label	word
_DATA	ends
_BSS	segment word public 'BSS'
b@	label	byte
b@w	label	word
	?debug	C E99DBA3B310A66756E6374696F6E2E63
_BSS	ends
_TEXT	segment	byte public 'CODE'
;	?debug	L 1
_fun_num	proc	near
	push	bp
	mov	bp,sp
	sub	sp,2
;	?debug	L 3
	mov	word ptr [bp-2],123
;	?debug	L 4
	lea	ax,word ptr [bp-2]
	jmp	short @1
@1:
;	?debug	L 5
	mov	sp,bp
	pop	bp
	ret	
_fun_num	endp
_TEXT	ends
_DATA	segment word public 'DATA'
_DATA	ends
_TEXT	segment	byte public 'CODE'
;	?debug	L 7
_fun_char	proc	near
	push	si
;	?debug	L 9
	mov	si,offset DGROUP:s@
;	?debug	L 10
	mov	ax,si
	jmp	short @2
@2:
;	?debug	L 11
	pop	si
	ret	
_fun_char	endp
_TEXT	ends
_DATA	segment word public 'DATA'
_DATA	ends
_TEXT	segment	byte public 'CODE'
;	?debug	L 13
_main	proc	near
	push	bp
	mov	bp,sp
	push	si
	push	di
;	?debug	L 17
	call	near ptr _fun_num
	mov	si,ax
;	?debug	L 18
	call	near ptr _fun_char
	mov	di,ax
;	?debug	L 20
	push	word ptr [si]
	mov	ax,offset DGROUP:s@+4
	push	ax
	call	near ptr _printf
	pop	cx
	pop	cx
;	?debug	L 21
	call	near ptr _fun_num
	mov	bx,ax
	push	word ptr [bx]
	mov	ax,offset DGROUP:s@+13
	push	ax
	call	near ptr _printf
	pop	cx
	pop	cx
;	?debug	L 22
	mov	al,byte ptr [di]
	cbw	
	push	ax
	mov	ax,offset DGROUP:s@+27
	push	ax
	call	near ptr _printf
	pop	cx
	pop	cx
;	?debug	L 23
	call	near ptr _fun_char
	mov	bx,ax
	mov	al,byte ptr [bx]
	cbw	
	push	ax
	mov	ax,offset DGROUP:s@+37
	push	ax
	call	near ptr _printf
	pop	cx
	pop	cx
;	?debug	L 25
	xor	ax,ax
	jmp	short @3
@3:
;	?debug	L 26
	pop	di
	pop	si
	pop	bp
	ret	
_main	endp
_TEXT	ends
	?debug	C E9
_DATA	segment word public 'DATA'
s@	label	byte
	db	49
	db	50
	db	51
	db	0
	db	112
	db	102
	db	117
	db	110
	db	61
	db	37
	db	100
	db	10
	db	0
	db	102
	db	117
	db	110
	db	95
	db	110
	db	117
	db	109
	db	40
	db	41
	db	61
	db	37
	db	100
	db	10
	db	0
	db	112
	db	99
	db	104
	db	97
	db	114
	db	61
	db	37
	db	115
	db	10
	db	0
	db	102
	db	117
	db	110
	db	95
	db	99
	db	104
	db	97
	db	114
	db	40
	db	41
	db	61
	db	37
	db	115
	db	10
	db	0
_DATA	ends
_TEXT	segment	byte public 'CODE'
	extrn	_printf:near
_TEXT	ends
	public	_fun_char
	public	_fun_num
	public	_main
	end
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.