Chinaunix首页 | 论坛 | 博客
  • 博客访问: 317902
  • 博文数量: 28
  • 博客积分: 2156
  • 博客等级: 大尉
  • 技术积分: 232
  • 用 户 组: 普通用户
  • 注册时间: 2009-12-02 15:31
文章分类

全部博文(28)

文章存档

2011年(7)

2010年(21)

分类: LINUX

2010-07-06 22:20:37

本文对指针进行了深入浅出的细致的讲解,非常适合初学者!



What Are Pointers?

Pointers are basically the same as any other variable. However, what is different about them is that instead of containing actual data, they contain a pointer to the memory location where information can be found. This is a very important concept. Many programs and ideas rely on pointers as the basis of their design, linked lists for example.



Getting Started

How do I define a pointer? Well, the same as any other variable, except you add an asterisk before its name. So, for example, the following code creates two pointers, both of which point to an integer:
int* pNumberOne;
int* pNumberTwo;
Notice the "p" prefix in front of the two variable names? This is a convention used to indicate that the variable is a pointer. Now, let's make these pointers actually point to something:
pNumberOne = &some_number;
pNumberTwo = &some_other_number;
The & (ampersand) sign should be read as "the address of" and causes the address in memory of a variable to be returned, instead of the variable itself. So, in this example, pNumberOne is set to equal the address of some_number, so pNumberOne now points to some_number.

Now if we want to refer to the address of some_number, we can use pNumberOne. If we want to refer to the value of some_number from pNumberOne, we would have to say *pNumberOne. The * dereferences the pointer and should be read as "the memory location pointed to by," unless in a declaration, as in the line int *pNumber.



What We've Learned So Far: An Example

Phew! That's a lot to take in. I'd recommend that if you don't understand any of those concepts, to give it another read through. Pointers are a complex subject and it can take a while to master them. Here is an example that demonstrates the ideas discussed above. It is written in C, without the C++ extensions.


#include <stdio.h>


void main()
{
    // declare the variables:


    int nNumber;
    int *pPointer;

    // now, give a value to them:


    nNumber = 15;
    pPointer = &nNumber;

    // print out the value of nNumber:


    printf("nNumber is equal to : %d\n", nNumber);

    // now, alter nNumber through pPointer:


    *pPointer = 25;

    // prove that nNumber has changed as a result of the above by


    // printing its value again:


    printf("nNumber is equal to : %d\n", nNumber);
}


Read through and compile the above code sample. Make sure you understand why it works. Then, when you are ready, read on!

注:

[root@xudonglee APUE]# vi test.c
[root@xudonglee APUE]# cc test.c
test.c: In function ‘main’:
test.c:5: 警告:‘main’ 的返回类型不是 ‘int’
[root@xudonglee APUE]# ./a.out
nNumber is equal to : 15
nNumber is equal to : 25




A Trap!


See if you can spot the fault in the program below:


#include <stdio.h>


int *pPointer;

void SomeFunction();
{
    int nNumber;
    nNumber = 25;

    // make pPointer point to nNumber:


    pPointer = &nNumber;
}

void main()
{
    SomeFunction(); // make pPointer point to something



    // why does this fail?


    printf("Value of *pPointer: %d\n", *pPointer);
}


This program firstly calls the SomeFunction function, which creates a variable called nNumber and then makes the pPointer point to it. Then, however, is where the problem is. When the function leaves, nNumber is deleted because it is a local variable. Local variables are always deleted when execution leaves the block they were defined in. This means that when SomeFunction returns to main(), the variable is deleted. So pPointer is pointing at where the variable used to be, which no longer belongs to this program. If you do not understand this, it may be wise to read back over on local and global variables, and on scope. This concept is also important.

So, how can the problem be solved? The answer is by using a technique known as dynamic allocation. Please be aware that this is different between C and C++. Since most developers are now using C++, this is the dialect that the code below is using.


Dynamic Allocation

Dynamic allocation is perhaps the key to pointers. It is used to allocate memory without having to define variables and then make pointers point to them. Although the concept may appear confusing, it is really simple. The following code demonstrates how to allocate memory for an integer:
int *pNumber;
pNumber = new int;
The first line declares the pointer, pNumber. The second line then allocates memory for an integer and then makes pNumber point to this new memory. Here is another example, this time using a double:

double *pDouble;
pDouble = new double;
The formula  is this the same every time, so you can't really fail with this bit. What is different about dynamic allocation, however,at the memory you allocate is not deleted when the function returns, or when execution leaves the current block. So, if we rewrite the above example using dynamic allocation, we can see that it works fine now:

#include <stdio.h>


int *pPointer;

void SomeFunction()
{
    // make pPointer point to a new integer


    pPointer = new int;
    *pPointer = 25;
}

void main()
{
    SomeFunction(); // make pPointer point to something


    printf("Value of *pPointer: %d\n", *pPointer);
}


Read through and compile the above code sample. Make sure you understand why it works. When SomeFunction is called, it allocates some memory and makes pPointer point to it. This time, when the function returns, the new memory is left intact(完整无缺的; 未经触动的; 未受损伤的), so pPointer still points to something useful. That's it for dynamic allocation! Make sure you understand this, and then read on to learn about the fly in the ointment(1. 软膏, 油膏2. 扫兴的人;煞风景的事物3. 药膏), and why there is still a serious error in the code above.

注:

[root@xudonglee APUE]# g++ test.c
test.c:14: 错误:‘::main’ 必须返回 ‘int’
[root@xudonglee APUE]# vi test.c  //将main函数的返回类型改为int
[root@xudonglee APUE]# g++ test.c
[root@xudonglee APUE]# ./a.out
Value of *pPointer: 25




Memory Comes, Memory Goes


There's always a complication and this one could become quite serious, although it's very easy to remedy(改正;纠正;改进). The problem is that although the memory that you allocate using dynamic allocation is conveniently left intact, it actually never gets deleted automatically. That is, the memory will stay allocated until you tell the computer that you've finished with it. The upshot of this is that if you don't tell the computer that you've finished with the memory, it will be wasting space that other applications or other parts of your application could be using. This eventually will lead to a system crash through all the memory being used up, so it's pretty important. Freeing the memory when you've finished with it is very simple:
delete pPointer;
That's all there is to it. You have to be careful, however, that you pass a valid pointer, i.e. that is a pointer that actually points to some memory you've allocated and not just any old rubbish. Trying to delete memory that's already been freed is dangerous and can lead to your program crashing. So here is the example again, updated this time so it doesn't waste any memory:

#include <stdio.h>


int *pPointer;

void SomeFunction()
{
// make pPointer point to a new integer


    pPointer = new int;
    *pPointer = 25;
}

void main()
{
    SomeFunction(); // make pPointer point to something


    printf("Value of *pPointer: %d\n", *pPointer);

    delete pPointer;
}


One line difference is all it took, but this line is essential. If you don't delete the memory, you get what is known as a "memory leak," where memory is gradually leaking away and can't be reused unless the application is closed.




阅读(1580) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~