上海龙凤419

C说话

C说话中的指针解读

时辰:2024-11-01 08:48:58 C说话 我要投稿
  • 相干保举

C说话中的指针解读

指针无疑是一个难点。可是,我感觉指针也是C说话出格首要的一个特征。也许,你在除C和C++之外的编程说话中,很少看到指针。而C++中,也多用援用,而非指针。指针,作为一种高效的工具,堪称是一把双刃剑——用得好,能够大大进步法式效力,但用的不好,便是良多bug的滋长地。下面是指针相干的常识,接待浏览。

  这也许也是人们对指针批驳不一的缘由吧。就我小我而言,我还是很喜好这个特征,由于我须要常常和硬件和一些底层的软件打交道。这个时辰,指针便表现出它怪异的魅力。指针的常识良多,有一本典范的书叫《C和指针》,若是有乐趣能够读一读。这里,我首要总结一些若何去解读指针(说真话这个工具实在是很轻易让人猜疑)的体例,一方面给自身做查问用,别的一方面,但愿能够给别人一些赞助。

  一,根基观点

  对于指针的根基观点,我就不具体先容了,由于有很多书都先容的很具体。这里我只先容一局部。指针指向一个地点,而指针自身在大大都体系上都是一个无标记整数(在32bit机上是4byte,在64bit机上是8byte)。下面用一个例子来申明其机制:

  在下面的例子中,先界说了一个指针p,它的范例是int,也便是说它只能指向一个int型的变量,而不能指向其余范例的变量。最初咱们将a变量的地点赋给p。在这个进程中,触及到两个内存块,一个是寄存指针p的内存(用&p可获得内存地点),一个是寄存a的值的内存块(用&a能够获得内存地点)。而第一个内存存的p的值颠末赋值语句后也便是&a的值了。别的一个注重点是, *(星号)和变量范例和变量名之间能够有肆意个空格,也能够不。比方下面三种体例都是一样的:

  int a = 10;

  int *p; //申明一个指针,但未初始化,此时为野指针

  p = &a; //将a变量的地点赋给指针p

  在下面的例子中,先界说了一个指针p,它的范例是int,也便是说它只能指向一个int型的变量,而不能指向其余范例的变量。最初咱们将a变量的地点赋给p。在这个进程中,触及到两个内存块,一个是寄存指针p的内存(用&p可获得内存地点),一个是寄存a的值的内存块(用&a能够获得内存地点)。而第一个内存存的p的值颠末赋值语句后也便是&a的值了。别的一个注重点是, *(星号)和变量范例和变量名之间能够有肆意个空格,也能够不。比方下面三种体例都是一样的:

  int* a;

  int * a;

  int *a;

  解读体例:

  起首从标示符起头浏览,而后往右读,每碰到圆括号的右半边就调转浏览标的目的。反复这个进程直到全部申明剖析终了。须要注重的是,已读过的局部在后续作为一个全体来看。

  看下面一个例子:

  int *a[3];

  //起首a右侧是[],申明a是一个具备3个元素的数组

  //右侧读完,则读左侧。a左侧是int*,申明a的元素是int范例的指针

  int (*a)[3]

  //起首,a右侧是圆括号的`右半边,转向,左侧是一个*,申明a是一个指针

  //碰到括号,再转向,是一个[],申明a是一个指向3个元素的数组的指针

  //左侧是int,申明元素范例是int

  //以是,a是一个指向具备3个整型元素的数组的指针

  int (*func)(int p);

  //不异的体例,func起首是一个指针

  //而后右侧是一个括号,申明(func)是个函数,而func是指向这个函数的指针

  //这个函数具备int范例的参数,前往值范例为int

  int (*func[3])(int p);

  //同理,func起首是一个具备3个元素的数组

  //其次,func左侧是一个*,申明func数组的元素是指针。要注重润色的是func[3],而不是func。由于已读过的局部在前面都作为一个全体来看待

  //跳出第一个圆括号,右侧又是一个圆括号,申明func数组的元素是函数范例的指针。这个函数具备int范例的参数和int型前往值

  二,数组首地点a,&a,&a[0]

  注:a,&a,&a[0]的寄义固然差别,可是他们三个的值是相称的!

  以int a[3]为例申明:

  a作为右值时,代表数组首元素的首地点,而非数组地点。 也便是a[0]的地点。int i = (a+1),这里a是右值,以是代表首元素的首地点,a+1代表下一个元素的首地点,即&a[1]。

  a是全部数组的名字。以是sizeof(a)的值为sizeof(int) * 3 = 40,代表全部数组的巨细。

  &a即为取a的首地点,也即全部数组的首地点。以是sizeof(&a) = 4。 int p = (int)(&a+1)中的&a+1代表下一个数组的首地点,明显是越界的。

  &a[0]代表首元素的首地点。 以是sizeof(&a[0]) = 4。

  &a[3],很明显数组越界了,但它的sizeof是几多呢? 也是4,由于关头字sizeof求值是在编译的时辰,固然并不存在a[3]这个元素,可是这里并不真正拜候a[3],而是按照数组元素范例来肯定其值的。以是sizeof(a[3])不会犯错。

  a[-1]代表甚么意义?起首要大白下标的情势被编译器剖析成指针的情势,即a[1]被剖析成(a+1)。那末,a[-1]被剖析成*(a-1)。

  对于数组首元素的首地点和数组的首地点的区分:实在,数组首元素的首地点和数组首地点的值是不异的,即&a[0]和a(和&a)是相称的,可是而这寄义不一样。首元素的首地点加1后,是第二个元素的首地点(之以是一向说首地点,是由于有的范例存储时会占多个地点),但数组的首地点加1后是“下一个数组的地点”,这里的下一个数组只是为了申明加1时加了全部数组的`巨细,而不是一个元素的巨细。

  有一点比拟轻易混合:a固然代表全部数组,但(a+1)却代表下一个元素的首地点,即和(&a[0]+1)一样,下一个数组的情势为:(&a+1)。 下面以一个法式来申明:

  #include

  int main()

  {

  int a[3] = {1, 2, 3};

  printf("%ld ",sizeof(long unsigned int));

  printf("*(a+1)=%d ",*(a+1));

  printf("sizeof(a)=%ld ", sizeof(a));

  printf("sizeof(&a[3])=%ld ", sizeof(&a[3]));

  printf("a[-1]=%d *(a-1)=%d ",a[-1],*(a-1));

  printf("a=%p &a=%p &a[0]=%p ",a, &a,&a[0]);

  printf("a=%p (a+1)=%p (&a+1)=%p ",a,(a+1),(&a+1));

  return 0;

  }

  输入成果:

  8

  *(a+1)=2

  sizeof(a)=12

  sizeof(&a[3])=8

  a[-1]=0 *(a-1)=0

  a=0x7fffcb4cb980 &a=0x7fffcb4cb980 &a[0]=0x7fffcb4cb980

  a=0x7fffcb4cb980 (a+1)=0x7fffcb4cb984 (&a+1)=0x7fffcb4cb98c

  申明(下面的行数只计较main函数内有代码的行):

  法式第1行界说了一个具备3个元素的整型数组。

  第2行打印了long型的巨细。由于我是64bit的,以是一个long是8byte。

  第3行打印了*(a+1)的值,成果和a[1]的值相称。申明a固然代表全部数组,但作为右值时,简直代表首元素的首地点。

  第4行输入值为12,是全部数组的巨细。

  第5行打印了一个出界元素的巨细,不报错,考证了下面第5条。

  第6行打印了a[-1]和*(a-1),输入值相称。考证了下面第6条。

  第7行打印了a和&a[0],值相称。申明数组的首地点和首元素的首地点是相称的。

  第8行打印了a,(a+1),(&a+1),由成果就能够看出首元素的首地点加1是加了一个数组元素的巨细,而数组首地点加1是加了一个数组的巨细。

  三,指针数组和数组指针

  指针数组: 起首它是一个数组,数组的元素是指针,同样成为“存储指针的'数组”。

  数组指针: 起首它是一个指针,它指向一个数组,也能够懂得为“数组的指针”。 也能够操纵前面的“解读体例”去阐发。

  四,函数指针和指针函数

  函数指针: 指向函数的指针变量。

  指针函数: 带指针的函数,也便是前往指针的函数。

  char * fun(char* a, char* b) //界说为指针函数

  {

  ...

  ...

  }

  int main()

  {

  char* (*p)(char* p1, char* p2); //界说函数指针

  p = &fun; //把函数地点赋给它

  //p = fun; //如许写也行

  (*p)("aa", "bb"); //利用函数指针

  return 0;

  }

  四,指针常量和常量指针

  const char* p1; //常量指针,指向常量的指针

  char const* p2; //同上

  char* const p3; //指针常量,指针是常量

  怎样记?

  能够先把范例名去掉,而后看const离谁近,就润色谁。

  也能够const在*左侧的为常量指针,const在*右侧的'为指针常量。

  五、万x钥匙

  实在,对于“指针数组与数组指针、函数指针与指针函数、指针常量与常量指针”的判定,有一个全能x匙。那便是按照咱们壮大的.中文语法:前边是润色词,后边才是主语。比方“指针数组”,前面的指针只是润色词,前面的数组才是主语,以是它是一个数组。

  六,野指针

  野指针指不肯定指向的指针。形成野指针的环境有:

  1. 指针变量建立但不初始化。

  2. 指针p被free或以后,不置为NULL。


【 C说话中的指针解读】相干文章:

C说话中的指针是甚么08-08

C说话中指针的观点03-16

C说话中野指针的深切剖析08-06

C说话中指针与数组的区分10-09

C说话中的指针和内存泄露08-07

c说话中指针的利用体例10-12

C说话中指针变量作为函数参数详解07-01

C说话中各类范例的指针的观点总结11-24

C说话指针的观点08-20

C说话指针函数和函数指针详解09-29