- 计算机只认识二进制,
- 32位机器,有32根地址线,而一根地址线又用无线电信号01来表示,也就相当于开闭
- 所谓的编程(地址)体现在地址总线的排列组合上
- 2^32个地址*1字节 = 2^10*2^10*2^10 *2^2 = 4GB
补充:有了指针(地址)会大大的提高效率,不存在指针(地址)的话, 只能一个一个的遍历
如何理解指针和指针变量
- 指针就是地址,地址也是数据
- 指针变量本质是变量,里面保存的是地址(指针)值
- 指针变量:空间(左值)+内容(右值:地址)
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
int* p = NULL;
p = (int*)0x1234;
int* q = p;
return 0;
}
- 第一个p使用的是变量p的空间
- 第二个p使用的是变量p的内容,也就是0x1234,此时指针==指针变量!!
- 通过实验发现对控制针进行解引用,会发生访问冲突,
- 0x1234如果是赋给p指针变量的空间的话,是不会报错的,所以推断出0x1234是赋给p指针变量的内容,
结论:对指针变量进行解引用,使用的是指针变量的右值(内容)
补充: 对指针进行解引用,代表指针所指向的目标
变量的地址
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
int a = 10;
printf("%p", &a);
return 0;
}
- 感兴趣的可以试试,只要不是用很老的编译器,你会发现每次打印出来的地址都不一样
- 那个东西叫栈随机化技术,是为了提高安全性
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
int* p = NULL;
p = (int*)&p;
*p = 10;
p = 20;
return 0;
}
- 这是一段有趣的代码,这里的p是自己指向自己
- 我这里不好复现,感兴趣的话可以自己试试,
- 注意:要用老的编译器
补充:对指针加1,就是加上其指向类型的大小
数组的内存布局
- 局部变量都是在栈区上面的,而栈区的使用习惯是先使用高地址再使用低地址
- 而a先定义意味着,a先开辟空间,那么a就先入栈,所以a的地址最高
- 数组是线性且连续的,所以地址也是依次递增的
- 在开辟空间的角度,不应该把数组认为成一个个独立的元素,要整体开辟,整体释放
#define _CRT_SECURE_NO_WARNINGS 1
#include
void show(int pr[])
{
int i = 0;
for (i = 0;i < 10;i++){
printf("%d ", *(pr + i));
//printf("%d ",pr[i]);
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
show(arr);
return 0;
}
- 所有的数组,传参都会发生降维,都会降维成指向内部元素类型的指针!
- 如果不降维成指针,就会发生数组拷贝,函数的调用效率也会降低
补充:在C语言中,任何函数的调用,只要有形参实例化,就必然会形成临时拷贝!!!
指针和数组访问元素的相似性
#define _CRT_SECURE_NO_WARNINGS 1
#include
void show(int* pr)
{
int i = 0;
for (i = 0;i < 10;i++){
printf("%d ", *(pr + i));
//printf("%d ",pr[i]);
}
printf("\n");
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int i = 0;
show(arr);
for (i = 0;i < 10;i++) {
printf("%d ", arr[i]);
//printf("%d ", *(arr + i));
}
return 0;
}
- 首先数组和指针肯定是不一样的,只是他们都可以用*和[ ]进行访问,但是寻址方案是完全不一样的
- 如果数组和指针的访问元素的方式不一样,那么对于一个程序员来说,他就需要不断的在不同的代码片段处,进行习惯的切换
- 所以干脆,C将指针和数组的访问方式打通,让程序员在函数内,也好像使用数组那样进行元素访问,本质值减少了编程难度!
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
int a = 0;
float b = 0.0f;
int arr[10] = { 0 };
//int [10] arr = { 0 };
return 0;
}
- 在C语言中像int a = 0;float b = 0.0f,都是类型在左,变量名在右,
- 为什么不能这样定义呢,int [10] arr = { 0 };
#define _CRT_SECURE_NO_WARNINGS 1
#include
typedef int* p1_t[10];
typedef int(*p2_t)[5];
int main()
{
p1_t x;
p2_t y;
return 0;
}
数组里的元素是数组类型的一部分吗?
- 实验表明:数组里的元素是数组类型的一部分
#define _CRT_SECURE_NO_WARNINGS 1
#include
int main()
{
int a[4] = { 1,2,3,4 };
int* ptr1 = (int*)(&a + 1);
int* ptr2 = (int*)((int)a + 1);
printf("%x,%x\n", ptr1[-1], *ptr2);
return 0;
}
- 当前大多数机器都是采用小端存储,
- 存的时候使用小端存,那取的时候自然也要用小端取,
- 所有的数组都可以当成"一维数组",多维数组就相当于一维数组不停的套娃
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)