欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

c语言指针篇

程序员文章站 2022-09-09 15:09:52
不保证绝对正确,学习中所记录的一些笔记罢了,可能随着经历的增多,逐渐的完善, 不要完全相信我所记录的内容,可能因为编译协议版本的不同出现不同的结果。 也可能我写的根本就是错的,请相信自己动手得出来的结果。 寒暄的风 普通的指针 它的意思是一个指针变量p储存了变量a的内存地址。 *p的意思是指向了p本 ......

不保证绝对正确,学习中所记录的一些笔记罢了,可能随着经历的增多,逐渐的完善,

不要完全相信我所记录的内容,可能因为编译协议版本的不同出现不同的结果。

也可能我写的根本就是错的,请相信自己动手得出来的结果。------寒暄的风

普通的指针

1 #include<stdio.h>
2 int main()
3 {
4     int *p,a;
5     p=&a;
6 }

它的意思是一个指针变量p储存了变量a的内存地址。

*p的意思是指向了p本身所储存的内存地址。

普通指针和数组

#include<stdio.h>
int main()
{
    int a[10],*p;
    p=a;//这种情况总共有三种表示方法,*(p+0),p[i],*p
    /*当然如果我们不用指针也可以对数组进行这样的操作,*(a+0),*a,a[i]
  我们之所以敢用*运算符,那是因为数组的数组名就是第一个元素的内存地址
  为什么数组可以直接用指向运算符*进行加减运算呢,那是因为加的1就是数组的类型内存大小
  简单的来说就是数组的步长值就是其类型的单个大小,加1后刚好会跳入下一个内存区域。
  至于指针的问题,和上面类似,只不过指针的步长值根据的是指针的类型,指针和所指向的变量他们的类型都是一样的,为的就是确定
  指针加1后其步长值能跳入下一个内存区域。*/
}

如果指针的类型和所指向的变量类型不一样怎么办呢?

#include<stdio.h>
int main()
{
    int a[10]={1,2,3};//其他的值会被填充成0;
    char *p;
    p=a;
    printf("%d\n",p[1]);//不会显示正确的结构,因为步长值不对
    //int是4,char是1,p[4]才能访问到第二个内容。是*(p+4)的另一种表示方法。
}

两者类似,但是又有所不同。(根据多次的操作尝试,数组名可能是编译器内置的一个常量) 上面多种的指针和数组的表示方式,和下面的二位数组有着非常大的关系

二维数组------>一个指向指针的指针

普通的二维数组

1 #include<stdio.h>
2 int main()
3 {
4     int a[2][2]={1,2,3,4};
5     printf("%d--%d--%d--%d\n",*(a[0]+0),a[0][0],*(*(a+0)+0),(*(a+0))[0]);
6 }
7 
8 //因为指针本身也是一个变量,他自己也有在内存中的地址。

数组指针

数组指针int (*p)[3]; 他的意思是一个指向数组元素为3的指针变量。显示的写法同上面一样。

1 #include<stdio.h>
2 int main()
3 {
4     int a[2][2]={1,2,3,4};
5     int (*p)[2];
6     p=a;
7     printf("%d--%d--%d--%d\n",*(p[0]+0),p[0][0],*(*(p+0)+0),(*(p+0))[0]);
8 }

一维数组和二维数组,指针的区别

如果你建立了一个指针,想要像二维数组名那样的访问,这个指针必须是数组指针,其格式为int (*)p[2]

既然有数组指针和普通指针之分
那么数组指针和普通指针到底有甚么区别呢?
1.普通指针只能p[1]的形式来访问二维数组,假设a[2][2],这个数组有4个元素,那p[3],就代表了p访问这个数组的第4个元素。
2.数组指针,(*)p[2],假设a[2][2],哪我们就不能用普通指针的方式来访问这个二维数组。应该用*(p[0]+0),p[0][0],*(*(p+0)+0),(*(p+0))[0]
//为什么会造成这种差异呢?*(*p+3)访问到第4个元素
/*那是因为和数组指针方括号里面的值有关,例如如果是2的话,那就代表着他的类型大小*2,所以p+1,就是p+类型大小*2

 1 #include<stdio.h>
 2 int main()
 3 {
 4     int a[2][2]={1,2,3,4};
 5     int (*p)[2]=a;
 6     printf("%p-%p",p,*p);
 7     //经过测试,p的值和*p的值是一样的,都是二维数组a的首元素的内存地址,但是不同的是他们的步长值,p的步长值是类型大小*2,2即是他方括号里的数字。
 8     //*p的步长值就是他类型大小
 9     //*(*p+3)的结果是4,这就可以看出p和*p的步长值区别了
10 }

指针数组

指针数组 int *p[3]; 这个指针有三个元素,分别是p[0],p[1], p[2]。特性和普通的数组一样,数组名即首元素的内存地址。
指针数组操作字符串
char *p[3]={"hello","world","nihao"};
这是一个指针数组,可以解释为p[0]这个元素储存的值是h的内存地址。所以*p+0指向的h的内存地址。
如果要访问某行某列的值怎么访问呢?
*(*(p+1)+1)读取第2行第2个内容,等同于p[1][1],*(p[1]+1),(*(p+1))[1]

 1 *(*(p+1)+1)读取第2行第2个内容,等同于p[1][1],*(p[1]+1),(*(p+1))[1]
 2 #include<stdio.h>
 3 int main()
 4 {
 5     char *p[3]={"hello","woeld","nihao"};
 6     printf("%p\n",p);//是指针数组p第一个元素的内存地址
 7     printf("%p\n",(p+1));//是指针数组p第二个元素的内存地址
 8     printf("%p\n",p[0]);//是指针数组p第一个元素所储存的内存地址,也就是h的内存地址。
 9     printf("%p\n",*(p+0));//是指针数组p第一个元素所储存的内存地址,也就是h的内存地址。
10     printf("%c\n",*(p[0]));//p[0]原本储存的是h的内存地址,再一次指向后,会显示h
11     printf("%c\n",*(*(p+0)));//*(p+0)原本储存的是h的内存地址,再一次指向后,会显示h
12     printf("%c\n",*(p[0]+1));//p[0]原本是h的内存地址,加1后会跳到e的内存地址上,然后指向,会显示e
13     printf("%c\n",*(*(p+0)+1));//*(p+0)原本是h的内存地址,加1后会调到e的内存地址上,然后指向会显示e
14 }