#include
int main()
{
int a = 10; //在内存中开辟一块空间
int *p = &a; //这里我们对变量a,取出它的地址,可以使用&操作符。
//将a的地址存放在p变量中,p就是一个指针变量。
return 0;
}
总结:
指针就是变量,用来存放地址的变量。(存放在指针中的值都被当成地址处理)。
经过仔细的计算和权衡我们发现一个字节给一个对应的地址是比较合适的。
前面有0x的数 —— 表示16进制 —— 2个位数的16进制数(FF) = 8个位数的2进制数(11111111)(举例:16进制 —— FF 和 2进制 —— 11111111 表示的数相等)
在32位平台下:有32个地址线,每个地址线能够给出0或1,则能够给出2的33次方 - 1个 编号地址2的33次方字节 = 4,294,967,296byte = 4,194,304kb = 4096mb = 4gb
所以在32位平台下(32个地址线):内存最大为4GB。
如果想要增大内存就要增加地址线,可以用64位的平台。
这里我们就明白:
总结:
这里我们在讨论一下:指针的类型
我们都知道,变量有不同的类型,整形,浮点型等。那指针有没有类型呢?
准确的说:有的。
指针为什么会有类型呢?
我们在前面讲过指针在32位平台下是4个字节,在64位平台下是8个字节。
既然指针的大小是相同的为什么我们不统一定一个类型为指针类型呢?
char* 类型的指针是为了存放 char 类型变量的地址。
short* 类型的指针是为了存放 short 类型变量的地址。
int* 类型的指针是为了存放 int 类型变量的地址。
下面我们讲指针类型的意义:
#include
int main()
{
int n = 0;
char* pa = &n;
int* pb = &n;
printf("%p\n", &n);
printf("char类型的地址:%p\n", pa);
printf("char类型+1的地址:%p\n", pa + 1);
printf("int类型的地址:%p\n", pb);
printf("int类型+1的地址:%p\n", pb + 1);
return 0;
}
总结:
指针的类型决定了指针向前或者向后走一步有多大(距离)。
#include
int main()
{
int n = 0x11223344;
char* pa = (char*)&n;
*pa = 0;
return 0;
}
#include
int main()
{
int n = 0x11223344;
int* pa = &n;
*pa = 0;
return 0;
}
总结:
指针的类型决定了,对指针解引用的时候有多大的权限(能操作几个字节)。
比如:
char* 的指针解引用就只能访问一个字节,
而 int* 的指针的解引用就能访问四个字节。
概念: 野指针就是指针指向的位置是不可知的(随机的、不正确的、没有明确限制的)
1.1 指针未初始化
#include
int main()
{
int* p;
*p = 10; //指针没有初始化 —— 指向的是随机值 —— 随机值是不在main函数的控制范围内 —— 野指针
return 0;
}
1.2 指针的越界访问
#include
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i <= 10; i++)
{
*p = i;
p++; //当指针指向的范围超出数组arr的范围时,p就是野指针 —— *p + 10 超过了数组的范围
}
return 0;
}
1.3 指针指向的空间释放
#include
int* test()
{
int a = 10;
int* p = &a;
return p;
}
int main()
{
int* p = test(); //这一步执行完 —— test所创建的空间已经被释放了
printf("hehe\n");
printf("%d", *p); //打印值为不确定的值
}
#include
int main()
{
int *p = NULL; //当不知道初始化的值时,可以用NULL空指针来赋值
int a = 10;
p = &a; //如果有初始化的值,尽量初始化
if(p != NULL)
{
*p = 20;
}
return 0;
}
int main()
{
int arr[5];
int* p;
for (p = &arr[0]; p < &arr[5]; *p++ = 0)
{
; //循环5次
}
return 0;
}
#include
int main()
{
int arr[10] = { 0 };
printf("%d\n", &arr[9] - &arr[0]); //打印值为 9 —— 不是36
return 0;
}
指针 - 指针算的是指针元素之间的个数,不是他们之间相差的字符个数
实现库函数 —— strlen
#include
#include
int my_strlen1(char* p) //一般方法 —— 实现库函数
{
int count = 0;
while (*p != '\0')
{
count++;
p++;
}
return count;
}
int my_strlen2(char* p) //利用指针 - 指针的方法 —— 实现库函数
{
char* s = p;
while (*p != '\0')
{
p++;
}
return p - s;
}
int main()
{
char arr[] = "abcdef";
printf("%d\n", strlen(arr)); //打印值为6
printf("%d\n", my_strlen1(arr)); //打印值为6
printf("%d\n", my_strlen2(arr)); //打印值为6
return 0;
}
for(p = &arr[5]; p > &arr[0];)
{
*--p = 0;
}
这个代码不会访问到 arr[ 0 ] 前面的地址
代码简化, 这将代码修改如下:
for(p = &arr[5]; p >= &arr[0]; p--)
{
*p = 0;
}
这个代码会访问到 arr[ 0 ] 前面的地址
第二种方法 —— 实际在绝大部分的编译器上是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,
但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
数组 —— 是一串连续的空间 —— 放相同类型的变量
数组大小 —— 和数组类型和元素个数有关
指针(变量) —— 是一个变量 —— 用来存放地址
指针大小 —— 和使用的平台有关 —— 在32位机器下为4个字节 —— 在64位平台下8个字节
#include
int main()
{
int arr[10] = {1,2,3,4,5,6,7,8,9,0};
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}
数组名表示首元素的地址 —— 但是有两种例外(表示整个数组) —— 其他的都表示首元素地址
第一种:&arr —— 表示整个数组
第二种:sizeof(arr) —— arr表示整个数组 —— 计算整个数组的大小
既然可以把数组名当成地址存放到一个指针中,我们使用指针来访问数组就成为可能。
#include
int main()
{
int i = 0;
int arr[] = {1,2,3,4,5,6,7,8,9,0};
int *p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr)/sizeof(arr[0]);
for(i=0; i<sz; i++)
{
printf("&arr[%d] = %p <====> p+%d = %p\n", i, &arr[i], i, p+i);
}
return 0;
}
从上面的结果就可以知道:arr[ i ] = *(arr + i )
那我们就可以直接通过指针来访问数组。
#include
int main()
{
int arr[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
int *p = arr; //指针存放数组首元素的地址
int sz = sizeof(arr) / sizeof(arr[0]);
int i = 0;
for (i = 0; i < sz; i++)
{
printf("%d ", *(p + i)); //*(p + i) = p[i]
}
return 0;
}
1. *ppa通过对ppa中的地址解引用 —— 找到pa —— *ppa = pa = &a
2. **ppa —— *(*ppa) = *pa = *(&a) = a = 10
int arr —— 整型数组
char ch —— 字符数组
int* parr —— 整型指针数组
char* pch —— 字符指针数组
#include
int main()
{
int a = 10;
int b = 20;
int c = 30;
int* arr[3] = { &a, &b, &c }; //int* arr[3]其中arr先和[ ]结合 —— 说明这是一个数组 ——
//*表示数组中存放的是指针 —— int表示指针所指向的数是int类型
//打印a, b, c的值
int i = 0;
for (i = 0; i < 3; i++)
{
printf("%d ", *(arr[i]));
}
return 0;
}