问题:你的X朋友怎么找到你呢?1
代入计算机内存
因此:楼房的门牌号就好比内存变量的标识——地址,地址(门牌号)可极大地提高寻找变量(屋子)的效率!
补充
疑问:地址都要存储呢?2
简单的理解:CPU内做了特殊的处理,当内存的指定位置的变量向CPU传递信息(电信号)时,CPU会将此电信号转换为数字信号(此变量的地址),通过地址总线再返还给内存。
值探究的维度
常量与变量
代入:指针是一个常量,指针变量是变量,里面存放的值是指针。
例:
#include
int main()
{
int a = 10;
int* p = &a;
*p = 9;
p = NULL;
printf("%d\n", a);
*&a = 12;
//相当于a = 12;
int b = *p;
//等于int b = a;
printf("%d\n", a);
return 0;
}
来看一段有意思的代码:
int main()
{
int* p = NULL;
p = (int*)&p;
*p = (int)p;
printf("%p %p", (int*)*p, p);
return 0;
}
再看一段雷同的代码:
#include
int main()
{
float* p = NULL;
p = (float*)&p;
*p = (float)p;
printf("%p %p", (float*)*p, p);
return 0;
}
结论:报错!
这就好比:本就跟你是两个世界的人,明知不可能还要骗自己。但结果不会欺骗自己。
指针本质上存的是一个32位数(整形家族),无法转换成浮点数(浮点家族),两个世界的,不可能进行转换!
阅读代码:
这段代码是不能正常执行的!我们只需认识每句代码的意思即可!
每句代码思考:
int main()
{
int a = 10;
int* p = &a;
int** pp = &p;
p = 100; //1
*p = 100; //2
pp = 100; //3
*pp = 100;//4
**pp = 100;//5
return 0;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10};
return 0;
}
int *p[10]
int(*p)[10]
说明:平常我们都只调用函数,好像没接触过函数指针。
下面我们从函数说起!
#include
void fun()
{
printf("hello\n");
}
int main()
{
fun();//这是一个简单的调用
//这一个语句可以拆分成两部分fun和()
//fun是函数,()是函数调用操作符
//那fun呢?
fun;
//&fun呢?
&fun;
return 0;
}
我们想描述一个指针类型,首先得描述其独特之处
函数的独特之处:
//void/*返回类型*/ ()/*参数*/ *p = &fun;//这样写看起来是正确的,但跟语法还差了一点
//void fun ();//如果把fun看成变量的话,那指针变量的位置也应该出现在fun处
//因此:void *p()= &fun;离目标还差一点——优先级:()的优先级高于*,要说明p为指针得
//先把p与*号集合起来
//所以正确且符合语法的规范
void (*p)()=&fun;
实际上:
fun等同于&fun
因此:这样写也对
void (*p)()=fun;
函数指针的类型呢?
将变量名去掉就是指针类型。
so此函数指针的类型为:
void (*)()
(*(void(*)())0))() ;//如何理解此代码
(void(*)())0
(void(*)())0
看做一个函数指针p*(*(void(*)())0))()
(* p )()
,很显然这是函数调用。void(*signal(int,void(*)(int)))(int);//如何理解这样一段代码?
要理解这样一段代码我们先要理解函数指针作为返回值的函数声明该如何表示?
假设
void(*)(int)fun();
//甚至会写出函数指针当做函数声明
void(*fun)();
然后我们还要理解函数指针作为参数的函数声明该如何表示?
void fun2(int,void(*)(int));
void(*fun2(int,void(*)(int)))(int);
void (*((*p)[3]))() = { NULL };
例
不能访问:
#include
int main()
{
int* p = (int*)1;
printf("%d", *p);
return 0;
}
不可被修改:
#include
int main()
{
int* p = (int*)1;
*p = 1;
return 0;
}
#include
int main()
{
int arr[10] = { 0 };
int* p = arr;
int* p1 = &arr[9];
printf("%d\n", p1 - p);
return 0;
}
void test(int arr[])//ok
{}
void test(int arr[10])//ok
{}
void test(int arr[9])//ok
{}
void test(int* arr)//ok
{}
void test2(int* arr[20])//ok
{}
void test2(int* arr[0])//ok
{}
void test2(int** arr)//ok
{}
int main()
{
int arr[10] = { 0 };
test(arr);
int* arr2[20] = { 0 };
test2(arr2);
return 0;
}
#include
int main()
{
char a[3][4] = { 0 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
printf("a[%d][%d] : %p\n", i, j, &a[i][j]);
}
}
return 0;
}
三维数组证明:
#include
int main()
{
char a[3][4][5] = { 0 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 4; j++)
{
for (int k = 0; k < 5; k++)
{
printf("a[%d][%d][%d] : %p\n", i, j,k, &a[i][j][k]);
}
}
}
return 0;
}
通过一间间房间的挨个查找。 ↩︎
不要,内存会根据变量位置,自动生成变量的地址,再使用。 ↩︎