指针

概览

指针是C语言的精华部分,通过利用指针,我们能很好地利用内存资源,使其发挥最大的 效率。有了指针技术,我们可以描述复杂的数据结构,对字符串的处理可以更灵活,对数组 的处理更方便,使程序的书写简洁,高效,清爽。

1.指针与指针变量

2.数组与指针

3.函数指针

指针与指针变量

指针:访问变量,首先应找到其在内存的地址,或者说,一个地址唯一指向一个内存变量,称这个地址为变量的指针;

指针变量:存放指针的变量就是指针变量。

指针变量的引用:指针变量是对变量一种间接访问形式。对指针变量的引用形式为:*指针变量,其含义是指针变量所指向的值。

字符串与指针

#include <stdio.h>

int main(int argc, const char * argv[]) {
    char a[]="abc";
    printf("%x,%s
",a,a);//结果:5fbff820,abc,同一个变量a是输出字符串还是输出地址,根据格式参数而定
    printf(a); //结果:abc
    printf("
");
    
    char b[]="abc";
    char *p=b;
    printf("b=%s,p=%s
",b,p);//结果:b= abc,p= abc
    
    //指针存储的是地址,而数组名存储的也是地址,既然字符数组可以表示字符串,那么指向字符的指针同样也可以,如下方式可以更简单的定义一个字符串
    char *c="abc"; //等价于char c[]="abc";
    printf("c=%s
",c); //结果:c= abc
    
    return 0;
}

这里需要指出是为什么printf(a)能够直接输出字符串呢?

我们看一下printf()的定义:int     printf(const char * __restrict, ...) __printflike(1, 2);其实printf的参数要求是指向字符类型的指针,而结合上面的例子和我们之前说的,如果函数形参是指针类型那么可以传入函数名,因此也就能正确输出字符串的内容了

数组与指针

对数组来说,数组名就是数组在内存中首地址,即指针;

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

  int *p = a 或 int *p = &a[0];

指针与一维数组

假设我们定义一个一维数组,该数组在内存会有系统分配的一个存储空间,其数组的名 字就是数组在内存的首地址。若再定义一个指针变量,并将数组的首址传给指针变量,则该 指针就指向了这个一维数组。我们说数组名是数组的首地址,也就是数组的指针。而定义的 指针变量就是指向该数组的指针变量。对一维数组的引用,既可以用传统的数组元素的下标 法,也可使用指针的表示方法。

int a[10] , * ptr ; / * 定义数组与指针变量 * /

做赋值操作: ptr = a ; 或 ptr = &a[0] ;
则 ptr 就得到了数组的首址。其中, a 是数组的首地址, &a[0] 是数组元素 a [0] 的地址,由于

a [0] 的地址就是数组的首地址,所以,两条赋值操作效果完全相同。指针变量 p t r 就是指向数 组a的指针变量。

若 ptr 指向了一维数组,现在看一下 C 规定指针对数组的表示方法:

1 ) ptr + n 与 a + n 表 示 数 组 元 素 a [n] 的 地 址 , 即 &a[n] 。对整个 a 数 组 来 说 , 共有 10个元素, n的 取 值 为 0 ~ 9 , 则数组元素 的 地 址 就 可 以 表 示 为 ptr + 0 ~ ptr + 9 或 a + 0 ~ a + 9 ,与 &a[0] ~ &a[9]保持一致。

2) 知道了数组元素的地址表示方法, *(ptr + n )和*(a + n )就表示为数组的各元素即等效于a[ n ] 。

3) 指向数组的指针变量也可用数组的下标形式表示为 ptr[n] ,其效果相当于 *( ptr + n) 。

指针与二维数组

定义一个二维数组:int a[3][4];

其中 a 是 二 维 数 组 的 首 地 址 , &a[0] [0] 既 可 以 看 作 数 组 0 行 0 列 的 首 地 址 , 同 样 还 可 以 看 作 是 二 维 数 组 的 首 地 址 , a[0] 是第 0 行 的 首 地 址 , 当 然 也 是 数 组 的 首 地 址 。 同 理 a[n] 就是第 n 行的 首址; &a[n] [m] 就是数组元素 a[n] [m] 的地址。

函数指针

函数也是在内存中存储的,当然函数也有一个起始地址(事实上函数名就是函数的起始地址),这里同样需要弄清函数指针的关系。函数指针定义的形式:返回值类型 (*指针变量名)(形参1,形参2),拿到函数指针其实我们就相当于拿到了这个函数,函数的操作都可以通过指针来完成,而且通过前面的例子可以看到指针作为C语言的数据类型,可以作为参数、作为返回值,那么当然函数指针同样可以作为函数的参数和返回值。

#include <stdio.h>

int sum(int a,int b){
    return a+b;
}

int sub(int a,int b){
    return a-b;
}

//函数指针作为参数进行传递
int operate(int a,int b,int (*p)(int,int)){
    return p(a,b);
}

int main(int argc, const char * argv[]) {
    int a=1,b=2;
    int (*p)(int ,int)=sum;//函数名就是函数首地址,等价于:int (*p)(int,int);p=sum;
    int c=p(a,b);
    printf("a+b=%d
",c); //结果:a+b=3
    
    
    //函数作为参数传递
    printf("%d
",operate(a, b, sum)); //结果:3
    printf("%d
",operate(a, b, sub)); //结果:-1
    
    return 0;
}

注意,普通的指针可以写成p++进行移动,而函数指针写成p++并没有意义。

原文地址:https://www.cnblogs.com/Lanht/p/10096704.html