指针(一)

目录

1 内存和地址

 2 指针变量和地址

 2.1 指针变量

2.2 指针变量的大小

3 指针变量类型的意义

 3.1 指针的解引用

3.2 指针+-整数

3.3 void*指针 

4 const修饰指针 

4.1 const修饰变量

 4.2 const修饰指针变量

5 指针运算

5.1 指针+-整数

5.2 指针-指针

5.3 指针的关系运算

 6 野指针


 

1 内存和地址

计算机CPU处理数据时,需要的数据从内存中读取,处理后也会放入内存中。为了高效管理内存空间,将内存划分成一个个的内存单元,每个内存单元的大小取一个字节,即8个比特位,每个比特位可以储存一个2进制的1或0。如:0X00000001   前面0X表示16进制

每个内存单元都有新编号,便于查找。C语言中地址的新名称:指针。

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

 2 指针变量和地址

取地址操作符&       解引用操作符* 

#include<stdio.h>
int main()
{
	int a = 10;
	int *pa = &a;//取出a的地址并存放在pa中 
	
	*pa=8;
	
	printf("%d",a);//输出8 
	
	return 0;
	
 } 

 2.1 指针变量

通过取地址操作符&取出的地址是数值,为了方便后期使用,我们将地址值存放在指针变量中。上述例子中指针变量就是pa,pa是变量,且存放a的地址,所以叫指针变量。

int *pa = &a;

*pa = 0;

*说明pa是指针变量,前面的int说明pa是指向整型(int)的类型对象。a的类型为int,pa的类型为int *。

*pa的意思是通过pa中存放的地址,找到指向的空间,*pa其实就是a变量。

指针变量有int */char */short */double *等类型。

2.2 指针变量的大小

#include<stdio.h>
int main()
{
	printf("%zd\n",sizeof(char *));//输出4/8
	printf("%zd\n",sizeof(int *));//输出4/8
	printf("%zd\n",sizeof(short *));//输出4/8
	printf("%zd\n",sizeof(double *));//输出4/8
	
	return 0; 
 } 

32位平台下地址是32个bit位,指针变量大小是4个字节。

64位平台下地址是64个bit位,指针变量大小是8个字节。

VS_2022中, X86环境下是32个bit位,X64是64个bit位。

指针变量的大小与类型无关,在相同的平台下,指针变量大小相同。

3 指针变量类型的意义

 3.1 指针的解引用

指针的类型决定了对指针解引用的时候会获得多大权限 (一次能操作多少字节)。

如:char*的指针解引用只能一个字节,int*的可以访问四个字节。

3.2 指针+-整数

#include<stdio.h>
int main()
{
	int n = 10;
	char *pc = (char*)&n;
	int *pi = &n;
	
	printf("%p\n",&n);// 00AFF974
	printf("%p\n",pc);// 00AFF974
	printf("%p\n",pc+1);// 00AFF975
	printf("%p\n",pi);// 00AFF974
	printf("%p\n",pi+1);// 00AFF978
	
	
	
	return 0; 
 } 

&n、pc、pi都表示n的地址,pc是char*型,pi是int*型,所以pc+1增加一个字节,地址+1,pi+1增加4个字节,地址+4。

指针类型决定了指针向前或向后走一步有多少距离。

3.3 void*指针 

void*类型,无具体类型的指针(或者叫泛型指针),可以接受任意类型地址。但不能直接进行指针的+-整数和解引用的运算。

1 int a =10;

2 int *p1 = &a;

3 char *p2 = &a;        //void* p2=&a;

将int类型的变量的地址赋值给char*类型的指针变量(int型a的地址赋值给char* pa),类型不兼容,编译器会给警告,使用void*类型就不会有问题。 (不能*p2,void*类型指针不可以解引用)

4 const修饰指针 

4.1 const修饰变量

变量是可以修改的,要想使其不能修改,需加上const。

#include<stdio.h>
int main()
{
	int m = 0;
	m = 20;//m从0变成20 
	const int n = 10;//使用const,n不可改变 
	n = 20;//err,程序不运行 
	printf("%d %d",m,n);//20 10
	return 0;
 } 

 const int n = 10,n本质还是变量,只是无法修改。const修饰变量a时,a叫常变量。

此时n无法修改,但如果使用指针修改n,还是能改变n的值。

1 const int n =10;

2 int* p = &n;

3 *p = 20;

 4.2 const修饰指针变量

const修饰指针变量,两种形式。

1 int const * p;//const放在*的左边做修饰(或const int * p)*p不可变

2 int * const p;//const放在*的右边做修饰                               p不可变 

//int const * const p                                                         *p,p都不可变

const放在*左边,修饰的是指针指向的内容,指针指向的内容不能通过指针改变。但指针本身的内容可以变。

const放在*右边,修饰的是指针变量本身,指针变量的内容不能修改,但是指针指向的内容可以用指针来改变。

5 指针运算

三种:

指针+-整数

指针-指针

指针的关系运算 

5.1 指针+-整数

数组在内存中连续存放,只要知道第一个元素的地址,就可以找到后面所有元素。

#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]);
	for(i = 0; i < sz;i++){
		printf("%d ",*(p+i));//没学指针前,此处填arr[i] 
	}
	return 0;
}

p中存放第一个元素的地址,*p表示第一个元素,*(p+i)表示后续元素。

5.2 指针-指针

   指针-指针的绝对值是指针和指针之间元素的个数。计算前提要求两个指针指向同一个空间,否则不连续,无法计算。

#include<stdio.h>
#include<string.h>
size_t my_strlen(char *p)
{
	char* start = p;
	char* end = p;
	while(*end != '\0'){
		end++;
	}
	return end-start;
 } 
int main()
{
	char arr[]="abcdef";
	size_t len = my_strlen(arr);
	printf("%zd\n",len);//6
	return 0;
}

指针+指针无意义。

相当于日期+-天数,日期-日期计算天数,而日期+日期无意义 。

5.3 指针的关系运算

指针的大小比较。 

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

 6 野指针

 野指针产生原因:指针未初始化,指针越界访问,指针指向的空间释放。

int *p;//未初始化,默认随机值

int arr[10]={0};

int i = 0;  int * p=&arr[0];

for(i = 0;i<=11;i++){

*(p++) = i;//指针指向的范围超出数组arr的范围时,p就是野指针

}

n是局部变量,将n的地址传给p时,p指向的空间释放

  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值