C语言编程学习(六)——指针

指针


指针变量的定义和使用:

  1. 指针也是一种数据类型,指针变量也是一种变量
  2. 指针变量指向谁,就把谁的地址赋值给指针变量
  3. “*”操作符操作的是指针变量指向的内存空间
#include <stdio.h>

int main()
{
	int a = 0;
	char b = 100;
	printf("%p, %p\n", &a, &b); //打印a, b的地址

	//int *代表是一种数据类型,int*指针类型,p才是变量名
	//定义了一个指针类型的变量,可以指向一个int类型变量的地址
	int *p;
	p = &a;//将a的地址赋值给变量p,p也是一个变量,值是一个内存地址编号
	printf("%d\n", *p);//p指向了a的地址,*p就是a的值

	char *p1 = &b;
	printf("%c\n", *p1);//*p1指向了b的地址,*p1就是b的值

	return 0;
}
008FF87C, 008FF873
0
d
请按任意键继续. . .

注意

&可以取得一个变量在内存中的地址。但是,不能取寄存器变量,因为寄存器变量不在内存里,而在CPU里面,所以是没有地址的。


指针的大小:

  1. 使用sizeof()测量指针的大小,得到的总是:4或8
  2. sizeof()测的是指针变量指向存储地址的大小
  3. 在32位平台,所有的指针(地址)都是32位(4字节)
  4. 在64位平台,所有的指针(地址)都是64位(8字节)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main() {

	int *p1;
	char *p2;
	float *p3;
	int **p11;
	char **p22;
	float **p33;
	printf("sizeof(p1) = %d\n", sizeof(p1));
	printf("sizeof(p2) = %d\n", sizeof(p2));
	printf("sizeof(p3) = %d\n", sizeof(p3));
	printf("sizeof(p11) = %d\n", sizeof(p11));
	printf("sizeof(p22) = %d\n", sizeof(p22));
	printf("sizeof(p33) = %d\n", sizeof(p33));
}

X64

sizeof(p1) = 8
sizeof(p2) = 8
sizeof(p3) = 8
sizeof(p11) = 8
sizeof(p22) = 8
sizeof(p33) = 8
请按任意键继续. . .

X86

sizeof(p1) = 4
sizeof(p2) = 4
sizeof(p3) = 4
sizeof(p11) = 4
sizeof(p22) = 4
sizeof(p33) = 4
请按任意键继续. . .

野指针和空指针:

野指针:不同于定义的a,其在程序本身没有具体地址。它指向的是一个未知的内存空间(操作系统不允许指针指向的内存区域)。所以,野指针不会直接引发错误,操作野指针指向的内存区域才会出问题。

//野指针
    //指向内存编号为100的内存地址
    //0-255都是系统保留的,不能读、写
    //野指针(不同于a,在程序本身没有)指向的是一个未知的内存空间,在读写的时候可能出错也可能不出错
	int a = 100;
	int *p;
	p = a; //把a的值赋值给指针变量p,p为野指针, ok,不会有问题,但没有意义
        p = 0x12345678; //给指针变量p赋值,p为野指针, ok,不会有问题,但没有意义
        *p = 1000;  //操作野指针指向未知区域,内存出问题,err

万能指针以及指针指向数组某个元素:

是使用 void * p来创建指针变量

int a = 10;
//万能指针
void *p = NULL;
p = &a;
//对于万能指针赋值需要对应原来值的变量类型(强转)
*(int *)p = 100;
printf("%d\n", a);
printf("%d\n", *(int *)p);	//需要告诉指针读取多少个字节大小(这里int为四个字节大小)

 指针指向数组某个元素并输出

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

int main() {

	int arr[10] = { 0 };	//初始化数组全为0
	void* p = &arr;		//创建万能指针
	*(int *)p = 100;	//将arr[0]赋值为100(表示的是初始地址)
	*((int *)p + 1) = 200;	//此时p已经被转换成int类型,故进行+1操作表示是下一个元素位置(相当于地址+4)
	for (int i = 0; i < 10; i++)
	{
		printf("%d\n", arr[i]);
	}
}
100
200
0
0
0
0
0
0
0
0
请按任意键继续. . .

const修饰指针

const修饰什么类型的变量,其变量就无法直接更改。简而言之,就是const修饰的变量被锁死,无法进行更改。

 const修饰内容以及结果:

const修饰内容

结果

const int a = 10;

//a = 100;

int *p = &a;

*p = 100;

 

可以通过一级指针修改常量的值

 const int* p;

p = &a;

p = &b;

//*p = 100;

 

const修饰指针类型

可以修改指针指向的地址

int * const p = &a;

*p = 100;

//p = &b;

const修饰指针变量

可以修改指针指向地址的值

const int * const p = &a;        

//p = &b;

//*p = b;

Const修饰指针数据类型

Const修饰指针变量

都不可以修改

 

 

代码如下:(具体看代码注释)

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
//这样安全,别人找不到所存的地址
#define MAX 100
int main401() {
	//这种方式不安全,可以通过指针修改
	//1、通过一级指针修改const修饰的常量
	const int a = 10;
	//a = 100;
	int *p = &a;
	*p = 100;
	printf("a的值%d\n", a);
	printf("*p的值%d\n", *p);
	return 0;
}

int main402() {

	//2、const能改变指针变量对应的地址,但是不能直接修改指向内存地址对应的元素
	int a = 10;
	int b = 30;
	//如果const修饰指针类型,则不能修改指针变量指向的内存地址的值,但是可以改变其对应的地址
	const int* p;
	p = &a;
	p = &b;		//改变其对应的地址
	/*	*p = 100;	左值指定const对象	*/
	printf("%d", a);
	return 0;

}

int main403() {

	//const 能改变指针变量对应的地址的值,但是不能修改指针指向的地址
	int a = 10;
	int b = 20;
	//const 修饰谁,则谁就无法改变,这里const修饰指针类型的p,p指向地址,所以地址无法改变
	int * const p = &a;
	*p = 100;
	/*	p = &b;	地址无法修改*/
	printf("%d\n", *p);
	return 0;
}

int main() {

	//const 修饰指针类型也修饰指针变量,则指针指向的地址以及指针指向的值
	int a = 10;
	int b = 20;
	const int * const p = &a;
	/*	都会报错无法修改(二级指针可以修改)
		p = &b;
		*p = b;
	*/

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值