C++-知识点1-指针

本文深入探讨了C++中指针的基本概念与使用方法,包括不同类型指针的定义、指针算术运算、指针与数组的关系、指针与结构体的交互方式,以及指针类型转换的安全性等问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

指针https://blog.youkuaiyun.com/qq_41035588/article/details/79673674

int **num

指针的类型:去掉num,int**

指针所指向的类型:去掉*num,int*

指针存储的值:32bit系统(4byte),指针是指向内存某块区域的首地址,内存地址32bit长,即指针本身所占据的内存区,永远是4byte

(1)int*ptr; //指针所指向的类型是int
(2)char*ptr; //指针所指向的的类型是char
(3)int**ptr; //指针所指向的的类型是int*
(4)int(*ptr)[3]; //指针所指向的的类型是int()[3]
(5)int*(*ptr)[4]; //指针所指向的的类型是int*()[4]
// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
	int array[20]={0};  
	int *ptr=array;  
	for(int i=0;i<20;i++)  
	{  
		(*ptr)++;  
		ptr++;//add 1,sizeof(int)=4byte,加指针所指向数据类型的大小
		cout<<array[i]<<endl;
	}  
	system("pause");
	return 0;
}

https://blog.youkuaiyun.com/zmz971751504/article/details/79363126

数组名可以看作指针。

&是取地址运算符,*是间接运算符。

	char a[20]="You_are_a_girl"; //a++,and sizeof(char)=1byte 
	cout<<&a<<endl;//00FAFDB0
	int *ptr=(int *)a; 
	ptr++; //ptr add 1,add sizeof(int)=4byte
	cout<<ptr<<endl;//00FAFDB4
	char a[20]=" You_are_a_girl";  
	char *p=a;  
	char **ptr=&p;  
	printf("p=%d\n",p);  //address1
	printf("ptr=%d\n",ptr);  //address2
	printf("*ptr=%d\n",*ptr);  //address1
	printf("**ptr=%c\n",**ptr);  //none
	ptr++;//error ,add 1, add sizeof(char*)
	int a,*b,**c;
	**c=*b=a
	 *c= b=&a
	  c=&b
	int array[10]={0,1,2,3,4,5,6,7,8,9},value;  
	value=array[0]; //也可写成:value=*array;  
	value=array[3]; //也可写成:value=*(array+3);  
	value=array[4]; //也可写成:value=*(array+4);  
	char *str[3]={  //二维
		"Hello,thisisasample!",  
		"Hi,goodmorning.",  
		"Helloworld"  
	};  
	char s[80];
	strcpy(s,str[0]); //也可写成strcpy(s,*str);  sizeof(char[3])=3byte
	cout<<s<<endl;
	strcpy(s,str[1]); //也可写成strcpy(s,*(str+1));  
	cout<<s<<endl;
	strcpy(s,str[2]); //也可写成strcpy(s,*(str+2));  
	cout<<s<<endl;
	int array[10];  
	int (*ptr)[10];  //ptr指针类型int*[10],指向数据类型int[10]
	ptr=&array;
	sizeof(int(*)[10])==4 或者 sizeof(ptr)==4 说明指针本身占4byte
	因为 sizeof(int[10])==40
	所以,ptr+1就是ptr+40
	struct MyStruct  
	{  
		int a;  
		int b;  
		int c;  
	};  
	struct MyStruct ss={20,30,40};  //声明了结构对象ss,并把ss 的成员初始化为20,30 和40。  
	struct MyStruct *ptr=&ss;  //声明了一个指向结构对象ss 的指针。它的类型是  MyStruct *,它指向的类型是MyStruct。  
	int *pstr=(int*)&ss;  //声明了一个指向结构对象ss 的指针。但是pstr和它被指向的类型ptr 是不同的。  
	访问方法:
	ptr->a; //指向运算符,或者可以这们(*ptr).a,建议使用前者
	ptr->b;
	ptr->c;
	错误访问方法:
	*pstr; //访问了ss 的成员a。
	*(pstr+1); //访问了ss 的成员b。
	*(pstr+2) //访问了ss 的成员c。
	原因:

	int array[3]={35,56,37};  
	int *pa=array;  //通过指针pa 访问数组array 的三个单元的方法是:  
	*pa; //访问了第0 号单元  
	*(pa+1); //访问了第1 号单元  
	*(pa+2); //访问了第2 号单元  
	从格式上看倒是与通过指针访问结构成员的不正规方法的格式一样。
所有的C/C++编译器在排列数组的单元时,总是把各个数组单元存放在连续的存储区里,
单元和单元之间没有空隙。但在存放结构对象的各个成员时,在某种编译环境下,
可能会需要字对齐或双字对齐或者是别的什么对齐,需要在相邻两个成员之间加若干个"填充字节",
这就导致各个成员之间可能会有若干个字节的空隙。
所以即使*pstr 访问到了结构对象ss 的第一个成员变量a,也不能保证*(pstr+1)就一定能访问到结构成员b。
因为成员a 和成员b 之间可能会有若干填充字节,说不定*(pstr+1)就正好访问到了这些填充字节呢。
这也证明了指针的灵活性。要是你的目的就是想看看各个结构成员之间到底有没有填充字节,
int fun(char *s,int len)  
{  
	int num=0;  
	for(int i=0;i<len;i++)  
	{  
		num+=*s;s++;  
	}  
	return num;  
}  
int _tmain(int argc, _TCHAR* argv[])
{
	int a;  
	char str[]="abcdefghijklmn";  
	//char *b=str;
	a=fun(str,sizeof(str));  //大小是15,末尾有个0
	return 0;
}
void fun(char*s)  
{  
	char c;  
	c=*(s+3);*(s+3)=*(s+0);*(s+0)=c;  
	c=*(s+2);*(s+2)=*(s+1);*(s+1)=c;  
}  
int _tmain(int argc, _TCHAR* argv[])
{
	int a=125;
	int *b=&a;
	fun((char*)&a); //指针类型强制转换
	//实参&a 的结果是一个指针,它的类型是int *,它指向的类型是int。形参这个指针的类型是char *,它指向的类型是char。
	//这样,在实参和形参的结合过程中,我们必须进行一次从int *类型到char *类型的转换。
	cout<<a<<endl;//为什么是32bit的地址?
	fun((char*)b);
	cout<<*b<<endl;//125
	cout<<a<<endl;//125
}

 

	//给指针赋地址值
	unsigned int a;  
	char *ptr; //TYPE 是int,char 或结构类型等等类型。  
	a=20000; //N 必须代表一个合法的地址;  
	ptr=(char*)a; 
	cout<<ptr<<endl;

指针安全;


char s='a';  
int *ptr;  
ptr=(int *)&s;  
*ptr=1298;  
指针ptr 是一个int *类型的指针,它指向的类型是int。它指向的地址就是s 的首地址。在32 位程序中,s 占一个字节,int 类型占四个字节。最后一条语句不但改变了s 所占的一个字节,还把和s 相临的高地址方向的三个字节也改变了。这三个字节是干什么的?只有编译程序知道,而写程序的人是不太可能知道的。也许这三个字节里存储了非常重要的数据,也许这三个字节里正好是程序的一条代码,而由于你对指针的马虎应用,这三个字节的值被改变了!这会造成崩溃性的错误。
让我们再来看一例:
例十九:
[cpp] view plain copy
char a;  
int *ptr=&a;  
ptr++;  
*ptr=115;  
该例子完全可以通过编译,并能执行。但是看到没有?第3 句对指针ptr 进行自加1 运算后,ptr 指向了和整形变量a 相邻的高地址方向的一块存储区。这块存储区里是什么?我们不知道。有可能它是一个非常重要的数据,甚至可能是一条代码。
而第4 句竟然往这片存储区里写入一个数据!这是严重的错误。所以在使用指针时,程序员心里必须非常清楚:我的指针究竟指向了哪里。在用指针访问数组的时候,也要注意不要超出数组的低端和高端界限,否则也会造成类似的错误。
在指针的强制类型转换:ptr1=(TYPE *)ptr2 中,如果sizeof(ptr2的类型)大于sizeof(ptr1 的类型),那么在使用指针ptr1 来访问ptr2所指向的存储区时是安全的。如果sizeof(ptr2 的类型) 小于sizeof(ptr1 的类型),那么在使用指针ptr1 来访问ptr2 所指向的存储区时是不安全的。至于为什么,读者结合例十八来想一想,应该会明白的。
 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值