#include<初见C语言之指针(1)>

目录

一、内存和地址

1.内存

2.理解编址 

二、指针变量和地址

1.变量

2.指针变量

2.1  * :解引用操作符

2.2指针变量的大小 

三、指针变量类型意义

1.指针解引用

2.指针+-解引用

3.void指针

四、const 修饰指针

1.const 修饰变量

2.const 修饰指针变量

2.1const修饰指针,有两种情况

五、指针运算

1.指针+-整数

2.指针-指针

3.指针的关系运算

总结


一、内存和地址

1.内存

生活中,每个房间有房间号,就能提高效率,快速找到房间,每个内存单元也有编号(这个编号相当于宿舍房间门牌号)

把内存划分成一个个单元,一个内存大小为一个字节

一个字节就好比一个学生宿舍,宿舍是八人间,每个人就是一个比特位

因此:内存单元的编号 == 地址 == 指针

扩展:

计算机储存单位:计算能够识别存储、运算的时候都是使用2进制的

2.理解编址 

计算机访问内存空间必须知道内存空间的地址

地址总线的一根线有0/1两种信号,两根线就会有四种信号,如果电脑是32位那就是32个地址线, 如果电脑是64位那就是64个地址线

数据总线:就是要传输的数据

控制总线:控制数据的操作

下图是大致的计算机操作图,在计算机硬件上有约定好的地址


二、指针变量和地址

1.变量

要想要知道指针变量,那么我们就要知道变量,其实变量的本质就是在内存中开辟一块空间

代码如下(示例):

#include<stdio.h>
int main()
{
	int a = 20;
    printf("%p",&a);
	return 0;
}

 //&取地址操作符 ;%p是专门打印地址的


 //取出的是a的4个字节中的第一个地址(较小的地址)

2.指针变量

2.1  * :解引用操作符

如下图:

int* p中 * 是在说明p是指针变量;int是在说明p指向的是int类型

用代码表示

2.2指针变量的大小 

这里的p也是变量,也是需要向内存申请一块空间,这样才能存放地址

那么p指针变量需要多大的空间?

存放的地址,地址存放需要多大,指针就多大

下面我们使用vs编译器来看看

可以看到指针变量的大小和类型无关

  • (x64)64位机器:地址是64个0/1的二进制序制,存储起来就需要64个bit位,也就是8个字节  
  • (x86)32位机器:地址是32个0/1的二进制序制,存储起来就需要32个bit位,也就是4个字节 

因此只要指针类型的变量,在相同平台下大小都一样 

【注】口头语中指针一般是指针变量

  1. 指针其实就是地址
  2. 指针变量是存放指针的

三、指针变量类型意义

指针变量的⼤⼩和类型⽆关,只要是指针变量,在同⼀个平台下,⼤⼩都是⼀样的,为什么还要有各 种各样的指针类型呢?

1.指针解引用

代码1 

 代码2

通过上述两段代码的调试:我们观察到代码1会将a的4个字节全部改为0,但是代码2只是将a的第⼀个字节改为0。

结论:所以指针的类型决定了,对指针解引⽤的时候有多⼤的权限(⼀次能操作⼏个字节)

  • int*的指针解引用访问4个字节
  • char*的指针解引用访问1个字节
  • short*的指针解引用访问2个字节

2.指针+-解引用

从上述代码可以看出

  • int*的指针类型+1跳过4个字节
  • char*的指针类型+1跳过1个字节

type* p

p+i 是跳过i个type类型的数据,相当于跳过i * sizeof(type)个字节

int* p

p+2相当于跳过2个int类型的数据(2*sizeof(int)==8个字节)

结论:指针类型决定了指针的步长,就是向前/向后走一步有多大距离

【注】根据实际需要,选择适当的指针类型

3.void指针

#include<stdio.h>

int main()
{
    int a = 10;
    int* pa=&a;
    char* pc = &a;
    
    return 0;  
}

如果是上述这样写的代码编译器就会报警告

#include<stdio.h>
int main()
{
    int a = 10;
    void* pv=&a;
    double i = 2.0;
    void* po = &i;
    return 0;  
}

使用void指针可以接受任意类型地址

局限性:void*的指针不能直接进行指针的+-整数和解引用的运算


四、const 修饰指针

1.const 修饰变量

代码1:

#include<stdio.h>
int main()
{
    int n = 10;//n是变量
    n = 0;
    printf("%d\n", n);
}
#include<stdio.h>
int main()
{
    //语法 - 语言的法则
    const int n = 10;//n是变量//const 常属性 - 不能被修改了
    //const修饰了n之后,n不能被修改了,但是n还是变量
    //n是常变量
    n = 0;//不能修改n
    printf("%d\n", n);
}

代码2 

#include<stdio.h>
int main()
{
    int arr[10] = {0};
    const int n = 10;//c++ 中const修饰的n是常量
    int arr[n] = { 0 };
    return 0;

代码3 

#include<stdio.h>
int main()
{
    const int n = 10;
    n=0;//err
    printf("%d\n", n);
    return 0;

2.const 修饰指针变量

前提

  1. p是指针变量,里边存放了其他变量的地址
  2. p是指针变量,*p是指针指向的对象n
  3. p是指针变量,p也有自己的地址,&p

这段代码是const修饰变量

2.1const修饰指针,有两种情况

  • cconst 放在*的左边,限制的是*p,不能通过p来改变指向对象的内容,但是p本身是可以改变的

const int* p = &n;

  • const放在*的右边,限制的是p,不能修改p本身是可以改变的,但是p指向的内容可以通过p来改变的

int* const p = &n;


五、指针运算

1.指针+-整数

如图所示:

数组在内存中是连续存放的,随着数组下标的增长,地址也是由低到高的 

代码:

#include<stdio.h>
int main()
{
    int arr[] = { 1,2,3,4,5,6,7,8 };
    int sz = sizeof(arr) / sizeof(arr[0]);
    int i = 0;
    int* p = &arr[0];
    for (i = 0; i < sz; i++)
    {
        printf("%d ", *p);
        p++;//p=p+1
    }
    return 0;
}

画图演示: 

2.指针-指针

指针 - 指针,运算的前提是两个指针指向了同一块空间
#include<stdio.h>
int main()
{
	int arr[10] = { 0 };
	printf("%d\n", &arr[9]-&arr[0]);//指针 - 指针
	printf("%d\n", &arr[0]-&arr[9]);//指针 - 指针
	//指针 - 指针的绝对值是指针和指针之间的元素个数	
	char ch[6] = { 0 };
	printf("%d\n", &arr[9] - &arr[4]);//err
	return 0;
}

3.指针的关系运算

strlen的模拟实现

#include<stdio.h>
#include<string.h>
int my_strlen(char* p)
{
	int count = 0;
	/*while (*p != '\0')
	{
		count++;
		p++;
	}*/

	return count;
}
int my_strlen(char* p)
{
	char* p1 = p;
	while (*p != '\0')
	{
		p++;
	}
	return p - p1;//指针 - 指针
}
int main()
{
	char arr[] = "abcdef";
	//数组名其实就是数组首元素地址
	//arr == &arr[0]
	int len = my_strlen(arr);
	printf("%d\n", len);//指针 - 指针

	return 0;
}
#include<stdio.h>
int main()
{
	int arr[] = { 1,2,3,4,5,6,7,8,9,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	int* p = &arr[0];
	while (p < arr + sz)//指针的关系运算
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}
#include <stdio.h>
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int* p = &arr[0];
	int i = 0;
	int sz = sizeof(arr) / sizeof(arr[0]);
	while (p < arr + sz)  //指针的⼤⼩⽐较
	{
		printf("%d ", *p);
		p++;
	}
	return 0;
}

总结

这里是指针的第一小部分,主要包括了内存和地址、指针变量和地址、指针变量类型意义、const修饰指针、指针的运算。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值