为什么要用指针?
run一下下面这段代码感受一下
注意第二个打出来的数字!!!
#include <iostream>
using namespace std;
//值传递
void change1(int n){
printf("The address in change1 is:%p\n", &n); //显示的是拷贝的地址而不是源地址
n++;
printf("The number after change1 is:%d\n", n);
}
//引用传递
void change2(int & n){
printf("The address in change2 is:%p\n", &n);
n++;
printf("The number after change2 is:%d\n", n);
}
//指针传递
void change3(int *n){
printf("The address in change3 is:%p\n", n);
*n=*n+1;
printf("The number after change3 is:%d\n", *n);
}
int main(){
int n=10;
printf("The address of the param is:%p\n", &n);//10
change1(n);
printf("The number after change1 is:%d\n", n);//10!!!!!!!!
change2(n);
printf("The number after change2 is:%d\n", n);//11
change3(&n);
printf("The number after change2 is:%d\n", n);//12
return 0;
}
因为传值调用改变没法真正改变值!对于这种传参,可以理解为裹着它的那个盒子一起传过去,改变才会生效,而地址/指针就是那个盒子就是上面change3方法
还要一种解决方法是引用传递,是c++的特性,在c文件里不能写,但是c++基本向下兼容c,c的语法c++是懂的!所以用dev新建文件后缀都是.cpp(为啥我会知道呢,因为我为了减少写数据结构的痛苦在vscode上写,一开始后缀都写.c疯狂报错,找了好久问题才发现这个原因......前面这些话就是说:不管写c还是c++,后缀用c++基本不会错!
对于这三种方法有个地方比较绕:
//值传递-声明和定义时
void change1(int n)
//引用传递-声明和定义时
void change2(int & n)
//指针传递-声明和定义时
void change3(int *n)
//调用时
int n=10;
change1(n);
change2(n);
change3(&n);
定义结点发生了什么
对于结构体
typedef struct Node{
int data;
struct Node *link;
} Node, *LinkNode;
先看看他们时什么意思
/Node可以代替struct Node;
LinkList是指向Node类型的指针
//strct Node a==Node a;LinkList b==Node *b==struct Node *b
初始化空间又是什么?
可以这样理解:
指向结构体的指针LinkNode是一个纸盒子
LinkNode p;声明了一个叠起来的、压扁的纸盒子,这时候不能使用p->data
P=(Node *)malloc(sizeof(Node))给纸盒一个空间,就是让纸盒撑起来了,能放东西了,可以使用p->data了
p->data=1;就是在纸盒中放入1
ps
使用结点:
Node *p;
p->data=1;
p->link=NULL;//一开始就置空
给纸盒空间的方法有这样几个
1.
Node n;//先有一块空间,
&n->data//包着这块空间的纸盒自然是可以放东西的,可以直接使用
2.
Node n;//先有一块空间
LinkNode l;l=&n; //l等同于包着这块空间的纸盒
3
Malloc啦
LinkNode l;
l=(Node *)malloc(sizeof(Node));
定义变量好还是指针好?
所以呢初始化链表/队列/栈的时候
不要直接声明一个指针,而是声明一个变量,传参的时候再去取地址
//自定义函数
void InitStack(Stack *s){
s->top = NULL;
}
//主函数
int main(){
Stack S;
InitStack(&S);
}
//自定义栈
typedef struct linkStack{
StackNode *top;
}Stack,* LinkStack;