指针

一、什么是指针
     计算机中所有的数据都必须放在内存中,不同类型的数据占用的字节数不一样,例如int类型占用4个字节,char类型占用1个字节。为了正确地访问这些数据,必须为每个字节都编上号码,就想门牌号一样,每个字节的编号是唯一的,根据编号可以准确地找到某个字节。我们将内存中字节的编号称为地址或指针。地址从0开始最小的地址为0x0000 0000,最大的地址为0xFFFF FFFF。
在这里插入图片描述
二、定义一个指针``

int *p,s;         //p是整型指针变量,s是整型变量
char *cpa,*cpb;     //cpa和cpb都是char类型指针变量
int a=10;    
int *ip;             //指针一般要直接进行初始化
ip =&a;              //等价于  int *p=&a;

三、空指针和野指针
1、空指针
int *p = NULL; NULL 指针是一个特殊的指针变量,表示不指向任何东西。
2、野指针
2.1 使用未初始化的指针

  int i = 3;
    int *j; 
    *j = i;

     指针在被定义的时候,如果程序不对其进行初始化的话,它会随机指向一个区域,当程序往这块内存空间写数据时会报错。
2.2 free指针后未把指针置为NULL

      char *p;
    p = (char*)malloc(20);
    free(p);

    这儿已经释放了p指向的内存空间。但是p指向的内存地址还没有变,如果别的程序在使用这款空间时会出现一些不可估量的问题。
四、指针的运算
1、指针 +/- 整数 :

    int    a = 10,   *pa = &a, *paa = &a;
    double b = 99.9, *pb = &b;
    char   c = '@',  *pc = &c;
    //最初的值
    printf("&a=%#X, &b=%#X, &c=%#X\n", &a, &b, &c);
    printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc);
    //加法运算
    pa++; pb++; pc++;
    printf("pa=%#X, pb=%#X, pc=%#X\n", pa, pb, pc);

运行结果:
&a=0X28FF44, &b=0X28FF30, &c=0X28FF2B
pa=0X28FF44, pb=0X28FF30, pc=0X28FF2B
pa=0X28FF48, pb=0X28FF38, pc=0X28FF2C
可以看到指针的类型不同,加1的能力也不一样。
typename *p;
p=p+1; 被编译器翻译成 : p = p +sizeof(typename)*1;

2、指针 - 指针 :
两个同类型指针,指向连续空间可以相减。减后的结果是数据元素的大小。
如: int类型指针 - int类型指针结果是整型元素的个数。
        char类型指针 - char 类型指针结果是整型元素的个数。

#include "stdio.h"

int main(){
    int a[10] = {1,2,3,4,5,6,7,8,9,0};
    int sub;
    int *p1 = &a[2];
    int *p2 = &a[8];

    sub = p2-p1;                                                                            
    printf("%d\n",sub);    // 输出结果为 6

    return 0;
}

五、数组与指针
1、利用指针访问数组

int ar[10] = {1,2,3,4,5,6,7,8,9,0};
int *p=ar;
for(int i=0;i<10;i++)
{
printf("%d",*(p+n);
}

2、指针数组

int *p[20]//定义一个大小为20,类型为int*类型的数组。

3、数组指针

 int main(){
     int ar[2][3] = {1,2,3,4,5,6};               // 定义一个二维数组并初始化
     int (*p)[3];                       // 定义一个数组指针,指针指向一个含有3个元素的一维数组
     p = ar;                                     // 将二维数组的首地址赋给 p,此时 p 指向 arr[0] 或 &arr[0][0]
     printf("%d\n",(*p)[0]);              // 输出结果为 1
     p++;                         // 对 p 进行算术运算,此时 p 将指向二维数组的下一行的首地址,即 &arr[1][0]
     printf("%d\n",(*p)[1]);                      // 输出结果为5
     return 0;                                                                               
 }

六、结构体指针
       结构体指针是指向结构的指针。可以用->进行成员访问


typedef struct Stu{
    char name[10];
    int age;
    int score;  
};

int main(){
    struct Stu stu1= {"zhangsan",23,80};
   struct Stu *p = &stu1;

    printf("%s\n",p->name);      // 输出结果为:zhangsna
    printf("%d\n",p->score);         // 输出结果为:80

    return 0;
}

七、函数指针
 在C语言中,函数本身不是变量,但是可以定义指向函数的指针,也称作函数指针,函数指针指向函数的入口地址。这种类型的指针可以被赋值、存放在数组中、传递给函数以及作为函数的返回值等等。 声明一个函数指针的方法如下:

int (*pointer)(int *,int *);        // 声明一个返回值为int型,形参列表为2个指针变量的函数指针。
#include<stdio.h>
void* Print_Int(void* p)  //利用无类型的指针接收地址
{
	int* ip = (int*)p;
	printf("%d ", *ip);
	return ip + 1;
}
void* Print_Double(void* p)
{
	double* dp = (double*)p;
	printf("%lf ", *dp);
	return dp + 1;
}

void Print_Array(void* br, int n, void* (*fp) (void*))
{
	for (int i = 0; i < n; ++i)
	{
		br = (*fp)(br);     利用(*fp)调用函数
	}
	printf("\n");
}
int main()
{
	int ar[] = { 12,23,34,45,56,67,78 };
	int in = sizeof(ar) / sizeof(ar[0]);
	double dx[] = { 1.2,2.3,3.4,4.5,5.6,6.7,7.8,8.9 };
	int dn = sizeof(dx) / sizeof(dx[0]);
	Print_Array(ar, in, Print_Int);
	Print_Array(dx, dn, Print_Double);

	return 0;
}

输出结果:
12 23 34 45 56 67 78
1.200000 2.300000 3.400000 4.500000 5.600000 6.700000 7.800000 8.900000

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值