C语言—指针

概述

内存

内存含义:

  • 存储器:计算机的组成中,用来存储程序和数据,辅助CPU进行运算处理的重要部分。
  • 内存:内部存贮器,暂存程序/数据——掉电丢失 SRAM、DRAM、DDR、DDR2、DDR3。
  • 外存:外部存储器,长时间保存程序/数据—掉电不丢ROM、ERRROM、FLASH(NAND、NOR)、硬盘、光盘。

内存是沟通CPU与硬盘的桥梁:

  • 暂存放CPU中的运算数据
  • 暂存与硬盘等外部存储器交换的数据

物理存储器和存储地址空间

有关内存的两个概念:物理存储器和存储地址空间。

物理存储器:实际存在的具体存储器芯片。

  • 主板上装插的内存条
  • 显示卡上的显示RAM芯片
  • 各种适配卡上的RAM芯片和ROM芯片

存储地址空间:对存储器编码的范围。我们在软件上常说的内存是指这一层含义。

  • 编码:对每个物理存储单元(一个字节)分配一个号码
  • 寻址:可以根据分配的号码找到相应的存储单元,完成数据的读写

内存地址

  • 将内存抽象成一个很大的一维字符数组。
  • 编码就是对内存的每一个字节分配一个32位或64位的编号(与32位或者64位处理器相关)。
  • 这个内存编号我们称之为内存地址。
    内存中的每一个数据都会分配相应的地址:
  • char:占一个字节分配一个地址
  • int: 占四个字节分配四个地址
  • float、struct、函数、数组等

指针基础知识

指针变量的定义和使用

  • 指针也是一种数据类型,指针变量也是一种变量
  • 指针变量指向谁,就把谁的地址赋值给指针变量
  • “*”操作符操作的是指针变量指向的内存空间
    示例:
#include<stdio.h>
int main(void)
{
   
	//定义指针变量存储变量地址
	int a = 10;
	//指针类型--->数据类型*
	int* p;
	p = &a;
	//通过指针间接改变变量的值
	*p = 100;
	printf("%p\n", &a);
	printf("%p\n", p);

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

结果:

00A0FA34
00A0FA34
100
100

示例:

#include<stdio.h>
int main(void)
{
   
	//在定义指针类型时一定要和变量的类型对应上
	char ch = 'a';
	char* p = &ch;
	//&是取地址符号是升维度的
	//*是取值符号是降维度的
	//int a = 10;
	//int *p = &a;
	//所有的指针类型存储的都是内存地址,内存地址都是一个无符号十六进制整型数
	printf("%d\n", sizeof(char*));//4
	printf("%d\n", sizeof(int*));
	printf("%d\n", sizeof(short*));
	printf("%d\n", sizeof(long*));
	printf("%d\n", sizeof(long long*));
	printf("%d\n", sizeof(float*));
	printf("%d\n", sizeof(double*));
	return 0;
}

结果:

4
4
4
4
4
4
4

在32位操作系统下所有的指针类型是4个字节大小
在64位操作系统下所有的指针类型是8个字节大小

野指针和空指针

#include <stdio.h>

int main0201(void)
{
   
	//不建议将一个变量的值直接赋值给指针
	//野指针---->指针变量指向一个未知的空间
	int* p = 100;//程序中允许出现野指针
	//操作系统将0-255作为系统占用不允许访问操作
	//操作野指针对应的内存空间可能报错
	printf("%d\n", *p);
	return 0;

}

int main(void)
{
   
	//空指针是指内存地址编号为0的空间
	int* p = NULL;
	//操作空指针对应的空间一定会报错
	*p = 100;
	printf("%d\n", *p);
	//空指针可以用在条件判断
	return 0;
}

万能指针

void *指针可以指向任意变量的内存空间:
示例:

#include<stdio.h>

int main(void)
{
   
	int a = 10;
	//int* p = &a;
	//万能指针可以接收任意类型变量的内存地址
	void* p = &a;
	//在通过万能指针修改变量的值时,需要找到变量对应的指针类型
	*(int*)p = 100;
	printf("%d\n", a);
	printf("%d\n", *(int*)p);
	printf("万能指针在内存占的字节大小:%d\n", sizeof(void*));
	return 0;

结果:

100
100
万能指针在内存占的字节大小:4

const修饰的指针变量

  • 指针简介修改常量的值
    示例:
#include<stdio.h>
int main(void)
{
   
	//常量
	const int a = 10;
	//指针间接修改常量的值
	int* p = &a;
	*p = 100;
	printf("%d\n", a);
	return 0;
}

结果:

100
  • const修饰指针类型
    可以修改指针变量的值,不能修改指针指向内存空间的值。
    示例:
#include<stdio.h>
int main(void)
{
   
	int a = 10;
	int b = 20;
	const int* p = &a;

	p = &b;//修改指针变量的值  ok
	//*p = 100;//修改指针对应的内存空间的值   error
	printf("%d\n", *p);
	return 0;

结果:

20
  • const 修饰指针变量
    可以修改指针指向内存空间的值,不可以修改指针变量的值。
    示例:
#include<stdio.h>
int main(void)
{
   
	int a = 10;
	int b = 20;
	int* const p = &a;
	//p=&b//不能修改指针变量的值  error
	*p = 100;//能修改指针对应的内存空间的值  ok
	printf("%d\n", a);
	return 0;

结果:

100

总结:const 不能修改离自己近的值,如const int* p = &a;不能修改*p的值
int* const p = &a;不能修改 p的值

const修饰指针类型,修饰指针变量

示例:

#include<stdio.h>
int main(void)
{
   
	int a = 10;
	int b = 20;
	//const修饰指针类型,修饰指针变量  称作只读指针
	const int* const p = &a;
	//p = &b;//不能修改指针变量 error
	//*p = 100;//不能修改指针对应的内存空间的值  error
	//二级指针操作
	int** pp = &p;
	*pp = &b;//*pp是一级指针的值  ok
	printf("%d\n", *p);
	**pp = 100;//**pp是变量的值   ok
	printf("%d\n", *p);
	return 0;
}

结果:

20
100

指针和数组

  • 数组名字是数组的首元素地址,但它是一个常量

指针操作数组元素

示例:

#include<stdio.h>

int main(void)
{
   
	int arr[] = {
    1,2,3,4,5,6,7,'a','b','c' };
	
	//数组名是常量不允许赋值
	//arr = 100;//error

	//数组名是数组首元素地址
	int* p=arr;

	printf("%p\n", p);
	printf("%p\n",arr);
	printf("%d\n", *p);//数组名是数组首元素地址,所以*p表示的是首地址上的元素
	printf("\n");

	//p++;
	//printf("%p\n", arr);//地址的改变
	//printf("%p\n", p);

	for (int i = 0; i < 10; i++)
	{
   
		//printf("%d\n", arr[i]);\\==
		//printf("%d\n", *(arr + i));//==  指针类型变量+1,等同于内存地址+sizeof(int)
		//如:arr=首地址=0ffx00,arr+1=首地址+1=0xff04
		//printf("%d\n", p[i]);//==
		printf("%d\n", *p);//地址改变后,打印相应地址对应的变量的值
		p++;

	}
	printf("\n");
	//两个指针相减  等于的结果是两个指针的偏移量(步长)
	//所有的指针类型相减的结果都是int类型
	int step = p - arr;
	printf("%d\n", step);
	return 0;
}

结果:

0053FB64
0053FB64
1

1
2
3
4
5
6
7
97
98
99

10

示例:

#include<stdio.h>

int main(void)
{
   
	//p和arr的区别
	int arr[] = {
    1,2,3,4,5,6,7,8,9,10 };
	int* p = arr;

	//p是变量,arr是常量
	printf("指针类型大小:%d\n", sizeof(p));//p是一个指针是4个字节的大小
	printf("数组大小:%d\n", sizeof(arr));//arr是一个数组是40个字节的大小
}
return 0;

结果:

指针类型大小:4
数组大小:40
  • 数组在作为函数参数的时候就退化为指针了,丢失了数组的精度
    示例:
void BubbleSort(int arr[],int len)//数组在作为函数参数的时候就退化为指针了,丢失了数组的精度,所以需要设置len 参数
{
   
	for (int i = 0; i < len - 1; i++)
	{
   
		for (int j = 0; j < len - 1 - i; j++)
		{
   
			if (arr[j] >arr[j + 1])
			{
   
				int temp = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = temp;
			}


			/*if (*(arr + j) > *(arr + j + 1))
			{
				int temp = *(arr + j);
				*(arr + j) = *(arr + j + 1);
				*(arr + j + 1) = temp;
			}*/
		}

	}
}
int main(void)
{
   
	int arr[] = {
    9,1,5,6,3,8,10,7,4,2};
	BubbleSort(arr, 10);
	for (int i = 0; i < 10; i++)
	{
   
		printf("%d\n", arr[i]);
	}
	return 0;
}

结果:

1 2 3 4 5 6 7 8 9 10

指针加减运算

  • 指针计算不是简单的整数相加
  • 如果是一个int *,+1的结果是增加一个int的大小
  • 如果是一个char *,+1的结果是增加一个char大小
    示例: 拷贝字符串
#include<stdio.h>

void my_strcpy01(char ch[], char dest[])//字符串拷贝函数,使用数组写的 ==
{
   
	int i = 0;
	while (ch[i] != '\0')
	{
   
		dest[i] = ch[i]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值