0
点赞
收藏
分享

微信扫一扫

C学习记录6——指针

niboac 2022-01-20 阅读 97

C学习记录6——指针

一、计算机存储简介

1.内存

  • 存储器:计算机组成中用来存储程序、数据,辅助CPU进行运算处理的重要部分
  • 内存:内部存储器,暂存程序/数据,断电丢失。一些内存:SRAM、DRAM、DDR、DDR4
  • 外存:外部存储器,长时间保存程序/数据。一些外存:ROM(只读存储器)、ERRROM、FLASH(快存)、硬盘、光盘

内存是沟通CPU和硬盘的桥梁(暂存CPU中运算数据/与外存交换的数据)

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

  • 物理存储器:实际存在的具体存储芯片,如:主板上的内存条、显示卡上的显示RAM芯片、适配卡上的RAM/ROM芯片
  • 存储地址空间:对存储器编码的范围
  • 编码:对每个物理存储单元(一个字节)分配一个号码(32位或64位,与处理器有关)
  • 寻址:根据分配号码找到相应的存储单元,完成数据读写

3.内存地址

将内存抽象位为一个很大的一维数组,编码的内存编号称为内存地址

PS:Windows电脑数据存储时小端对齐
如:0xaabbccdd
在这里插入图片描述

二、指针基础

1.指针与指针变量

指针是一种数据类型,指针变量指向谁,谁就将其地址赋给指针变量
定义什么类型的变量,就用什么类型的指针

int a = 10;
int* p = &a;
a = 100;  //直接改变变量值
*p = 100;  //*:解引用。通过指针间接改变变量a的值

&取地址,升维度;*取值,降维度。

2.指针大小

所有指针类型存储的都是一个无符号的十六进制整形数,在32位(x86)下大小为4字节,64位(x64)下大小为8

3.野指针和空指针

  • 任意数值赋给指针变量毫无意义,这样的指针称为野指针,指向区域未知,不会直接引发错误,操作野指针指向的内存空间(*p)才出现问题
  • 操作系统将0~255作为系统占用不允许访问(读写)操作,指向此处操作不报错(VS2019报错……)
  • 为标志此指针变量未指向任何变量(空闲可用),C中可将NULL赋值给此指针,标志其为空指针。(NULL是一个值为0的宏常量)内存地址编号为0的空间,操作空指针对应的空间必报错
  • 空指针可用于条件判断

4.万能指针viod*

可指向任意的内存空间,可接收任意内存地址
在通过万能指针修改变量的值时,需要找到变量对应的指针类型

int a = 10;
void *p = &a;
*((int *)p) = 11;  //使用指向的内存时转换为int*

5.const修饰的指针变量

const常量可以用指针间接改值

  1. const修饰指针类型(const int* p = &a;常量指针)可修改指针变量的指向(p的值),不可修改指向内存空间的值(*p的值)
  2. const修饰指针变量(int* const p = &a;指针常量)不可修改指针变量的指向(p的值),可修改*p的值(只读指针)

const离谁近,谁的值不变

  1. const同时修饰指针类型,指针变量,p、p*都不可改

const一级指针可以用二级指针改值

int** p1 = &p;
*p1 = p = &a;
**p1 = a;

三、指针和数组

1.数组名

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

2.指针操作数组元素

int arr[]={};
int* p = arr;

arr[i]与p[i]相同(地址+下标偏移量(允许负数))
arr[i]下标从0(原位置)偏移i,与*(arr+i)、*(p+i)相同
指针类型变量+1等同与内存地址+sizeof(类型)
区别:

  • p为常量,arr为变量
  • p是指针,4字节大小,arr为数组(4*元素个数)字节大小

3.指针加减法运算

  1. 加法、减法
    int*+1结果是增加一个int的大小,指向数组下一元素
  2. 指针相加减
    两指针相加,得野指针,报错
    两指针相减,得两指针的偏移量(步长)=数值差/sizeof(int)(所有指针类型,相减结果都是int型)
  3. 其它运算
    指针不允许乘除取余,允许比较,逻辑判断(&&……),赋值

4.指针数组

数组中每个元素都是指针类型

int a = 10,b=20,c=30;
int * arr[3] = {&a,&b,&c};

指针数组是一个特殊的二维数组模型

int a[]={1,2},b[]={3,4};
int* arr[] = {a,b};
printf("%d\n",arr[0][1]);输出2  //arr[0]=a=&a[0]
//arr[i][j] = *(arr[i]+j) = *(*(arr+i)+j))

指针数组对应二级指针

四、多级指针

二级指针指向一级指针变量地址

int a[]={1,2},b[]={3,4};
int* arr[] = {a,b};
int** p = arr;
//二级指针加偏移量相当于调过了一个一维数组大小(1行)
printf("%d\n ",**(p+1));输出3  
//一级指针加偏移量,相当于跳过一个元素
printf("%d\n ",*(*p+1));输出2  

五、指针和函数

参数中形参改为指针,可减少内存空间占用,不会复制新的副本

1.值传递

形参不影响实参

void swap(int a,int b)
{
	int temp = a;
	a = b;
	b = temp;
}
int main()
{
	int a = 10;
	int b = 20;
	swap(a,b);
	printf("%d\n",a);
	return 0;
}
输出10

2.地址传递

形参可改变实参

void swap(int* a,int* b)
{
	int temp = *a;
	*a = b;
	*b = temp;
}
int main()
{
	int a = 10;
	int b = 20;
	swap(&a,&b);
	printf("%d\n",a);
	return 0;
}
输出20

PS:数组名做函数参数,函数会退化为指针

六、指针和字符串

1.字符指针

(1)char* p = "hello world";可执行,但不可用p[i] = 'x’修改(数据区常量区字符串)
char ch[] = "hello world";栈区字符串
若再写char* p1 = "hello world";仍与(1)指向同一地址

2.指针数组做为main函数形参

int main(int argc,char* argv[])
argc:命令行参数个数,程序名本身算一个参数
argv:命令行参数的字符串数组,指向输入参数

举报

相关推荐

0 条评论