指针

    技术2025-11-20  51

    1,问题的引入     int a;     a = 100;//把数值100存放到变量a对应的存储单元中去     b = a;//把a的数值存放到变量b对应的存储单元中去     ==> 在C语言中,任何一个变量名,都有两层含义     (1)代表该变量的存储单元,左值 lvalue     (2)代表该变量的值        右值 rvalue          而且,我们对变量的访问有两种情况     (1)写操作,把一个值写入变量对应的存储单元中     (2)读操作,读出变量对应存储单元中存放的值          我们知道系统已经把变量名与变量的地址相关联,系统实质上通过地址     来访问变量对应的存储空间。那么是不是我们也可以直接通过地址来访问     变量呢?     ==> 指针      2,指针的概念     地址:系统把内存以一个字节为单位划分成许多份进行编号,这个编号就是内存单元的地址。          在C语言中,指针的概念与地址差不多,你可以指针就是有类型的地址。     一个变量的首地址,称为该变量的"指针"。它标志着该变量的内容从哪里开始。      3,指针变量     ★指针变量也是一个变量,它是用来保存一个对象的地址的。          指针变量的定义:         类型  *指针变量名;         "类型":指针变量指向的类型         "指向":如果我保存了你的地址,那么就说我指向你。              eg:  int *p;          int a;          p = &a;          p是一个指针变量名,它指向的类型是int          p的类型是: int*               注意:在32位的处理器里,地址都是32位的,即指针变量分配的空间都是4个字节。         所以把指针变量的类型强制转化为其它指针类型也不会失真。         因此 void* 也叫通用指针。             ★指针变量的类型只决定指针变量的变化(与整形加减)与实际地址变化间的倍率     eg:   int a;           char b;           int *p1=&a;           char *p2=&b;           printf("%p\n",p1);//%p是打印地址的格式控制符           printf("%p\n",++p1);           printf("%p\n",p2);           printf("%p\n",++p2);          4,如何获取地址     (1)通过取地址符  &         &对象名: 表示取该对象的地址         对象: 变量,数组元素。。。     (2)有些对象的名字本身就表示地址         如:数组名,函数名....     注:这两种方式获取到的地址都有类型的。      5,如何访问指针指向的空间。  *(指向运算符)     *(地址) <==> 地址对应的那个变量     即*(地址) 可作左值也可作右值,还可以取地址。      *(&a) <==> a;      *& 可直接约掉     注意: 与定义时的*区分      6,数组与指针     数组元素与普通变量,也有自己的地址。     并且数组元素间地址是连续的。(数组名为首元素的地址,是个常量)     eg:         int a[10];         int *p;         p = &a[0];

            那么把100赋值给a[0],有几种方法:             a[0] = 100;             *p = 100;             *a = 100;//数组名为首元素的地址,是个常量             p[0] = 100;                      那么 *(a+1) ==> a[1]         ★得到公式           *(p+i) <=> p[i],when i>=0            7,字符串与指针     在C语言中,并没有内置字符串的类型,C语言的字符串是通过char*指针     来实现的。     char *str = "ABCDEF";     str:保存字符串的首地址,即'A'的地址     str+1:指向字符'B'的地址     *(str+1) = '2';//error(段错误),因为这里没有定义字符数组,没有分配空间                    //常量保存在rodata段内,不能被改变     eg:                        char *str1 = "ABCDEF";//字符串保存在rodata段内         char str2[]= "ABCDEF";//字符串保存在数组里                  *(str1+1) = '2';//error(段错误),指向的是只读空间,不能进行写操作         *(str2+1) = '2';//right,指向的是数组空间,可以进行写操作         str1++;//right,str1是指针变量,其值可以改变         str2++;//error(段错误),str2是数组名,其值不能改变          注意: (1)NULL在C语言中表示不指向任何空间,若指向了NULL并进行了读或写操作,             就会出现段错误,NULL的值是0           (2)出现段错误的两种情况              a.指向了NULL,并进行了读或写操作              b.对只读空间进行了写操作               8,二维数组与指针     int a[3][4];     二维数组a可以看成元素为int[4]的一维数组。     所以,*(a+i)<=>a[i]指向的是该一维数组的第i个元素,该元素为int[4]类型,     因此,这里需要再指向一下才能指向二维数组的元素。     即*((*(a+i))+j) <=> a[i][j],这时元素的类型为int型。          表达式(i>=0,j>=0)          类型                                 含义                                      值     a+i                           int[4]*/int[3][4]   指向第i行的首地址/整个二维数组             &a[i]                      做指针运算/sizeof(a),typeof(a)     *(a+i)+j<=>a[i]+j           int*/int[4]     第i行第j列的元素的地址/i行的一维数组    &a[i][j]                     做指针运算/sizeof(a[i]),typeof(a[i])         *(*(a+i)+j)<=>a[i][j]           int                          第i行第j列的元素                          a[i][j]

    9,数组指针与指针数组      int a[10];     如果我们需要定义一个指针变量p,来保存a的地址,该如何定义?     typeof(a) *p;     => int[10] *p;     => int(*p)[10];     p就是一个指针变量,指向一个数组(int[10]),那么我们把p叫做数组指针。     因为*的结合性较低,所以这里要把*p括起来,表示定义的是指针变量。          int *p[10];     这里的p是一个数组,里面有10个元素,每个元素都是int*类型,     那么我们把p叫做指针数组。     eg:         int(*p1)[10];         int *p2[10];         printf("%d %d\n",sizeof(p1),sizeof(p2));     ★二维数组名的类型就是数组指针      10,main的参数     在unix/liunx下面,main函数的原型,应该是如下的     int main(int argc,char *argv[])     {          }     在操作系统调用你的可执行程序时(调用你的main函数),允许带参数,     只不过参数都是字符串类型(char *)     argc:argument count,表示允许你的程序时,参数的个数(程序名是第一个参数)     argv:argument vector 参数字符串指针的数组     eg:  ./sum   1   2          命令的本质就是程序,只不过它存放在命令搜索路径里

    11,二级指针与多级指针     其实main函数原型也可写为如下模式     int main(int argc,char **argv)     {}          可见指针数组就是二级指针,二级指针就是能指向两次的指针。     一般有以下两种理解方式     (1)指针变量的地址         eg:   int a;               int *p = &a;               int **p2 = &p;             printf("%d %d %d\n",a,*p,**p2);     (2)指针数组         如果一个数组的元素是指针,则该数组名就是二级指针         同理,如果一个数组的元素是二级指针,则该数组名就是三级指针         ...         eg:               int a=1,b=2,c=3;             int *p[3]={&a,&b,&c};             *(p+1)  ==>   p[1]  ==> &b             **(p+1) ==> b                      在C语言中,char *可以表示字符串,其实指针也可以表示一个已定义好的数组。         它们区别是:字符串有终止符'\0'来确定长度,而数组必须要我们自己给定长度。                  int array_max(int *a,int n)         {                      }          12,函数指针     函数指针变量就是用来保存函数地址的变量          函数指针变量的定义格式:         指向的函数返回值类型 (*函数指针变量名)(指向的函数形参列表)              通过函数指针调用指向的函数:         (*函数指针名)(实参列表);         或         (函数指针名)(实参列表);

        ☆函数指针数组         void (*a[3])(int,int);//定义了一个函数指针数组a,该数组有3个元素,每个元素都是                               //函数指针类型,指向的函数返回类型是void,参数类型是int,int。                                13,指针作为函数参数     由于形参不能改变实参,被调函数想传数据给主调函数一般用return返回。     除此之外还有两种方法     (1)访问全局变量     (2)带指针作为函数参数      14,动态内存分配(malloc.c)

    Processed: 0.018, SQL: 9