镇楼图
Pixiv:WANKE
这一次来讲一下指针,指针的内容特别多而且较难理解,希望大家别被劝退。
============
内存是如何存放变 量的?
一个变量是如何通过变量名来索引内存中存储的值呢?
内存的最小索引单元为1个字节,内存的索为字节。
在我们看来变量可能是这么取值:
【变量名】→【值】
但实际上是:
【变量名】→【内存地址】→【值】
编译器只知道【变量名】对应的是【内存地址】,通过对【内存地址】的索引来得到值
============
取址运算符、解引用运算符
*为解引用运算符
获取这个变量对应的内存地址
int *a = 0;
//含义:a的内存地址为0
&为取址运算符
获取这个变量的地址所对应的值
int *a=0;
int b = 3;
a = &b;//a的地址赋值为b的地址
printf("%d",*a);
//变量的值变了,变量的值会变
//变量的地址变量,变量的值也会变
现在你可以通过变换内存地址的方式来完成赋值啦~
============
定义指针变量
数据类型表明了定义的指针指向哪个数据类型;*表示取址也就是指针;后面为变量名
后面表明了指针初始的地址
什么类型的指针就只能存放什么类型的数据,但指针有跨类型的例外,下面会说明
int *a = 0;
野指针
int *a;
如果我写成这样,就代表没有初始化,没有初始化可能让内存指向一个会出现bug的内存地址,一定要避免这种写法。
NULL空指针
long *a = 0;
long *b =NULL;
printf("%p\n",a);
printf("%p",b);
空指针的定义能保证指针不会成为野指针,防止出现bug。
但空指针无法被赋予值,一定会出现bug,因为空指针代表没有内存,没有内存自然无法赋值
unsigned int *a = 0;
*a = 100;
printf("%d",*a);
//空指针无法赋值
注意NULL和NUL的区别!
void通用指针
void *a = 1;
int num = 1024;
int *pi = #
char *ps = "LIKE";
void *pv;
pv = pi;
printf("pi:%p, pv:%p\n",pi,pv);
pv = ps;
printf("ps:%p, pv:%p\n",ps,pv);
//pv既能到int上也能到char上
void指针的强大之处在于它可以指向任意类型你可以指向char、int、long、bool都可以!
但不可以引用,因为编译器并不知道类型,但有一种解决方法——类型强制转换
char *ps = "LIKE";
void *pv;
pv = ps;
printf("%s\n",(char*)pv);
int *a = 100;
pv = a;
printf("%s\n",*(int*)pv);
============
指针与数组
int a;
int* p=&a;
printf("请输入整数");
scanf("%d",&a);
printf("\n结果为%d",a);
printf("\n请重新输入整数");
scanf("%d",p);
printf("\n结果为%d",a);
printf("\n结果为%d",*p);
char str[120];
printf("请输入字符");
scanf("%s",str);
printf("\n结果为%s",str);
由上段代码可以得知,数组名就是首个元素的地址
str
&str[0]
这些形式都是等价的.
事实上 a[0] 、a[1]...a[i] 代表的都是值,a、(a+0)、(a+1)、(a+i) 代表的是地址;另外这里的 a 代表整个数组的首地址,相当于 a[0] 的地址,而这里 (a+1) 就代表的是 a[0+1] 的地址。
int a[10];
bool b[10];
char c[10];
double d[10];
printf("a[0]的地址是 %p",a);
printf("a数组地址是%p",&a);
现在可以使用指针的方法来检索数组
int a[100];
int* p = a;
for (int i = 0;i < 100;p++,i++){
*p = i;
printf("a[%d] = %d\n",i,a[i]);
}
//p++并不是简单地址的值+1,而是地址到下一个元素的地址
符号
具体含义以及区别
a
数组首元素地址(指向首个元素)
&a[0]
数组首元素地址(指向首个元素)
&a
数组地址(指向数组整体)
&a+1代表整个数组的长度+1也就是数组最后一个元素的位置
a+1只代表首元素到第二个元素,可以将上述代码再简化为以下代码
数组本身作为地址常量,无法进行运算;而指针可以进行运算
int a[100];
for (int i = 0;i < 100;i++){
a[i] = 2*i;
printf("a[%d] = %d\n",i,*(a+i));
}
char *p1[5]={"12","23","34","45","56"};
int i;
for (i = 0; i < 5; i++){
printf("%s\n", p1[i]);
}
//用指针定义的字符串数组略微特殊
============
指针数组与数组指针
int *p1[5];
//指针数组
int (*p2)[5];
//数组指针
指针数组
*p1[5]
首先[]的优先级比*要高,先定义了p1[5]这个数组,然后类型是指针类型,所以元素存储的是内存地址,就是一组存储指针的元素,简称指针数组。
char *p[3] = {
"我",
"真",
"帅"
};
for (int i = 0;i<3;i++){
printf("%s",p[1]i);
}
数组指针
int (*p)[5]
这一次凭着括号,先定义了指针,再由这个指针去指向一个数组(整体),这个就称为数组指针
int a[5] = {1, 2, 3, 4, 5};
int (*p)[5] = &a;
//注:数组指针需要指向整体,不能写成a而要写成&a。
int i;
for (i = 0; i < 5; i++){
printf("%d\n", *(*p + i));
//p指向了数组的地址,而*p指向了首元素地址,**p为首元素,如果你看到这里感到困惑的话下一章的二重指针将能解决你的疑问
}
return 0;
============
二重指针
假设存在一个数组array[50],现在我们知道array[0]代表首元素,array或者&array[0]代表首元素地址,而&array代表了整个数组的地址(虽然值与array一致)。
这直接构成了一个逻辑关系,而我们也可以利用指针来更加明确这个关系。
array[n]←*(array+n)第n个元素
array←首元素地址
&array←
int array[5] = {2,3,4,5,6};
int (*p)[5] = &array;
//现在p就是数组地址,*p就是首元素地址,**p则代表了首元素
for (int i = 0; i < 5; i++){
printf("%d\n", *(*p + i));
}
当为二维数组时关系变成为了这样,一维指针已经不够用了,需要用二维指针
array[m][n]←*(*(array+m)+n)第二维第m行第n列
array[m]←*(array+m)第一维第m行
array←首元素地址
int array[4][5] = {0};
int i,j,k = 0;
for(i = 0;i<4;i++){
for(j = 0;j<5;j++){
array[i][j] = k++;
}
}
printf("*(array+1):%p\n",*(array+1));
printf("array[1]:%p\n",array[1]);
printf("&array[1][0]:%p\n",&array[1][0]);
printf("**(array+1):%d\n",**(array+1));
int (*p)[4] = array;
printf("**(p+1):%d\n", **(p+1));
printf("**(array+1):%d\n",**(array+1));
printf("array[1][0]:%d\n",array[1][0]);
/*
如果这么定义
int *p = array;
那一定会出错的,为什么在一维数组里可以这么写到二维数组就出错了呢?
因为int *p为指向int的指针,+1只会前移int个单位,而int (*p)[4]却是数组指针,会前移一整行
这种对应关系比较号推理,同理我们也能知道一个(逻辑上)三维、四维的数组可以使用指针来索引
三维数组的索引
int array[2][2][2] = {1,2,3,4,5,6,7,8};
int (*p)[2][2] = array;
int i = 0,j = 0,k = 0;
for (;i<2;){
printf("%d\n",p[i][j][k]);
//也可以换成*((*(p+i)+j)+k)
k++;
if (k== 2){
k = 0;
j++;
}
if (j== 2){
j = 0;
i++;
}
}
五维数组的索引
//array是待处理的五维数组
#define SIZE 5
int array[2][2][2][2][2] = {0};
int (*p)[2][2][2][2] = array;
int num[5] = {0};
int x = 0;
while (num[0] != 2){
p[num[0]][num[1]][num[2]][num[3]][num[4]] = x;
x++;
num[4]++;
for (int index = 5;index != 0;index--){
if (num[index] == 2){
num[index] = 0;
num[index-1]++;
}
}
}
num[0] = 0;
//对五维数组进行赋值
while (num[0] != 2){
printf("%d\n",p[num[0]][num[1]][num[2]][num[3]][num[4]]);
num[4]++;
for (int index = 5;index != 0;index--){
if (num[index] == 2){
num[index] = 0;
num[index-1]++;
}
}
}
//获取五维数组的数据
由此我们可以知道:
n维数组需要使用数组(n-1维)指针
============
总结:無
标签:第十天,int,C语言,num,数组,printf,array,指针
来源: https://www.cnblogs.com/AlienfronNova/p/14413354.html