C++之指针

指针

指针的大小

取决于编译器位数,如果是X86是32,如果是X64是64;

  1. 没有赋值的指针成为野指针,所以指针所指向的变量一般需要进行初始化,不然的话,指针指向的位置有可能是系统地址的部分。Void *p =NULL;
  2. 取地址是在寄存器中,不占内存;所谓的地址实际是计算机总线,作为一个常量,不占内存;但是指针如果作为一个变量存在,是消耗内存的,比如*p = &num

空指针

void *p;是合法的,因为所有指针的存储大小是一样的,只是解析方式不一样。但是如下方式是不合理的。
Int num = 10;
Void *p = #
Printf(%d”,*p);需进行强制类型转换printf(“%d”,*((int*)p)//指针类型的意义决定解析方式
Int *p = NULL//空指针,指向地址00000000
  1. 指针打印:
    printf(“%p”,&num);显示地址的位数
    printf(“%x”,&num);只显示有效地址数
  2. 取地址是取内存地址:&操作是在寄存器中执行的。
Int a;
&a;//获取内存地址
//&&a;///&a是在寄存器中进行操作,无法对寄存器进行取址操作
//&1;//寄存器的产物,非法操作
//&(a+1);在寄存器中进行操作,非法操作
//&get();//get返回值一般放置在寄存器的cache区或者编译器指定的内存区(禁止访问)

通过指针修改const

Const只能避免直接修改
Const int num =3;
(int)&num =10;//通过int *将不可修改的const int *转换为可修改的int *,且只能通过这种方式修改

指针运算

指针的运算和类型密切相关
Void *p;
p+1;//错误,因为未指定类型,不知道移动的大小
如果不在数组内部,指针的移动没有任何意义;

指针运算

指针的运算和类型密切相关
Void *p;
p+1;//错误,因为未指定类型,不知道移动的大小
如果不在数组内部,指针的移动没有任何意义;

数组指针

(存在数组退化为指针的情况)

int a[10] = [1,2,3,4,5,6,7,8,9,10];
printf(%p,%p”,a, &a);//a表示a[0], 长度是int。&a表示数组首地址,长度是int*length,此处打印一样
Printf(%d,%d”,a, a+1);//a+1相对a移动了int的长度
另外,数组没有副本机制,传递数组实际上会退化为指针。
Printf(%d,%d”,&a, &a+1);//输出相差40个字节,移动了一个数组的长度
Printf(%d,%d”,sizeof(a), sizeof(a+1));//输出40,4;此处a等价于 int a;*(&a);

二级指针

double db = 10.8;
double p = &db;
double pp = &p;
double *px = &p;//不符合标准规范
指针也有副本机制,如,changep(int *p);如果函数中对p进行赋值,改变的只是副本。其实不难理解,如果要在局部函数中改变一个值,那么必须传递其对应的地址,同样,如果想改变一个存储地址的变量,即指针变量,那么必须把指针变量的地址传递过去,即使用
p
如果要修改应该使用指针的指针进行传递,changepp(int **pp);
需要注意p = &b; 与
p = b;的区别

Char *p = “123”’
*p = ‘A’;//错误,常量区不允许修改

指针退化

Char a[5] = {‘a’,’b’,’c’};
Char *b[5] = {‘a’,’b’,’c’};这个地方对吗?对的,没有问题,指针数组名对应的二级指针。
Char **p = b;
Run(char a);//数组a退化为指针a
Run(char **b);//指针数组b退化为二级指针b;
5. 指针数组强化(2020/1/1/21:21)
空类型指针可以指向任何类型的数据,包含他们的地址;因此任何类型的指针都可以存储给空指针。
memset函数,返回的是空指针。以字节为单位进行操作。
用法:memset(str,0,5)#(地址,填充的元素如字符或者数字,字节数)
void p = malloc(1001024
1024);分配内存大小,以字节为单位,返回一个空类型的指针
一个指针包含三部分内容:1)地址2)步长 3)内容如何解析

函数返回值是指针

了解strcpy函数的实现

char* mystrcpy(char *dest, char *source)
{	char *last = NULL;
	if (*dest == NULL || *source == NULL)
	{
		return last;//没有进行任何操作,返回空指针
	}
	last = dest;
	while ((*dest++ = *source++) != '\0');
	return last;
}

数组指针2

Int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
Int b[3][4] = {1,2,3,4,5,6,7,8,9,0,11,12};

a 做一个指针,步长4 指向一个元素
&a一个指针,步长40,指向一个一维数组
b等价于行指针,步长一行的大小;&b步长是整个数组;*b指向列,一个列一个元素4个字节

Int a[10];
Int *p1[10];//指针数组:表示有10个元素,数组中每个值存储的是指针变量。
Int (*p2) [10];//4 指向有10个元素的数组的指针(可以是一维,也可以是二维,因为行是动态扩展的);只是定义了一个指针,但是呢?这个指针的所指向的区域,是一个数组,且大小已经确定,有10个元素,元素类型不确定。

二维数组赋值

int(*p)[5] = malloc(sizeof(int) * 30);//列必须使用常量进行固定,行是动态扩展的

	for (int i = 0; i<30; i++)
	{
		printf("%4d", p[i / 5][i % 5] = i);
		
		if ((i + 1) % 5 == 0)
		{
			printf("\n");
		}	
	}

指针运算

不可以把地址直接赋值给指针,如int*p = 123;//123会被当做一个地址赋值给p,指针一般是间接赋值。

//int * const p;//地址不可以改变,指向的数据可以改变
//const int * p;//指向的数据不可以改变,地址可以改变
Int const * const p;//指向指针的指针常量

地址间隔

int a[5] = { 1,2,3,4,5 };
	char *p1 = a;//
	char *p2 = &a[4];
	//++*p;//作用于首地址
	printf("地址间隔为:%d\n", p2 - p1);

char类型输出为16;int类型输出为4

函数指针强化

定义指向指针的变量的一般形式为:
数据类型(*指针变量名) (函数参数列表);

Int (*p) (int ,int);
通过指针实现通用接口:
int sum(int a, int b)
{
	return a + b;
}
int sub(int a, int b)
{
	return a - b;
}
void op(int(*p)(int, int), int a, int b)//接口固化
{
	printf("%d\n", p(a, b));
}

函数指针的命名方式

int(* getop())(int, int)//一个函数,参数为空,返回值是一个函数指针
{
	return sum;
}
void main()
{
	int a = getop()(1, 2);
}

函数指针定义

int Func(int x); /*声明一个函数*/
int (*p) (int x); /*定义一个函数指针*/
p = Func; /*将Func函数的首地址赋给指针变量p*/

int *p      int (*p)(int,int)  指针与函数指针
int *p[10]   int(*p[10])(int, int)   指针数组与函数指针数组
int **p     int(**p)(int, int)  二级指针与二级函数指针

int (*p)[5]//规律:看结合顺序,*p优先,表示指针
int *p[5]//规律,实际可以这样看,(int *) p[5],表示数组,内容是指针

int( (*p)[5])(int, int)//规律:看结合顺序,*p优先,表示指针
int (*p[5])(int ,int)//规律,实际可以这样看,(int *) p[5],表示数组,内容是指针
  1. 函数指针数组与多线程
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值