C语言——指针详解和应用

#参考江科大C语言视频#

一、指针简介

指针(Pointer)

  • 指针是C语言的一个重要知识点,其使用灵活、功能强大,是C语言的灵魂
  • 指针与底层硬件联系紧密,使用指针可操作数据的地址,实现数据的间接访问

1.1  计算机存储机制

  • int a = 0x12345678

int 代表4个字节的数据,4*8 = 32个2进制来表示

a 可以表示为12 34 56 78

如上表所示:最低位78,被分配到了第一个地址;56,被分配到了第二个地址……

这种分配方式把小端放在了内存地址的第一位,被称为小端模式

  • short b = 0x5A6B 

 short 是2字节数据

  • char c[ ] = {0x33, 0x34, 0x35} 

 char 为数组,数组是按照顺序来存储的

 1.2 定义指针

指针即指针变量,用于存放其他数据单元(变量/数组/结构体/函数等)的首地址。若指针存放了某个数据单元的首地址,则这个指针指向了这个数据单元,若指针存放的值是0,则这个指针为空指针。

定义指针变量: 

数据类型

指向该数据类型的指针

(unsigned) char

1字节

(unsigned) char *

x字节

(unsigned) short

2字节

(unsigned) short *

x字节

(unsigned) int

4字节

(unsigned) int *

x字节

(unsigned) long

4字节

(unsigned) long *

x字节

float

4字节

float *

x字节

double

8字节

double *

x字节

16位系统:x=2,32位系统:x=4,64位系统:x=8

指针所占用的位宽 = 系统的位宽

eg1.1.

#include <stdio.h>

int main(void)
{
    int a;
    int *p;

    printf("%d\n",sizeof(a));
    printf("%d\n",sizeof(p));
    return 0;
}

执行结果:

4

8

sizeof() 函数的返回值是输入变量的字节

a是int型,所以为4字节;p是地址,且系统为64位,所以是8字节

 1.3 指针操作

若定义:

  • int a;    //定义一个int型的数据
  • int *p;  //定义一个指向int型数据的指针

则对指针p有如下操作方式:

操作方式

举例

解释

取地址

p=&a;

将数据a的首地址赋值给p

取内容

*p;

取出指针指向的数据单元

p++;

使指针向下移动1个数据宽度

p=p+5;

使指针向下移动5个数据宽度

p--;

使指针向上移动1个数据宽度

p=p-5;

使指针向上移动5个数据宽度

eg1.2.

#include <stdio.h>

int main(void)
{
    char a=0x66;
    char *p;

    p=&a;

    printf("%x\n",a);
    printf("%x\n",p);
    printf("%x\n",*p);

    return 0;
}

输出结果:

66
61fe17
66

*p的意思是 把p的内容作为一个地址然后去找地址的内容

 eg1.3.

#include <stdio.h>

int main(void)
{
    int a=0x66;
    int *p;

    p=&a;

    printf("%x\n",a);
    printf("%x\n",p);
    printf("%x\n",*p);

    p++;
    printf("%x\n",*p);   

    return 0;
}

输出结果:

66
61fe14
66
61fe18 

为什么执行完p++后地址多了4?

  • 因为p++指的是使指针向下移动1个数据宽度,int型是4字节,所以应该是61fe18

若是定义short型,那就是+2;定义char型,就+1.

 1.4 数组与指针

数组是一些相同数据类型的变量组成的集合,其数组名即为指向该数据类型的指针。数组的定义等效于申请内存、定义指针和初始化。

 

例如: char c[] = {0x33, 0x34, 0x35} ;

等效于: 申请内存

                定义char *c = 0x4000;

                初始化数组数据

利用下标引用数组数据也等效于指针取内容

例如:  c[0];  等效于:  *c;

             c[1];  等效于:  *(c+1);

             c[2];  等效于:  *(c+2);

eg1.4.

#include <stdio.h>

int main(void)
{
    char a[]={0x33,0x34,0x35};

    printf("a[0]=%x\n",a[0]);
    printf("a[1]=%x\n",a[1]);
    printf("a[2]=%x\n",a[2]);

    printf("*a=%x\n",*a);
    printf("*(a+1)=%x\n",*(a+1)); 
    printf("*(a+2)=%x\n",*(a+2)); 

    return 0;
}

输出结果:

a[0]=33
a[1]=34
a[2]=35
*a=33
*(a+1)=34
*(a+2)=35

数组名就是数组的首地址

#include <stdio.h>
#include <stdlib.h>


int a[]={0x33,0x34,0x35};

//等效于

int a;
a=malloc(3*4);//申请内存(3个变量*4个字节),其返回值为void*,可以表示任何类型的指针
*a=0x33;
*(a+1)=0x34;
*(a+2)=0x35;

1.5 注意事项

  • 在对指针取内容之前,一定要确保指针指在了合法的位置,否则将会导致程序出现不可预知的错误。
  • 同级指针之间才能相互赋值,跨级赋值将会导致编译器报错或警告。

二、指针的应用

传递参数

  • 使用指针传递大容量的参数,主函数和子函数使用的是同一套数据,避免了参数传递过程中的数据复制,提高了运行效率,减少了内存占用
  • 使用指针传递输出参数,利用主函数和子函数使用同一套数据的特性,实现数据的返回,可实现多返回值函数的设计

传递返回值

  • 将模块内的公有部分返回,让主函数持有模块的“句柄",便于程序对指定对象的操作

直接访问物理地址下的数据

  • 访问硬件指定内存下的数据,如设备ID号等
  • 将复杂格式的数据转换为字节,方便通信与存储

2.1  传递参数

eg2.1.

#include <stdio.h>

void fun(int param)
{
    printf("%x\n",param);
}

int main(void)
{
    int a=0x66;
    fun(a);

    return 0;
}

其中,a和param两个变量存储在两个不同的地址

值传递,数据复制,不会影响主函数变量;弊端:数据过大,占用内存

eg2.2.

#include <stdio.h>

int FindMax(int *array,int length)
{
    int i;
    int max=array[0];
    for(i=1;i<length;i++)
    {
        if(array[i]>max)
        {
            max=array[i];
        }
    }
    return max;
}

int main(void)
{
    int a[]={2,1,6,9,7};
    int Max;
    Max=FindMax(a,5);
    printf("Max=%d\n",Max);
    return 0;
}

指针传递,在子函数中更改数组的值,会影响主函数原来的数组

可以在子函数调用时,在前面加上 const ,说明该调用为常量,为只读,不能修改

eg2.3.

#include <stdio.h>

void FindMaxAndCount(int *max, int *count, int *array, int length)
{
    int i;
    *max=array[0];
    *count=1;

    for(i=1;i<length;i++)
    {
        if(array[i]>*max)
        {
            *max=array[i];
            *count=1;
        }
        else if(array[i]==*max)
        {
            (*count)++;
        }
    }
}

int main(void)
{
    int a[]={2,1,6,9,9,2};
    int Max;
    int Count;

    FindMaxAndCount(&Max,&Count,a,5);

    printf("Max=%d\n",Max);
    printf("Count=%d\n",Count);
    return 0;
}

用指针实现多返回值

主函数中定义变量Max,函数调用&Max,取Max地址赋值给了int *max,为指针变量,*max取值,即为Max。

 2.2 传递返回值

eg2.4.

#include <stdio.h>

/***************************/
int Time[]={16,51,20};

int *GetTime(void)
{
    return Time;
}
/***************************/

int main(void)
{
    int *pt;

    pt=GetTime();

    printf("pt[0]=%d\n",pt[0]);
    printf("pt[1]=%d\n",pt[1]);
    printf("pt[2]=%d\n",pt[2]);

    return 0;
}

通过返回值式指针,获取句柄,从而实现数组的访问。

注意:不能返回局部变量,局部变量在函数执行完后会销毁。

  • 28
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值