C/C++入门基础----指针(1)

    指针其实就是一个变量, 和其他类型的变量一样。在32位计算机上, 指针占用四字节的变量。指针与其他变量的不同就在于它的值是一个内存地址,指向内存的另外一个地方, 指针能够直接访问内存和操作底层的数据,可以通过指针直接动态分配与释放内存

#include <stdio.h>

int main(void)
{
int i = 1;
int *p = &i;       //指针p指向了i的地址
*p += 1;          //*p将i的什增1
printf("i = %d\n", i);
return 0;
}

//下面是用typedef定义一个新结构最常用的定义形式,演示了指针的基本使用方式。

/*在声明指针的时候,最好将其初始化为NULL, 否则指针将随机指向某个区域,访问没有初始化的指针,会因为指针未定义而为程序带来预想不到的结果;指针释放后, 也应该将指针指向NULL, 以防止野指针。因为指针所指向的内存虽然释放了,但是指针依然指向某一内存区域。

   指针的运算最容易出错。指针支持加减运算。 下面代码中ptmp += 1 运算结束之后, 指针指向的区域不是向前移动了一个字节, 而是向前移动了 sizeof(node)个字节, 也就是说“1” 代表了指针指向的数据结构(node)大小个字节。如果要让指针向前移动一个字节,那么需要先对指针进行类型转换:(char*)ptmp+1。

也就是说, 对于指针p, 指针的加法运算 p = p + n中, p向前移动的位置不是 n 个字节, 而是

n * (sizeof(*p) 个字节,指针的减法运算与此类似。

*/

typedef struct_node
{
int value;
struct_node * next;
}node, *link;

node * pnode = NULL; //声明变量都应该初始化,尤其是指针
pnode = (node *)malloc(sizeof(node)); //内存分配
//务必检测内存分配失败情况, 程序健壮性的考查
//不加这样的判断,如果分配失败,会造成程序访问NULL指针崩溃
if(pnode == NULL)
{
//出错处理,返回资源不足错误信息
}
memset(pnode, 0, sizeof(node)); //新分配的内存应该初始化, 否则内存中含有无用的垃圾信息
pnode->value = 100;
printf("pnode->value = %d\n", pnode->value);
node* ptmp = pnode;
ptmp += 1; //指针支持加减操作,但须格外小心
free(pnode); //使用完内存后, 务必释放,否则会泄漏,一般采取谁分配谁释放原则
pnode = NULL; //释放内存后,需要将指针置NULL, 防止野指针

1、下面总结些指针变量的各种声明形式:主要要明白[],*和()运算符的优先级:()>[]>*, 比如 int * a[10],由于[]的优先级别高于*,所以该表达示首先是一个数组。那么它是什么数组呢?由 int *确定它是个指针数组。又比如 int(*a)[], 由于()高于[], 所以它是一个指针。那么它是什么指针呢?由[]确定它是个数组指针,即指向数组的指针。

1) int *a[10];      //指针数组;

2) int (*a)[10];   //数组指针;

3) int (*a)(int);   //函数指针;

4) int (*a[10])(int);    //函数指针数组。注意用*与[]的优先级来判断这组定义的区别;

5) int *a, **a;     //指针和指向指针的指针;

6) char str[];       //字符串数组;

7) char *str, **str; //字符指针和指向字符串的指针;

2、用sizeof()计算指针长度:主要要明白指针长度(在32位系统中)为4,字符串数组的长度必须包含字符串的结束标志符'\0',数组的长度为元素个数乘以单个元素大小。

  char *p1 = "Hello World!";  //p1为字符串指针,所以sizeof(p1) = 4;

  char p2[] = "Hello World!"; //p2为字符数组并初始化为"Hello, world"。由于字符串的存储特点,总是以'\0'作为结束标志,因此上面的字符串等价于下面的数组:char p2[] = {'H','e', 'l', 'l','o',',', ','w','o','r','l','d','\0'};必须包含字符串的结束标志符'\0',所以sizeof(p2) = 13。

  char p3[] = {'H','e', 'l', 'l','o','W','o','r','l','d'}; //p3为字符数组,并由12个字符初始化,所以sizeof(p3) = 12。

注意:strlen(p)计算的是字符串中有郊的字符数(不含'\0')。所以 strlen(p)的值为12。

如下面字符串拷贝:strlen(str)+1这个要是没有加1来存储字符串结束'\0',则strcpy(strbak,str)将报错。

char * str = "Hello, how are you!";

char * strbak = (char*)malloc(strlen(str)+1);

if(NULL == strbak)

{

    //内存分配失败,返回错误

}

strcpy(strbak,str);

有关sizeof用法及总结如下:

(1)参数可以为数据类型或者为一般变量。

       如sizeof(int), sizeof(double)等,这种情况要注意的是,不同系统或者不同编译器得到的结果可能是不同的。例如int类型在16位系统中占2个字节,在32位系统中占4个字节。

(2)参数可以为数组或指针。

        int a[50];//sizeof(a) = 4*50 = 200; 数组所占的空间大小为200字节。

        注意数组作函数参数时,在函数体内计算该数组参数等同于计算指针的长度

        int *a = new int[50]; //sizeof(a) = 4; a 为一个指针,sizeof(a)是求指针的大小,在32位系统中,当然是占4 个字节。

(3)参数可以为结构或类。

        sizeof应用在类和结构中的处理情况是相同的。有两点需要注意,第一,结构或者类中的静态成员不对结构或者类的大小产生影响,因为静态变量的存储位置与结构或者类的实例地址无关。第二,没有成员变量的结构或类的大小为1,因为必须保证结构或类的每一个实例在内存中都有唯一的地址。

3,常用指针含义:

    1) const int *a; //指针常量,指针指向的变量不参改变值

    2) int const * a; //指针常量,与const int *a等价

    3) int * const a; //常量指针,指针本身不能改变值

4,计算数组的长度:        

     在计算数组长度的时候,需要注意数组作为函数的参数,将退化为指针,所以, 其长度为指针的长度。

     int a[10];        //sizeof(a) = 10 * sizeof(int) = 40;

 

     int a[10]; 

     void func(int a[], int n)

    {

         print("%d", sizeof(a));        //此时数组退化为指针,所以sizeof(a) = 4;

    }

    需要指出的是,数组也是指针,但它是常量指针,即 int a[10]中的 a 可以看作是 int * const a。所以一但声明,a不能再被改变。

 

posted @ 2016-12-27 23:57  cindy_zl  阅读(208)  评论(0编辑  收藏  举报