指针学习

        程序中定义的变量,在编译时,系统会给这个变量分配内存单元,根据数据类型,分配一定的长度空间。如Visual C++为整型变量分配4个字节,float分配4个字节,对char分配1个字节,内存区的每个字节有一个编号,这就是“地址”。由于通过地址能找到所需的变量单元,可以说,地址指向该变量单元,将地址形象的称为”指针”,即一个变量的地址称为该变量的”指针

 

  指针变量,也是地址变量;       如:

int i=3;            / 定义整型变量并初始化
int *i_pointer;     / 定义整型数据的指针变量
i_pointer=&i;       / 将i 的地址存放到i_pointer中,比如变量i 所占用单元的起始地址为2000,那么i_pointer=2000 。

            *i_pointer=3; 其中*i_pointer 表示指向的对象,指向就是通过地址来实现的。通过i_pointer=2000的地址指向该变量单元,即 i 的值为3.。 例中变量i 的指针为2000(地址),指针变量i_pointer 只是存放地址的变量,不能说i的指针变量是2000。

   

定义指针变量:

         类型名 *指针变量名;              如:int *pointer_1;  对它初始化还可以写成int *pointer_1=&a ; 

        上面定义的指针变量前面的" * " 表示该变量的类型为指针类型,在定义指针变量时必须指定基类型,因不同类型的数据在内存中所占的字节数和存放方式是不同的。指针变量只能存放地址(指针),不能将一个整数赋给一个指针变量,如*i_pointer=100; 把整数100赋给指针变量是非法的。合法赋值为 i_pointer=&a; 

 

 数组指针:

         数组元素的指针就是数组元素的地址。如;

int a[10]={1,2,3,4,5,6,7,8,9,10}; 
int *p;                   / 定义指针变量
p=&a[0];  或 p=a;        / 把a[0]即数组首元素的地址赋给p 。

        数组名a代表数组中首元素a[0]的地址,而不是代表整个数组。

当指针指向数组元素的时候可以对指针进行加减运算,执行p+1时并不是将p的值 (地址)简单的加1,而是加上一个数组元素所占用的字节数。如int 占4个字节,p的值(地址)为2000时,则p+1的值是2004,指向的是数组的下一个元素如a[1];  *(p+1)为a[1]的值。

        *p++等价于*(p++) , *(p++)为先取*p的值,然后再使p+1;而*(++p)为先使p+1,再取*p的值,如p初值为a(即&a[0]),若输出*(p++),得到a[0]的值,若输出*(++p),则得到a[1]的值;++(*p)表示p所指向的元素值加1,不是指针p加1。

        二维数组指针:

        可以认为二维数组是“数组的数组”,如 int a[3][4]; ,a代表二维数组首地址,a+1代表序号为1的行的首地址,即指向a[[1],为a[1]的首地址。比如a即二维数组的首地址为2000,a+1的地址为2000+4x4=2016(因为0行有4个整型数据),a+2代表a[2]的首地址为2032.

        在二维数组中,a[0]是一维数组名,所以 a[0]+1 代表的是二维数组0行1列元素的地址,即地址为2000+4(而不是2016),相当在一维数组范围内讨论。因为a[0] 和 *(a+0)等价,即 a[ i ] 和 *(a+i) 等价, 所以a[0]+1 和 *(a+0)+1都是&a[0][1](即地址的值为2004), 若想得到a[0][1]的值可表示为 : a[0][1]  或  *(a[ 0 ] +1)  或  *(*(a+0)+1)  或  *(*a+1) 

     通过以下例子理解:

输出二维数组的有关数据(地址和值)
int main()
{
    int a[3][4]={1,3,5,7,9,11,13,15,17,19,21,23};

    printf("%d,%d\n", a,*a);                / 0行首地址 和 0行0列元素地址
    printf("%d,%d\n", a[0], *(a+0));        / 0行0列元素地址
    printf("%d,%d\n", &a[0], &a[0][0]);     / 0行首地址 和 0行0列元素地址

    printf("%d,%d\n", a[1],a+1);            / 1行0列元素地址 和 1行首地址
    printf("%d,%d\n", &a[1][0],*(a+1)+0);   / 1行0列元素地址

    printf("%d,%d\n", a[2],*(a+2));         / 2行0列元素 地址
    printf("%d,%d\n", &a[2],a+2);           / 2行首 地址

    printf("%d,%d\n", a[1][0],*(*(a+1)+0)); / 1行0列 元素的 值
    printf("%d,%d\n", *a[2],*(*(a+2)+0));   / 2行0列 元素的 值
    
    return 0;
} 

运行结果:
1245008,1245008
1245008,1245008
1245008,1245008
1245024,1245024
1245024,1245024
1245040,1245040
1245040,1245040
9,9
17,17

    以上程序运行结果,不同编译环境,由于分配的内存不一样,所显示的地址可能不同,但是都是有共同规律的。

 

字符串指针引用:

        用字符指针变量指向一个字符串常量,通过字符指针变量引用字符串常量。在字符串中 ,虽然未定义字符数组,但字符串在内存中是以字符数组形式存放的a[ i ] 和 *(a+i) 也是等价的。

        如;

char *string="I love china!";  
等价于:  
char *string;           / 定义一个char型变量
string="I love china!"; / 把字符串第一个元素的地址赋给字符指针变量string,不能写成*string

再例:将字符串a复制为字符串b,然后输出字符串b

int main()
{
    char a[]="I am a boy.",b[20],*p1,*p2;
    p1=a;p2=b;                    / p1,p2分别指向a数组和b数组中的第一个元素
    for(;*p1!='\0';p1++,p2++)     / p1,p2每次自加1,其中'\0'也可以用ASCII代码 0 来代替
        *p2=*p1;                  / 将p1所指向的元素的值赋给p2所指向的元素
    *p2='\0';                     / 在复制完全部有效字符后加'\0'
    printf("string a is:%s\n",a); / 输出a 数组中的字符
    printf("string b is:%s\n",b); / 输出b 数组中的字符

    return 0;
}

运行结果:
string a is:I am a boy.
string b is:I am a boy.

 

函数指针:

        在编译时,编译系统会为函数代码分配一段存储空间,这段存储空间的起始地址称为这个函数的指针。如:

        类型名  ( *指针变量名 ) ( 函数参数表列 )  →    int (*p) ( int , int);

       定义p是一个指向函数的指针变量,它可以指向函数的类型为整型且有两个整型参数的函数。注意:*p两侧的()不可省略,表示p先与*结合,是指针变量,然后再与后面的()结合,()表示函数,即该指针变量不是指向一般的变量,而是指向函数。

       用指针调用函数:

       如给函数指针变量赋值:p= max; // 将函数入口地址赋给p ,不能写成p=max(a,b);  ,只需给出函数名不需给出参数。

       用函数指针变量调用函数:如: c=(*p)(a,b);  // 调用由p指向的函数,实参为a,b ,得到的函数值(函数返回的类型值)赋给c。

       用指向函数的指针作函数参数:例:

主要方便用于多次调用不同函数:

#include<stdio.h>
int main()
{
    int fun(int x,int y,int (*p)(int,int));  / fun 函数声明
    int max(int,int);                        / max 函数声明
    int min(int,int);                        / min函数声明
    int add(int,int);                        / add函数声明
    
    int a=34,b=-21,n
    printf("please choose 1,2 or 3:");
    scanf("%d",&n);                          / 输入1,2,或 3之一

    if(n==1)      fun(a,b,max);              / 输入1 时调用 max函数
    else if(n==2) fun(a,b,min);              / 输入2 时调用 min函数
    else if(n==3) fun(a,b,add);              / 输入3 时调用 add函数

    return 0;
}

int fun(int x,int y,int(*p)(int,int))        / 定义fun函数
{
    int result;
    result=(*p)(x,y);
    printf("%d\n",result);
}

int min(int x,int y)                        / 定义min 函数
{
    int z;
    ..
    return (z);
}

int max(int x,int y)                        / 定义max 函数
{
    int z;
    ..
    return (z);
}

int add(int x,int y)                        / 定义add 函数
{
    int z;
    ..
    return (z);
}

                                                                   指针小结

指针变量的类型及含义
变量定义类型表示含义
int i;int定义整型变量i
int *p;int *定义p为指向整型数据的指针变量
int a[5];int [5]定义整型数组a,它有5个元素
int *p[4];int *[4]定义指针数组p,它由4个指向整型数据的指针元素组成
int (*p)[4];int (*)[4]p为指向包含4个元素的一维数组的指针变量
int f();int ()f为返回整型函数值的函数
int *p();int *()p为返回一个指针的函数,该指针指向整型数据
int (*p)();int (*)()p为指向函数的指针,该函数返回一个整型值
int **pint **p是一个指针变量,它指向一个整型数据的指针变量
void *p;void *p是一个指针变量,基类型为void(空类型),不指向具体的对象

指针运算:

        例:p++ ,p- - , p+i ,p-i , p+=i , p- = i .    将该指针变量的原值(是一个地址)和它指向的变量所占用的存储单元的字节相加减。

指针赋值:

        例:

p = &a ;               (将变量a的地址赋给p)
p = array ;            (将数组array首元素地址赋给p)
p = &array[i] ;        (将数组array第i个元素的地址赋给p)
p = max ;              (max 为已定义的函数,将max的入口地址赋给p)
p1 = p2 ;              (p1和p2是基类型相同指针变量,将p2的值赋给p1)
                       注意:不应把一个整数赋给指针变量
p = NULL ;             NULL是一个符号常量,在stdio.h 头文件定义 #include NULL 0 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

虾稿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值