关于指针

#关于指针关于指针


###首先,我们下来了解一下地址这个概念
####地址:C程序中的变量在内存中占有一个可表示的存储区,每一个存储区是有若干个字节组成,
####每一个字节都有自己的地址,而一个存储区的地址就是该存储区中第一个字节的地址
C这门语言允许在程序中使用变量的地址
( 通过地址运算符&可得到)
例如:
int x;则x的地址就是&x
*:解引用操作符
&:取地址操作


###之后,我们要知道指针是什么.
指针:一个变量的指针就是该变量的地址(指针就是地址)
指针变量:存放变量地址的变量,它用来指向另一个变量
%p可输出指针的值
就例如:

int a,*p1;
//注意: 指针变量是p1 , 不是*p1 (在变量定义时, * 号表示该变量是指针变量 ) 
a=233;
p1=&a;//这时p1就指向了a的地址(也可以理解为p1就是a的地址)
pritnf("%d\n",*p1);//*p1就是p1指向的地址上的值,输出p1指向的地址上的值,即a的值,即233
printf("%p\n",p1);//输出p1的值,即a的地址

###&*p -> &(p) -> &a
###
&a -> *(&a) -> p -> a
###注意:1、p与
p不同, p是指针变量, p的值是p所指向的变量的地址 *p 是p 所指向的变量 , *p的值是p所指向的变量的值
###2、引用指针变量时的 * 与 定义指针变量时的 * 定义变量时的 * 只是表示其后的变量是指针变量 (引用自指针某不知名指针ppt)


###下面我们来做一道例题:
(NOIP2015提高组阅读程序写结果第2题)

#include<iostream>
using namespace std;
void fun(char *a,char *b){
	a=b;
	(*a)++;
}
int main(){
	char c1,c2,*p1,*p2;
	c1='A';
	c2='a';
	p1=&c1;
	p2=&c2;
	fun(p1,p2);
	cout<<c1<<c2<<endl;
	return 0;
}
输出______

###解析:
这里定义的指针变量指向char类型(虽然不是指向int类型,但本质上还是一样的).
p1指向c1的地址;p2指向c2的地址;
那么我们不妨设c1的地址为1000,c2的地址为1001
则p1就是1000,p2就是1001
通过fun函数将两个两个指针变量p1,p2传入;
则fun中的a就指向了p1指向的地址(即c1的地址即1000),b就指向了c2的地址(即1001).
这时进行赋值语句a=b.那么a的值就变成了1000.
之后(*a)++,将a指向的地址上的值++,即将1001上的‘a’++,即将a变成b
调用fun函数后,1000上的值(即c1的值)还是’A’,而1001上的值(即c2的值)变成了‘b’.
(你可能会问p1与p2在调用fun函数前后是否改变了.实事证明它们并没有改变,因为函数中只是将形参a的值变成了b,而实参p1并没有改变(这样讲可以懂吗?ლ(╹◡╹ლ)),就是说只有函数中的a在函数中发生了改变,而外界并没有受到影响)

故输出为 Ab

###我们再来看一道例题:
(NOIP2014提高组单项选择题第11题)
有以下结构体说明和变量定义,如图所示,指针p,q,r分别指向一个链表中的三个续结点。现要将q和r所指结点的先后位置交换,同时要保持链表的连续,以下程序段中错误的是( ).
A. q->next = r->next; p-> next = r; r->next = q;
B. p->next = r; q->next = r->next; r->next = q;
C. q->next = r->next; r->next = q; p->next = r;
D. r->next = q; q->next = r->next; p->next = r;

我也不想多说了
注意几点:
在D中的第二条语句中q->next=r->next中的r->next已经发生了变化,已经变成了q,所以执行该语句后,
q->next=q而不是一开始时r-next

故答案为D


##**总结一下吧:**其实多模拟以下指针的过程,或是做做实验,敲敲代码,把你不懂的交给程序,在从程序输出的结果出发,思考为什么会这样.这样就能慢慢地理解了

<think>嗯,用户之前已经询问过关于指针的基本概念,现在又进一步问“关于指针的知识点”。我需要判断他们到底需要哪些更深层次的信息。可能他们已经了解基础,现在想系统性地学习更多相关内容。 首先,回顾之前的对话,用户已经知道指针是存储内存地址的变量,以及其特点,比如直接访问内存、高效性和灵活性。现在可能需要更详细的知识点,比如指针的操作、类型、常见错误,以及在不同语言中的应用。 接下来,用户可能对指针的使用场景感兴趣,比如动态内存分配、数组和指针的关系、函数指针等。另外,他们可能想了解指针在高级语言中的替代方案,比如C#中的引用类型或托管指针,以及智能指针的概念。 需要确保覆盖指针的基础知识点,如声明、初始化、解引用、运算,然后深入指针与数组、函数、动态内存的关系。同时,可能涉及常见错误,如空指针、野指针、内存泄漏,以及如何避免这些问题。 还要考虑用户可能的实际应用场景,比如在数据结构(链表、树)中的使用,或者多级指针的应用。此外,对比不同编程语言中的指针实现,可以满足用户扩展知识的需求。 最后,检查是否需要补充指针的高级主题,如函数指针的应用场景,多级指针的使用,以及现代C++中的智能指针机制。这些内容能帮助用户全面理解指针的各个方面,避免常见错误,并有效利用指针进行高效编程。</think>好的!我将分步骤介绍指针的核心知识点,帮助你系统理解这一概念。 --- ### 一、指针基础 1. **定义** 指针**存储变量内存地址**的特殊变量。 例如: ```c int a = 10; // 定义整型变量a int *p = &a; // p指向a的地址(&a表示取a的地址) ``` 2. **声明与初始化** - 语法:`数据类型 *指针变量名;` ```c int *p; // 声明一个整型指针 char *c_ptr; // 声明一个字符指针 ``` - **必须初始化**:未初始化的指针可能指向非法内存(野指针)。 3. **解引用(Dereference)** 通过`*`访问指针指向地址的数据: ```c printf("%d", *p); // 输出a的值(10) *p = 20; // 修改a的值为20 ``` --- ### 二、指针与内存 1. **内存地址操作** - 指针支持算术运算(仅限加减): ```c int arr[3] = {1, 2, 3}; int *ptr = arr; // ptr指向数组首地址 ptr++; // 指向下一个元素(地址+sizeof(int)) ``` 2. **动态内存分配** - `malloc`/`free`:C语言中动态分配堆内存 ```c int *ptr = (int*)malloc(5 * sizeof(int)); // 分配5个int空间 free(ptr); // 释放内存 ``` - `new`/`delete`:C++中的动态内存管理 ```cpp int *ptr = new int[5]; delete[] ptr; ``` --- ### 三、指针类型与复杂用法 1. **指针类型** - 空指针(`NULL`/`nullptr`):表示指针未指向任何地址 ```c int *p = NULL; // C语言 int *p = nullptr; // C++11后推荐 ``` - 通用指针(`void*`):可指向任意类型,但需强制类型转换后才能使用 ```c void *vp = &a; int *ip = (int*)vp; ``` 2. **指针与数组** 数组名本质是指向首元素的指针: ```c int arr[3] = {1, 2, 3}; int *p = arr; // p指向arr[0] printf("%d", p[1]); // 输出arr[1]的值(2) ``` 3. **多级指针** 指向指针指针: ```c int a = 10; int *p = &a; int **pp = &p; // pp指向指针p的地址 printf("%d", **pp); // 输出10 ``` 4. **函数指针** 指向函数的指针,用于回调机制: ```c int add(int a, int b) { return a + b; } int (*func_ptr)(int, int) = add; // 定义函数指针 printf("%d", func_ptr(2, 3)); // 输出5 ``` --- ### 四、常见错误与规避 1. **指针(Dangling Pointer)** - 原因:指针指向已释放的内存 - 规避:释放内存后置指针为`NULL` ```c free(ptr); ptr = NULL; // 防止后续误用 ``` 2. **内存泄漏(Memory Leak)** - 原因:动态分配的内存未释放 - 规避:确保每个`malloc`对应一个`free`,或使用智能指针(C++)。 3. **指针解引用** - 原因:对未初始化的指针(`NULL`)进行解引用 - 规避:使用前检查指针有效性 ```c if (ptr != NULL) { *ptr = 10; } ``` --- ### 五、指针在不同语言中的替代方案 1. **C#** - 使用`引用类型`(类、数组)隐式管理指针 - 显式指针需在`unsafe`代码块中声明 ```csharp unsafe { int a = 10; int* p = &a; } ``` 2. **Java/Python** - 无显式指针,通过对象引用间接管理内存(JVM/Python解释器自动回收垃圾)。 3. **现代C++** - 智能指针(`unique_ptr`, `shared_ptr`)自动管理内存生命周期。 --- ### 六、应用场景 1. **数据结构**:链表、树、图的实现 2. **函数参数传递**:避免大对象复制(如传递结构体指针) 3. **硬件操作**:直接读写特定内存地址(嵌入式开发) --- 如果对某个知识点有疑问,可以具体提问!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值