C语言的指针

 

1.     指针

指针包括两个方面的内容:

  • 指针指向的对象,即指针变量的值,也就是数据对象存放的地址
  • 指针的类型,指针的类型决定了该怎么去解释其指向的对象区域,同一片内存区域,按照不同的解释,其意义是完全不同

指针本身也是一个对象,也占据内存空间。

 

这是 The C Programming Language 里面的示意图,c is a char and p is a pointer that points to it.

分清楚指针与指针指向的对象意义重大。

有几个常见的错误。

 

错误1.没有为指针指向的对象分配内存

  1. char *str;
  2. gets(str); // 错误,没有为str分配内存, str指向垃圾数据

当定义一个指针变量char *str时,只是在栈上分配了str的空间,指针的值则是未定义的,也就是了垃圾。

下面的才是正确的:

  1.     char *str;
  2.     str = (char*)malloc(100);// 申请一片内存区,让str指向这片区域
  3.     gets(str); // ok

事实上,上面的代码再作一个内存申请是否成功的检测:If( str != NULL ) 就更好了。

 

错误2. 野指针问题

指针使用完毕后,一般会free 释放其指向的内存区域,但释放完毕以后,此时指针的值是存在的,只不过是垃圾值。用 if( p != NULL ) 会返回真。

比较好的习惯是,free掉以后显式设置 p = NULL

 

错误3.同一片内存区域 多次释放

这类错误一般隐藏的比较深。尤其在C++里,呵。

比如

  1.     char *p1 =  (char*)malloc(100);
  2.     char *p2 = p1; // 两个指针指向同一片内存区域
  3.     free(p1);     
  4.     free(p2);     // 错误!前一个语句已经释放内存;
  5.     // 晕死,用MinGW测试这段代码居然没问题,靠

 

C++的指针比 C 语言的指针要复杂许多,因为有许多内存的自动申请与释放,还有继承关系,交叉在一起,头疼。

 

指针相加毫无意义,相减表示两个指针中间的元素个数。

 

指针占用空间:地址总线32位时,指针占四个字节。Int* p1;Char* p2;Char (*p3)[10];

Sizeof P1,p2,p3的大小会是一样的。但是其指向的对象迥异

 

 

2.    指针与数组

     

       数组与指针是不同的。数组名对应着(不是指向)一块内存,其地址与容量在生命期内保持不变,只有数组的内容可以改变。数组名是常量,因而不能修改。比如int m[10], m++是一个编译错误。定义一个指针n指向m第一个元素,int *n = m, 此时n++合法,表达式执行完毕后n指向数组第2个元素。另外,用sizeof(m) sizeof(n) 会是完全不同的结果。sizeof(m)返回的是整个数组的长度,sizeof(n)则是指针的长度。

 

表达式a[i]会自动被转换成*(a+i)参与运算,因此使用指针形式并不会比数组形式更有效率。另外,&a[i]a+i也是等价的。下标总是和指针的偏移量相同

   

将数组作为参数传到函数中时,数组形式与指针形式等价。数组名被编译器当作指向该数组第一个元素的指针。

Fun ( int *arr ){···}

fun ( int arr [] ){···}

fun ( int arr[10] ){···}//这里实参是多大的数组都可以

 

  字符串常量初始化指针与数组(The C Programming Language P104)

There is an important difference between these definitions:

   char amessage[] = "now is the time"; /* an array */

   char *pmessage = "now is the time"; /* a pointer *

 

   amessage is an array, just big enough to hold the sequence of characters and '/0' that initializes it. Individual characters within the array may be changed but amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.

 

 

3.    数组指针与指针数组

数组指针:指向数组的指针

指针数组:指针构成的数组

 

char a[100];        
char (*p)[100] = &a;

// 这里b就是一个数组指针,它指向整个数组,数组包含100char

 

int matrix[3][10];
    
    
int (*mm)[10] = matrix;
    
    
// 这也是一个数组指针,指向matrix的第一行, 这个数组包含10个整形元素
     
     

  
  
   
    
  
  典型的指针数组定义如下:
   
   
char *a[10]; // 数组,包含10个元素,每个元素都是指向char的指针
     
     
比如:
     
     
char *name[] = { "Illegal month", "Jan", "Feb", "Mar" };
    
    

 

(The C Programming Language P112)

The parentheses are necessary since brackets [] have higher precedence than *. Without parentheses, the declaration  int *daytab[13] is an array of 13 pointers to integers.

 

4.     指针数组与二维数组(The C Programming Language P114)

char *name[] = { "Illegal month", "Jan", "Feb", "Mar" };

    
    
     
     
    
    

char aname[][15] = { "Illegal month", "Jan", "Feb", "Mar" };

    
     

5.    函数指针

int *p1();
int (*p2)();
p1是一个函数,它返回一个指向int* 型数据的指针。
p2是一个函数指针,它指向一个参数为空的函数,这个函数返回一个整数数据

 

(The C Programming Language P120)

int (*comp)(void *, void *)

which says that comp is a pointer to a function that has two void * arguments and returns an int.

The use of comp in the line

   if ((*comp)(v[i], v[left]) < 0)

is consistent with the declaration: comp is a pointer to a function, *comp is the function, and

   (*comp)(v[i], v[left])

is the call to it. The parentheses are needed so the components are correctly associated; without them,

   int *comp(void *, void *)    /* WRONG */

says that comp is a function returning a pointer to an int, which is very different.

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值