CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
不看会后悔的Windows XP之经验谈 简单快捷DIY实用家庭影院
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  C/C++ >  新手乐园

指针,C的灵魂!

楼主prgmBaggio(only C)2005-07-01 19:21:36 在 C/C++ / 新手乐园 提问

第一章。指针的概念  
   
  指针是一个特殊的变量,它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型,指针所指向的类型,指针的值或者叫指针所指向的内存区,还有指针本身所占据的内存区。让我们分别说明。    
   
  先声明几个指针放着做例子:    
   
  例一:    
   
  (1)int   *ptr;    
   
  (2)char   *ptr;    
   
  (3)int   **ptr;    
   
  (4)int   (*ptr)[3];    
   
  (5)int   *(*ptr)[4];    
   
  如果看不懂后几个例子的话,请参阅我前段时间贴出的文章<<如何理解c和c    
   
  ++的复杂类型声明>>。    
   
     
   
  1。   指针的类型。    
   
  从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的类型:    
   
  (1)int   *ptr;   //指针的类型是int   *    
   
  (2)char   *ptr;   //指针的类型是char   *    
   
  (3)int   **ptr;   //指针的类型是   int   **    
   
  (4)int   (*ptr)[3];   //指针的类型是   int(*)[3]    
   
  (5)int   *(*ptr)[4];   //指针的类型是   int   *(*)[4]    
   
  怎么样?找出指针的类型的方法是不是很简单?    
   
     
   
  2。指针所指向的类型。    
   
  当你通过指针来访问指针所指向的内存区时,指针所指向的类型决定了编译器将把那片内存区里的内容当做什么来看待。  
   
  从语法上看,你只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉,剩下的就是指针所指向的类型。例如:    
   
  (1)int   *ptr;   //指针所指向的类型是int    
   
  (2)char   *ptr;   //指针所指向的的类型是char    
   
  (3)int   **ptr;   //指针所指向的的类型是   int   *    
   
  (4)int   (*ptr)[3];   //指针所指向的的类型是   int()[3]    
   
  (5)int   *(*ptr)[4];   //指针所指向的的类型是   int   *()[4]    
   
  在指针的算术运算中,指针所指向的类型有很大的作用。    
   
  指针的类型(即指针本身的类型)和指针所指向的类型是两个概念。当你对C越来越熟悉时,你会发现,把与指针搅和在一起的“类型”这个概念分成“指针的类型”和“指针所指向的类型”两个概念,是精通指针的关键点之一。我看了不少书,发现有些写得差的书中,就把指针的这两个概念搅在一起了,所以看起书来前后矛盾,越看越糊涂。  
   
  3。   指针的值,或者叫指针所指向的内存区或地址。    
   
  指针的值是指针本身存储的数值,这个值将被编译器当作一个地址,而不是一个一般的数值。在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。    
   
  指针所指向的内存区就是从指针的值所代表的那个内存地址开始,长度为sizeof(指针所指向的类型)的一片内存区。以后,我们说一个指针的值是XX,就相当于说该指针指向了以XX为首地址的一片内存区域;我们说一个指针指向了某块内存区域,就相当于说该指针的值是这块内存区域的首地址。    
   
  指针所指向的内存区和指针所指向的类型是两个完全不同的概念。在例一中,指针所指向的类型已经有了,但由于指针还未初始化,所以它所指向的内存区是不存在的,或者说是无意义的。    
   
  以后,每遇到一个指针,都应该问问:这个指针的类型是什么?指针指向的类型是什么?该指针指向了哪里?    
   
  4。   指针本身所占据的内存区。    
   
  指针本身占了多大的内存?你只要用函数sizeof(指针的类型)测一下就知道了。在32位平台里,指针本身占据了4个字节的长度。  
   
  指针本身占据的内存这个概念在判断一个指针表达式是否是左值时很有用。      
   
  第二章。指针的算术运算  
   
     
   
  指针可以加上或减去一个整数。指针的这种运算的意义和通常的数值的加减运算的意义是不一样的。例如:    
   
  例二:    
   
  1。   char   a[20];    
   
  2。   int   *ptr=a;    
   
  ...    
   
  ...    
   
  3。   ptr++;    
   
  在上例中,指针ptr的类型是int*,它指向的类型是int,它被初始化为指向整形变量a。接下来的第3句中,指针ptr被加了1,编译器是这样处理的:它把指针ptr的值加上了sizeof(int),在32位程序中,是被加上了4。由于地址是用字节做单位的,故ptr所指向的地址由原来的变量a的地址向高地址方向增加了4个字节。  
   
  由于char类型的长度是一个字节,所以,原来ptr是指向数组a的第0号单元开始的四个字节,此时指向了数组a中从第4号单元开始的四个字节。  
   
  我们可以用一个指针和一个循环来遍历一个数组,看例子:    
   
  例三:    
   
  int   array[20];    
   
  int   *ptr=array;    
   
  ...    
   
  //此处略去为整型数组赋值的代码。    
   
  ...    
   
  for(i=0;i<20;i++)    
   
  {    
   
  (*ptr)++;    
   
  ptr++;    
   
  }    
   
  这个例子将整型数组中各个单元的值加1。由于每次循环都将指针ptr加1,所以每次循环都能访问数组的下一个单元。再看例子:    
   
  例四:    
   
  1。   char   a[20];    
   
  2。   int   *ptr=a;    
   
  ...    
   
  ...    
   
  3。   ptr+=5;    
   
  在这个例子中,ptr被加上了5,编译器是这样处理的:将指针ptr的值加上5乘sizeof(int),在32位程序中就是加上了5乘4=20。由于地址的单位是字节,故现在的ptr所指向的地址比起加5后的ptr所指向的地址来说,向高地址方向移动了20个字节。在这个例子中,没加5前的ptr指向数组a的第0号单元开始的四个字节,加5后,ptr已经指向了数组a的合法范围之外了。虽然这种情况在应用上会出问题,但在语法上却是可以的。这也体现出了指针的灵活性。    
   
  如果上例中,ptr是被减去5,那么处理过程大同小异,只不过ptr的值是被减去5乘sizeof(int),新的ptr指向的地址将比原来的ptr所指向的地址向低地址方向移动了20个字节。    
   
  总结一下,一个指针ptrold加上一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值增加了n乘sizeof(ptrold所指向的类型)个字节。就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向高地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。一个指针ptrold减去一个整数n后,结果是一个新的指针ptrnew,ptrnew的类型和ptrold的类型相同,ptrnew所指向的类型和ptrold所指向的类型也相同。ptrnew的值将比ptrold的值减少了n乘sizeof(ptrold所指向的类型)个字节,就是说,ptrnew所指向的内存区将比ptrold所指向的内存区向低地址方向移动了n乘sizeof(ptrold所指向的类型)个字节。 问题点数:0、回复次数:91Top

1 楼prgmBaggio(only C)回复于 2005-07-01 19:21:52 得分 0

第三章。运算符&和*  
   
     
   
  这里&是取地址运算符,*是...书上叫做“间接运算符”。&a的运算结果是一个指针,指针的类型是a的类型加个*,指针所指向的类型是a的类型,指针所指向的地址嘛,那就是a的地址。*p的运算结果就五花八门了。总之*p的结果是p所指向的东西,这个东西有这些特点:它的类型是p指向的类型,它所占用的地址是p所指向的地址。  
   
  例五:    
   
  int   a=12;    
   
  int   b;    
   
  int   *p;    
   
  int   **ptr;    
   
  p=&a;//&a的结果是一个指针,类型是int*,指向的类型是int,指向的地址是a的地址。    
   
  *p=24;//*p的结果,在这里它的类型是int,它所占用的地址是p所指向的地址,显然,*p就是变量a。  
   
  ptr=&p;//&p的结果是个指针,该指针的类型是p的类型加个*,在这里是int**。该指针所指向的类型是p的类型,这里是int*。该指针所指向的地址就是指针p自己的地址。    
   
  *ptr=&b;//*ptr是个指针,&b的结果也是个指针,且这两个指针的类型和所指向的类型是一样的,所以?amp;b来给*ptr赋值就是毫无问题的了。  
   
  **ptr=34;//*ptr的结果是ptr所指向的东西,在这里是一个指针,对这个指针再做一次*运算,结果就是一个int类型的变量。  
   
     
   
  第四章。指针表达式。  
   
     
   
  一个表达式的最后结果如果是一个指针,那么这个表达式就叫指针表达式。下面是一些指针表达式的例子:    
   
  例六:    
   
  int   a,b;    
   
  int   array[10];    
   
  int   *pa;    
   
  pa=&a;//&a是一个指针表达式。    
   
  int   **ptr=&pa;//&pa也是一个指针表达式。    
   
  *ptr=&b;//*ptr和&b都是指针表达式。    
   
  pa=array;    
   
  pa++;//这也是指针表达式。    
   
  例七:    
   
  char   *arr[20];    
   
  char   **parr=arr;//如果把arr看作指针的话,arr也是指针表达式    
   
  char   *str;    
   
  str=*parr;//*parr是指针表达式    
   
  str=*(parr+1);//*(parr+1)是指针表达式    
   
  str=*(parr+2);//*(parr+2)是指针表达式    
   
  由于指针表达式的结果是一个指针,所以指针表达式也具有指针所具有的四个要素:指针的类型,指针所指向的类型,指针指向的内存区,指针自身占据的内存。  
   
  好了,当一个指针表达式的结果指针已经明确地具有了指针自身占据的内存的话,这个指针表达式就是一个左值,否则就不是一个左值。   在例七中,&a不是一个左值,因为它还没有占据明确的内存。*ptr是一个左值,因为*ptr这个指针已经占据了内存,其实*ptr就是指针pa,既然pa已经在内存中有了自己的位置,那么*ptr当然也有了自己的位置。  
   
     
   
  第五章。数组和指针的关系  
   
     
   
  如果对声明数组的语句不太明白的话,请参阅我前段时间贴出的文章<<如何理解c和c++的复杂类型声明>>。   数组的数组名其实可以看作一个指针。看下例:    
   
  例八:    
   
  int   array[10]={0,1,2,3,4,5,6,7,8,9},value;    
   
  ...    
   
  ...    
   
  value=array[0];//也可写成:value=*array;    
   
  value=array[3];//也可写成:value=*(array+3);    
   
  value=array[4];//也可写成:value=*(array+4);    
   
  上例中,一般而言数组名array代表数组本身,类型是int   [10],但如果把array看做指针的话,它指向数组的第0个单元,类型是int   *,所指向的类型是数组单元的类型即int。因此*array等于0就一点也不奇怪了。同理,array+3是一个指向数组第3个单元的指针,所以*(array+3)等于3。其它依此类推。    
   
  例九:    
   
  char   *str[3]={    
   
  "Hello,this   is   a   sample!",    
   
  "Hi,good   morning.",    
   
  "Hello   world"    
   
  };    
   
  char   s[80];    
   
  strcpy(s,str[0]);//也可写成strcpy(s,*str);    
   
  strcpy(s,str[1]);//也可写成strcpy(s,*(str+1));    
   
  strcpy(s,str[2]);//也可写成strcpy(s,*(str+2));    
   
  上例中,str是一个三单元的数组,该数组的每个单元都是一个指针,这些指针各指向一个字符串。把指针数组名str当作一个指针的话,它指向数组的第0号单元,它的类型是char**,它指向的类型是char   *。  
   
  *str也是一个指针,它的类型是char*,它所指向的类型是char,它指向的地址是字符串"Hello,this   is   a   sample!"的第一个字符的地址,即'H'的地址。   str+1也是一个指针,它指向数组的第1号单元,它的类型是char**,它指向的类型是char   *。    
   
  *(str+1)也是一个指针,它的类型是char*,它所指向的类型是char,它指向"Hi,good   morning."的第一个字符'H',等等。    
   
  下面总结一下数组的数组名的问题。声明了一个数组TYPE   array[n],则数组名称array就有了两重含义:第一,它代表整个数组,它的类型是TYPE   [n];第二,它是一个指针,该指针的类型是TYPE*,该指针指向的类型是TYPE,也就是数组单元的类型,该指针指向的内存区就是数组第0号单元,该指针自己占有单独的内存区,注意它和数组第0号单元占据的内存区是不同的。该指针的值是不能修改的,即类似array++的表达式是错误的。    
   
  在不同的表达式中数组名array可以扮演不同的角色。    
   
  在表达式sizeof(array)中,数组名array代表数组本身,故这时sizeof函数测出的是整个数组的大小。    
   
  在表达式*array中,array扮演的是指针,因此这个表达式的结果就是数组第0号单元的值。sizeof(*array)测出的是数组单元的大小。    
   
  表达式array+n(其中n=0,1,2,....。)中,array扮演的是指针,故array+n的结果是一个指针,它的类型是TYPE*,它指向的类型是TYPE,它指向数组第n号单元。故sizeof(array+n)测出的是指针类型的大小。    
   
  例十:    
   
  int   array[10];    
   
  int   (*ptr)[10];    
   
  ptr=&array;    
   
  上例中ptr是一个指针,它的类型是int   (*)[10],他指向的类型是int   [10],我们用整个数组的首地址来初始化它。在语句ptr=&array中,array代表数组本身。    
   
  本节中提到了函数sizeof(),那么我来问一问,sizeof(指针名称)测出的究竟是指针自身类型的大小呢还是指针所指向的类型的大小?答案是前者。例如:  
   
  int   (*ptr)[10];    
   
  则在32位程序中,有:    
   
  sizeof(int(*)[10])==4    
   
  sizeof(int   [10])==40    
   
  sizeof(ptr)==4    
   
  实际上,sizeof(对象)测出的都是对象自身的类型的大小,而不是别的什么类型的大小。      
   
  Top

2 楼prgmBaggio(only C)回复于 2005-07-01 19:21:57 得分 0

第六章。指针和结构类型的关系  
   
     
   
  可以声明一个指向结构类型对象的指针。    
   
  例十一:    
   
  struct   MyStruct    
   
  {    
   
  int   a;    
   
  int   b;    
   
  int   c;    
   
  }    
   
  MyStruct   ss={20,30,40};//声明了结构对象ss,并把ss的三个成员初始化为20,30和40。  
   
  MyStruct   *ptr=&ss;//声明了一个指向结构对象ss的指针。它的类型是  
   
  MyStruct*,它指向的类型是MyStruct。  
   
  int   *pstr=(int*)&ss;//声明了一个指向结构对象ss的指针。但是它的类型和它指向的类型和ptr是不同的。  
   
  请问怎样通过指针ptr来访问ss的三个成员变量?    
   
  答案:    
   
  ptr->a;    
   
  ptr->b;    
   
  ptr->c;    
   
  又请问怎样通过指针pstr来访问ss的三个成员变量?    
   
  答案:    
   
  *pstr;//访问了ss的成员a。    
   
  *(pstr+1);//访问了ss的成员b。    
   
  *(pstr+2)//访问了ss的成员c。    
   
  呵呵,虽然我在我的MSVC++6.0上调式过上述代码,但是要知道,这样使用pstr来访问结构成员是不正规的,为了说明为什么不正规,让我们看看怎样通过指针来访问数组的各个单元:    
   
  例十二:    
   
  int   array[3]={35,56,37};    
   
  int   *pa=array;    
   
  通过指针pa访问数组array的三个单元的方法是:    
   
  *pa;//访问了第0号单元    
   
  *(pa+1);//访问了第1号单元    
   
  *(pa+2);//访问了第2号单元    
   
  从格式上看倒是与通过指针访问结构成员的不正规方法的格式一样。  
   
  所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,单元和单元之间没有空隙。但在存放结构对象的各个成员时,在某种编译环境下,可能会需要字对齐或双字对齐或者是别的什么对齐,需要在相邻两个成员之间加若干个“填充字节”,这就导致各个成员之间可能会有若干个字节的空隙。  
   
  所以,在例十二中,即使*pstr访问到了结构对象ss的第一个成员变量a,也不能保证*(pstr+1)就一定能访问到结构成员b。因为成员a和成员b之间可能会有若干填充字节,说不定*(pstr+1)就正好访问到了这些填充字节呢。这也证明了指针的灵活性。要是你的目的就是想看看各个结构成员之间到底有没有填充字节,嘿,这倒是个不错的方法。    
   
  通过指针访问结构成员的正确方法应该是象例十二中使用指针ptr的方法。  
   
     
   
  第七章。指针和函数的关系  
   
     
   
     
   
  可以把一个指针声明成为一个指向函数的指针。    
   
  int   fun1(char*,int);    
   
  int   (*pfun1)(char*,int);    
   
  pfun1=fun1;    
   
  ....    
   
  ....    
   
  int   a=(*pfun1)("abcdefg",7);//通过函数指针调用函数。    
   
  可以把指针作为函数的形参。在函数调用语句中,可以用指针表达式来作为实参。    
   
  例十三:    
   
  int   fun(char*);    
   
  int   a;    
   
  char   str[]="abcdefghijklmn";    
   
  a=fun(str);    
   
  ...    
   
  ...    
   
  int   fun(char*s)    
   
  {    
   
  int   num=0;    
   
  for(int   i=0;i<strlen(s);i++)    
   
  {    
   
  num+=*s;s++;    
   
  }    
   
  return   num;    
   
  }    
   
  这个例子中的函数fun统计一个字符串中各个字符的ASCII码值之和。前面说了,数组的名字也是一个指针。在函数调用中,当把str作为实参传递给形参s后,实际是把str的值传递给了s,s所指向的地址就和str所指向的地址一致,但是str和s各自占用各自的存储空间。在函数体内对s进行自加1运算,并不意味着同时对str进行了自加1运算。    
   
     
   
  第八章。指针类型转换  
   
     
   
  当我们初始化一个指针或给一个指针赋值时,赋值号的左边是一个指针,赋值号的右边是一个指针表达式。在我们前面所举的例子中,绝大多数情况下,指针的类型和指针表达式的类型是一样的,指针所指向的类型和指针表达式所指向的类型是一样的。    
   
  例十四:    
   
  1。   float   f=12.3;    
   
  2。   float   *fptr=&f;    
   
  3。   int   *p;    
   
  在上面的例子中,假如我们想让指针p指向实数f,应该怎么搞?是用下面的语句吗?    
   
  p=&f;    
   
  不对。因为指针p的类型是int*,它指向的类型是int。表达式&f的结果是一个指针,指针的类型是float*,它指向的类型是float。两者不一致,直接赋值的方法是不行的。至少在我的MSVC++6.0上,对指针的赋值语句要求赋值号两边的类型一致,所指向的类型也一致,其它的编译器上我没试过,大家可以试试。为了实现我们的目的,需要进行“强制类型转换”:    
   
  p=(int*)&f;    
   
  如果有一个指针p,我们需要把它的类型和所指向的类型改为TYEP*和TYPE,那么语法格式是:    
   
  (TYPE*)p;    
   
  这样强制类型转换的结果是一个新指针,该新指针的类型是TYPE*,它指向的类型是TYPE,它指向的地址就是原指针指向的地址。而原来的指针p的一切属性都没有被修改。    
   
  一个函数如果使用了指针作为形参,那么在函数调用语句的实参和形参的结合过程中,也会发生指针类型的转换。  
   
  例十五:    
   
  void   fun(char*);    
   
  int   a=125,b;    
   
  fun((char*)&a);    
   
  ...    
   
  ...    
   
  void   fun(char*s)    
   
  {    
   
  char   c;    
   
  c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;    
   
  c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;    
   
  }    
   
  注意这是一个32位程序,故int类型占了四个字节,char类型占一个字节。函数fun的作用是把一个整数的四个字节的顺序来个颠倒。注意到了吗?在函数调用语句中,实?amp;a的结果是一个指针,它的类型是int   *,它指向的类型是int。形参这个指针的类型是char*,它指向的类型是char。这样,在实参和形参的结合过程中,我们必须进行一次从int*类型到char*类型的转换。结合这个例子,我们可以这样来想象编译器进行转换的过程:编译器先构造一个临时指针   char*temp,然后执行temp=(char*)&a,最后再把temp的值传递给s。所以最后的结果是:s的类型是char*,它指向的类型是char,它指向的地址就是a的首地址。    
   
  我们已经知道,指针的值就是指针指向的地址,在32位程序中,指针的值其实是一个32位整数。那可不可以把一个整数当作指针的值直接赋给指针呢?就象下面的语句:    
   
  unsigned   int   a;    
   
  TYPE   *ptr;//TYPE是int,char或结构类型等等类型。    
   
  ...    
   
  ...    
   
  a=20345686;    
   
  ptr=20345686;//我们的目的是要使指针ptr指向地址20345686(十进制)    
   
  ptr=a;//我们的目的是要使指针ptr指向地址20345686(十进制)    
   
  编译一下吧。结果发现后面两条语句全是错的。那么我们的目的就不能达到了吗?不,还有办法:    
   
  unsigned   int   a;    
   
  TYPE   *ptr;//TYPE是int,char或结构类型等等类型。    
   
  ...    
   
  ...    
   
  a=某个数,这个数必须代表一个合法的地址;    
   
  ptr=(TYPE*)a;//呵呵,这就可以了。    
   
  严格说来这里的(TYPE*)和指针类型转换中的(TYPE*)还不一样。这里的(TYPE*)的意思是把无符号整数a的值当作一个地址来看待。    
   
  上面强调了a的值必须代表一个合法的地址,否则的话,在你使用ptr的时候,就会出现非法操作错误。    
   
  想想能不能反过来,把指针指向的地址即指针的值当作一个整数取出来。完全可以。下面的例子演示了把一个指针的值当作一个整数取出来,然后再把这个整数当作一个地址赋给一个指针:    
   
  例十六:    
   
  int   a=123,b;    
   
  int   *ptr=&a;    
   
  char   *str;    
   
  b=(int)ptr;//把指针ptr的值当作一个整数取出来。    
   
  str=(char*)b;//把这个整数的值当作一个地址赋给指针str。    
   
  好了,现在我们已经知道了,可以把指针的值当作一个整数取出来,也可以把一个整数值当作地址赋给一个指针。    
   
     
   
  第九章。指针的安全问题  
   
  看下面的例子:    
   
  例十七:    
   
  char   s='a';    
   
  int   *ptr;    
   
  ptr=(int*)&s;    
   
  *ptr=1298;    
   
  指针ptr是一个int*类型的指针,它指向的类型是int。它指向的地址就是s的首地址。在32位程序中,s占一个字节,int类型占四个字节。最后一条语句不但改变了s所占的一个字节,还把和s相临的高地址方向的三个字节也改变了。这三个字节是干什么的?只有编译程序知道,而写程序的人是不太可能知道的。也许这三个字节里存储了非常重要的数据,也许这三个字节里正好是程序的一条代码,而由于你对指针的马虎应用,这三个字节的值被改变了!这会造成崩溃性的错误。让我们再来看一例:    
   
  例十八:    
   
  1。   char   a;    
   
  2。   int   *ptr=&a;    
   
  ...    
   
  ...    
   
  3。   ptr++;    
   
  4。   *ptr=115;    
   
  该例子完全可以通过编译,并能执行。但是看到没有?第3句对指针ptr进行自加1运算后,ptr指向了和整形变量a相邻的高地址方向的一块存储区。这块存储区里是什么?我们不知道。有可能它是一个非常重要的数据,甚至可能是一条代码。而第4句竟然往这片存储区里写入一个数据!这是严重的错误。所以在使用指针时,程序员心里必须非常清楚:我的指针究竟指向了哪里。    
   
  在用指针访问数组的时候,也要注意不要超出数组的低端和高端界限,否则也会造成类似的错误。    
   
  在指针的强制类型转换:ptr1=(TYPE*)ptr2中,如果sizeof(ptr2的类型)大于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是安全的。如果sizeof(ptr2的类型)小于sizeof(ptr1的类型),那么在使用指针ptr1来访问ptr2所指向的存储区时是不安全的。至于为什么,读者结合例十七来想一想,应该会明白的。  
   
   
  请写出以下程序的运行结果:  
   
  #include<stdio.h>  
  int   *p;  
  pp(int   a,int   *b);  
  main()  
  {  
  int   a=1,b=2,c=3;  
  p=&b;  
  pp(a+c,&b);  
  printf("(1)%d%d%dn",a,b,*p);  
  }  
  pp(int   a,int   *b)  
  {int   c=4;  
  *p=*b+c;  
  a=*p-c;  
  printf("(2)%d%d%dn",a,*b,*p);  
  }  
  Top

3 楼FBIq(aiby)回复于 2005-07-01 19:43:47 得分 0

mkTop

4 楼microchu()回复于 2005-07-01 21:30:36 得分 0

markTop

5 楼bingbox_1984(苦丁茶)(我只喜欢CC)回复于 2005-07-01 21:42:22 得分 0

朝九晚五何时了?!房子汽车何时有?!  
  经典!!!!!继续奋斗吧!!!Top

6 楼liyuan02(梨园)回复于 2005-07-01 22:42:28 得分 0

好好好好好好!!!!!!!Top

7 楼tfq(大梦谁先觉)回复于 2005-07-01 23:12:12 得分 0

支持Top

8 楼foochow(无聊,灌水......)回复于 2005-07-01 23:30:58 得分 0

dingTop

9 楼jsldhy(我爱典典)回复于 2005-07-02 08:22:49 得分 0

我先帮你顶!Top

10 楼Willpro(WillPro)回复于 2005-07-02 11:30:47 得分 0

22222222Top

11 楼jixingzhong(瞌睡虫·星辰)回复于 2005-07-02 16:48:57 得分 0

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!Top

12 楼xiaoluoli(C/C++思考)回复于 2005-07-02 19:21:21 得分 0

看到指针的影响力了  
   
  是男人的就应该用好指针,大家同意吗Top

13 楼OnlySong()回复于 2005-07-02 19:46:30 得分 0

哈哈顶!!!  
  楼主辛苦了Top

14 楼riking511()回复于 2005-07-02 19:58:44 得分 0

多谢楼主了Top

15 楼changhongqiang(一叶孤舟)回复于 2005-07-02 20:10:26 得分 0

经典~!支持楼主~!Top

16 楼windercc()回复于 2005-07-02 20:44:00 得分 0

谁说的是简单的话,很有可能是你根本就没有认真的学习。  
  而我相信即使是SUPER高手也是相当注意这些的。  
  大道至简!!!Top

17 楼LordSimon(lordsimon@x.cn)回复于 2005-07-02 22:02:31 得分 0

学好汇编会对指针有更深一层的认识Top

18 楼ghking(菜鸟*king)回复于 2005-07-03 00:22:42 得分 0

果然是强人,顶一个Top

19 楼sonyfan(门外汉)回复于 2005-07-03 14:01:11 得分 0

学习中  
  Top

20 楼homtipo()回复于 2005-07-03 15:13:22 得分 0

呵呵,   不错。   不错Top

21 楼hackingtruth(尘封)回复于 2005-07-04 18:02:10 得分 0

下班了,   明天再看Top

22 楼sankt(宠辱不惊,看庭前花开花落;去留无意,望天空云卷云舒.)回复于 2005-07-04 23:16:31 得分 0

不错  
  Top

23 楼iverson76()回复于 2005-07-05 01:21:19 得分 0

楼主好人啊,继续努力,我们需要像楼主这样的人Top

24 楼zzdd621(windy)回复于 2005-07-05 11:33:25 得分 0

谢谢楼主!   这么有热心帮助人。Top

25 楼AthlonxpX86(一坨屎)回复于 2005-07-05 11:56:20 得分 0

markTop

26 楼xiaoxiaohe()回复于 2005-07-05 17:48:04 得分 0

绝对好贴!Top

27 楼DeathRocK(小飞)回复于 2005-07-05 19:11:06 得分 0

看的晚了些.  
  不过还是的感谢楼主....Top

28 楼tygfr(Try to do!)回复于 2005-07-05 19:23:00 得分 0

mkTop

29 楼prgmBaggio(only C)回复于 2005-07-05 19:37:33 得分 0

呵呵,偷偷地告诉大家:“这个是转贴”Top

30 楼jp1981113(傲笑剑客)回复于 2005-07-05 20:09:42 得分 0

楼主刚开始学C。  
   
  完毕!Top

31 楼ACCPGB(漠男)回复于 2005-07-05 21:39:30 得分 0

如获至宝呀!     我是个新人,楼主发如此好教材真是让我感激不尽呀!     多谢了!     我一定会能力的!Top

32 楼bbdog(贝贝狗)回复于 2005-07-05 22:30:06 得分 0

今天没有时间看了,做个标记先,明天抽空看看。Top

33 楼jsd850926(紫冰)回复于 2005-07-05 22:32:30 得分 0

同楼上一样   呵呵Top

34 楼GeminiXXXCC(吕布)回复于 2005-07-05 23:23:32 得分 0

1。   指针的类型。    
   
  从语法的角度看,你只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。这是指针本身所具有的类型。让我们看看例一中各个指针的类型:    
   
  (1)int   *ptr;   //指针的类型是int   *    
   
  (2)char   *ptr;   //指针的类型是char   *    
   
  (3)int   **ptr;   //指针的类型是   int   **    
   
  (4)int   (*ptr)[3];   //指针的类型是   int(*)[3]    
   
  (5)int   *(*ptr)[4];   //指针的类型是   int   *(*)[4]    
   
  怎么样?找出指针的类型的方法是不是很简单?    
   
  还是不明白int   (*)[3]是什么指针?int   *(*)[4]呢?int   *[3]呢?Top

35 楼carsonhealy(雪峰影)回复于 2005-07-05 23:33:59 得分 0

先顶一下再说!Top

36 楼prgmBaggio(only C)回复于 2005-07-06 23:13:59 得分 0

呵呵,我才工作1年,不过C的经验也不少哦Top

37 楼liuyiwu()回复于 2005-07-06 23:26:22 得分 0

楼主能否解释一下二维数组名到底是什么?我一直搞不懂,好象也更指针有关吧。谢谢了Top

38 楼cyblueboy83(爱情白痴—电脑迷)回复于 2005-07-06 23:39:32 得分 0

呵呵,写得很好,收藏  
  Top

39 楼xjp6688(大平/要做必须最好)回复于 2005-07-08 10:42:53 得分 0

很不错!Top

40 楼treesting(叶底蝉)回复于 2005-07-08 13:33:12 得分 0

早就看了!!写的很不错的Top

41 楼oyang2004()回复于 2005-07-08 14:58:39 得分 0

不错!!Top

42 楼hackingtruth(尘封)回复于 2005-07-08 15:57:25 得分 0

upTop

43 楼guogangj(无名小卒)回复于 2005-07-08 16:03:47 得分 0

严重同意Top

44 楼popcom(生活在别处)回复于 2005-07-11 15:05:24 得分 0

好Top

45 楼meiqi_fu(美琪)回复于 2005-07-11 15:36:41 得分 0

还是不明白int   (*)[3]是什么指针?int   *(*)[4]呢?int   *[3]呢?  
   
  int   (*)[3]:指向数组的指针;  
  int   *(*)[4]:指向一个指针数组的指针;  
  int   *[3]:一个指针数组,该数组含有三个指针。Top

46 楼wosirius(神经第六)回复于 2005-07-11 17:08:45 得分 0

mmTop

47 楼whatsouta(某疯子)回复于 2005-07-11 17:30:17 得分 0

鼎Top

48 楼prewind(prewind)回复于 2005-07-13 11:10:56 得分 0

markTop

49 楼hslinux(幻世龙)回复于 2005-07-15 12:50:57 得分 0

朝五晚九何时了?!房子汽车何时有?!  
  经典!!!!!继续奋斗吧!!!  
   
  ^_^  
  朝九晚六基本是都是这样规定的吧~~~~~~~~~~~但是,,,实际都是差不多:朝九晚九Top

50 楼Gzqun(格子裙)回复于 2005-07-15 13:29:33 得分 0

没什么多说的....  
   
  一句话:我是男人..Top

51 楼wIND_Du(wIND_Du)回复于 2005-07-15 16:41:42 得分 0

留名纪念Top

52 楼iforem(在咖啡香中醒来)回复于 2005-07-15 16:53:30 得分 0

mark  
   
  谢谢楼主Top

53 楼prgmBaggio(only C)回复于 2005-07-15 19:24:15 得分 0

^_^  
  朝九晚六基本是都是这样规定的吧~~~~~~~~~~~但是,,,实际都是差不多:朝九晚九  
  ================================================================================  
  呵呵,我还算幸运,没有加班Top

54 楼wjn007013(死者代言人)回复于 2005-07-19 18:32:49 得分 0

有点明白了!谢谢这位师兄!!Top

55 楼httpftp(我不是坏小孩儿)回复于 2005-07-21 13:46:01 得分 0

mark一下,慢慢研习Top

56 楼prgmBaggio(only C)回复于 2005-07-25 19:09:46 得分 0

11Top

57 楼xufangrui(岁月如歌)回复于 2005-07-25 20:00:26 得分 0

好晕呀!!!!  
  指针的东西太多了!Top

58 楼godanpimm(无忌哥哥)回复于 2005-07-26 10:30:25 得分 0

值得研究Top

59 楼dacat1983()回复于 2005-07-26 11:21:02 得分 0

好贴Top

60 楼rick29(rick.z)回复于 2005-07-26 12:10:31 得分 0

MARK.Top

61 楼Bible_Chou(日子在发霉)回复于 2005-07-26 12:33:39 得分 0

受益。Top

62 楼lnabc(浅浅)回复于 2005-07-26 20:19:18 得分 0

感谢楼主  
   
  收藏此贴Top

63 楼needchange(don't waste time)回复于 2005-07-27 10:38:23 得分 0

我有些不苟同上面的某些观点。  
  指针的类型指的应该是指针所指向变量的类型,指针是一个地址,永远是unsigned   long   int类型的,如2000,2004等。  
  我觉的上文所说的“指针所指向的类型”,即我所说的“指针的类型”。  
  指针是这样的:指针的值是一个地址,通过这个地址找到这个地址中的值。举个例子:int   i=20;  
  int   *p=&i;如果i的地址是2000,则p=2000,*p=20.  
  Top

64 楼lxk_cool()回复于 2005-07-27 16:22:40 得分 0

MARK   ,学习中Top

65 楼FlyingEagle_seu(飞鹰)回复于 2005-07-27 22:45:09 得分 0

好贴!好贴!收藏Top

66 楼qinyuanfeng(沁园枫)回复于 2005-07-28 11:43:48 得分 0

指针是C的重要概念,灵魂是算法……Top

67 楼michelle_vickie(行者)回复于 2005-07-28 12:35:18 得分 0

经典之贴,收藏:)Top

68 楼guycs(年轻人)回复于 2005-07-28 15:58:03 得分 0

支持Top

69 楼prgmBaggio(only C)回复于 2005-07-28 22:06:32 得分 0

我喜欢研究算法,谁有迷宫的算法??Top

70 楼wyd124(鱼日)回复于 2005-07-28 22:46:04 得分 0

markTop

71 楼alex460()回复于 2005-07-28 23:17:24 得分 0

收藏Top

72 楼myhouwei(myhouwei)回复于 2005-07-29 00:34:00 得分 0

收下Top

73 楼dounier()回复于 2005-07-29 03:02:06 得分 0

meiqi_fu(美琪)   (   )   信誉:100     2005-7-11   15:36:42     得分:   0      
     
     
         
  还是不明白int   (*)[3]是什么指针?int   *(*)[4]呢?int   *[3]呢?  
   
  int   (*)[3]:指向数组的指针;  
  int   *(*)[4]:指向一个指针数组的指针;  
  int   *[3]:一个指针数组,该数组含有三个指针。  
   
       
     
  请问int   *   [3]   和int   (*)[3]有什么区别?  
  我的理解和这个好象不太一样......Top

74 楼sc_arhat(睡梦罗汉 )回复于 2005-07-29 13:56:20 得分 0

先收下Top

75 楼prgmBaggio(only C)回复于 2005-07-29 18:41:30 得分 0

请问int   *   [3]   和int   (*)[3]有什么区别?  
  我的理解和这个好象不太一样......  
   
  ==========================================  
  int   *[3]:一个指针数组,该数组含有三个指针。  
  int   (*)[3]:指向数组的指针;  
   
  这里说的没错啊?你的理解是?Top

76 楼prgmBaggio(only C)回复于 2005-08-05 19:00:15 得分 0

!!Top

77 楼aiguozhou(想起)回复于 2005-08-05 19:08:40 得分 0

潜力题,写的不错。UP  
  学习Top

78 楼JeffDing(小高)回复于 2005-08-06 22:18:54 得分 0

顶~~~~指针我最糊涂啦~~~~Top

79 楼Lxyer(L_xiao)回复于 2005-08-06 22:44:07 得分 0

如果指针就算灵魂,那个学个机儿,  
  不要从字面上,把指针看得这么难嘛,  
  汇编也就是几个地址,跳去跳,  
  把指针都说成这样了.Top

80 楼king_(我选择我喜欢)回复于 2005-08-06 22:50:25 得分 0

谢谢啊,果然是强人,顶一个Top

81 楼boyplayee()回复于 2005-08-06 23:07:55 得分 0

MARKTop

82 楼zenny_chen(ACE Intercessor)回复于 2005-08-06 23:15:10 得分 0

不要再转载了啦!看了太多次了。  
   
  再说指针哪有那么多东西好讲!  
   
  在汇编语言中“指针”是最常用的。  
   
  Top

83 楼prgmBaggio(only C)回复于 2005-08-06 23:23:12 得分 0

大家看完后可以去看看这个:  
  http://community.csdn.net/Expert/topic/4177/4177340.xml?temp=.5304071Top

84 楼ding8125(丁丁)回复于 2005-08-10 09:50:56 得分 0

-_-奋斗Top

85 楼xiangyuen(成绩是汗)回复于 2005-08-10 10:14:07 得分 0

学习Top

86 楼ArcCreator(-=ROBOTECH=-)回复于 2005-08-10 13:37:15 得分 0

markTop

87 楼prgmBaggio(only C)回复于 2005-08-12 17:27:12 得分 0

8.14Top

88 楼hongfeng21(鸿锋)回复于 2005-08-12 18:55:01 得分 0

mark  
  Top

89 楼bobobie(波波)回复于 2005-08-21 20:42:02 得分 0

先顶再看Top

90 楼woaixiong(我爱熊)回复于 2005-09-30 17:44:08 得分 0

thanksTop

91 楼dsm933(白雪映苍月)回复于 2005-10-18 09:24:19 得分 0

又一颗新星Top

相关问题

  • 掌握 C++ 指针?
  • C++指针问题
  • C++指针问题
  • Turbo c 内存 巨指针
  • 关于C++的指针。
  • C指针的难题???
  • c++的指针问题?
  • C#中的指针问题!
  • c指针的问题!
  • C++ 函数指针问题?

关键词

  • 指针
  • 内存
  • 函数
  • 结构
  • 编译器
  • 语句
  • 数组
  • 指向
  • 类型
  • 单元

得分解答快速导航

  • 帖主:prgmBaggio

相关链接

  • C/C++ Blog
  • C/C++类图书
  • C/C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo