参考:【【强烈推荐】4小时彻底掌握C指针 - 顶尖程序员图文讲解 - UP主翻译校对 (已完结)】 https://www.bilibili.com/video/BV1bo4y1Z7xf/?share_source=copy_web&vd_source=b4a9adec1e790e088162134b69d77d6c
p存地址 p=&a
*p引用地址所在的变量的值 *p=a
p的单位是地址(4/8...)
不是bite
指针的类型,算数运算
p+1=下一个bite的位置
*(p+1)=下一个地址的值
“下一个”根据p的类型而决定
指向指针的指针
函数传值vs传引用
传值Increment copy a的内存
传引用
数组和指针
数组的特点:
对于一般变量,你不知道它的隔壁是什么数,有没有,所以p=p+1之后,*p是什么,我不知道:
但数组是连续的数,所以我能够知道它的隔壁是什么:
A=&A[0],是首元素的地址:
(b无异于指针)
数组作为函数参数
int A[];
sizeof(A)//整个数组的总bite
sizeof(A[0])//一个元素的bite
在为数组A分配内存之后,int total执行完毕,结束,进而执行SumOfElements函数
为SumOfElements准备新内存并且copy数组A的内存
是引用A的位置(首个A[0]的位置),所以intA[]=
回顾传引用:
数组作为参数,就是传引用,只不过指针与数组同名
指针和字符数组
#include <stdio.h>
#include <string.h>
void print(char* c)
{
int i = 0;
while ( c[i] != '\0')//(*c!=0) 指针
{
printf("%c",c[i]);
i++;//c++
}
printf("\n");
}
int main() {
char c[5] = "abc";
print(c);
return 0;
};
经典变量指针,经典改字符串
#include<stdio.h>
#include<string.h>
void print( char* c) {
while (*c != '\0') {
printf("%c", *c);
c++;
}
printf("\n");
}
int main() {
char c[20] = "Hello";
/*char * c = "hello";*///因为*c是一个常量,就像是20,不可以单独修改2.
c[0] = 'G';
print(c);
}
经典变量指针,新函数里改字符串
#include<stdio.h>
#include<string.h>
void print( const char* c) {
c[0] = 'G';
while (*c != '\0') {
printf("%c", *c);
c++;
}
printf("\n");
}
int main() {
char c[20] = "Hello";
/*char * c = "hello";*///因为*c是一个常量,就像是20,不可以单独修改2.
print(c);
}
常量指针 ,只读
#include<stdio.h>
#include<string.h>
void print( const char* c) {
c[0]=G;//报错
while (*c != '\0') {
printf("%c", *c);
c++;
}
printf("\n");
}
int main() {
char c[20] = "Hello";
print(c);
}
指针与二维数组
一维数组:地址->值
二维数组:地址->地址->值
指针定义:
int *p=B//错误
int *p[3]=B
*(B+1)+2=(地址)B[1]+2=&B[1][2]
*(*B+1)=3【*B是地址,是B[0][0]的地址,*B+1是B[0][1]的地址,*(*B+1)是B[0][1]的值】
指针与多维数组
一维数组中A是首元素A[0]的地址
此数组中C[0][0]是其首元素C[0][0][0]的地址
指针定义:
int p[2][2]=C;
数组函数传值:
A[2][3]->int A[ ][3]or int *A [3]
A[a][b][c]->int A[][b][c] pr int A*[b][c]
越大包容越多 单位越大
指针和动态内存-栈vs堆
函数返回指针
非常重要的2句话:当被调函数结束控制返回主调函数的时候,那块内存已经被释放了;
,
。
heap上分配内存需要我们自己释放;stack上分配内存自动释放;global全局变量上全局生命周期是整个程序
语法:int *p=x等价于int *p,p=x;