1. 1 + 1 = 2?
给一个指针 加 1,表示要让指针指向下一个变量
如果指针不是指向一片连续分配的空间,这种运算没有意义
#include<stdio.h>
int main(void)
{
// char 数组
char ac[] = {0, 1, 2, 3, 4, 5, 6};
char *p = ac;
printf("p=%p\n", p); // p=000000000022FE40
printf("P+1=%p\n", p + 1); // P+1=000000000022FE41
printf("sizeof(char)=%d\n", sizeof(char)); // sizeof(char)=1
// int 数组
int ai[] = {1, 2, 3, 4, 5};
int *q = ai;
printf("q=%p\n", q); // q=000000000022FE10
printf("q+1=%p\n", q + 1); // q+1=000000000022FE14
printf("sizeof(int)=%d\n", sizeof(int)); // sizeof(int)=4
printf("*(q+1)=%d\n", *(q + 1)); // *(q+1)=2 即 *(q + 1) = ai[1]
return 0;
}
2. 指针的算术运算
可以给指针 加 减一个整数、递增(++)、递减(–)、两个指针相减
#include<stdio.h>
int main(void)
{
char ac[] = {0, 1, 2, 3, 4, 5, 6, 7};
char *p = &ac[0];
char *p1 = &ac[5];
printf("p =%p\n", p); // p =000000000022FE20
printf("p+1=%p\n", p + 1); // p+1=000000000022FE21
printf("p1-p=%d\n", p1-p); // p1-p=5
int ai[] = {1, 2, 3, 4, 5, 6, 7, 8};
int *q = ai;
int *q6 = &ai[6];
printf("q =%p\n", q); // q =000000000022FE20
printf("q6=%p\n", q6); // q6=000000000022FE38,十六进制
printf("q6-q=%d\n", q6-q); // q6-q=6
return 0;
}
3. *p++
- 先计算 ++,在计算 *
- 取出 p 所指的那个数据,再将p移到下一个位置
- 用于数组类的连续空间操作
- 在某些CPU上,可以直接被翻译成一条汇编指令
#include<stdio.h>
int main(void)
{
char ac[] = {0, 1, 2, 3, 4, 5, 6, -1};
char *p = &ac[0];
int i;
for(i = 0; i < sizeof(ac)/sizeof(ac[0]); i++){
printf("%d\n", ac[i]);
}
printf("-------------\n");
// 假设 -1 表示结束
while( *p != -1){
printf("%d\n", *p++);
}
return 0;
}
4. 指针比较
<, <=, == , >, >=, != 都可以对指针做
可以比较在内存中的地址
数组中的单元的地址肯定是 现行递增的
5. 0地址
- 0地址通常是不能随便碰的地址,所以你的指针不应该具有 0值
- 可以用0地址来表示特殊的事:
- 返回的指针是无效的
- 指针没有被真正初始化
- NULL是一个预定义的符号,表示0地址
- 有的编译器不愿意用0来表示0地址
6.指针的类型
- 无论指向什么类型,所有的指针的大小都是一样的,因为都是地址
- 指向不同类型的指针 不能直接互相赋值,这是为了避免用错指针
#include<stdio.h>
int main(void)
{
char ac[] = {0, 1, 2, 3, 4, 5, 6, -1};
char *p = &ac[0];
int ai[] = {0, 1, 2, 3, 4, 5, 6};
int *q = ai;
// q = p; // [Error] cannot convert 'char*' to 'int*' in assignment
return 0;
}
7. 指针的类型转换
- void* 表示不知道指向什么东西的指针
- 指针也可以转换类型
#include<stdio.h>
int main(void)
{
int i = 5;
int *p = &i;
// 没有改变p所指的变量的类型,只是换了个看待p所指变量的方式
// 不再当它是 int,认为是 void
void* q = (void*)p;
return 0;
}
8.指针的用途
- 需要传入比较大的数据时 用作参数
- 传入数组后,对数组做操作
- 函数返回不止一个结果,需要用函数来修改不止一个变量
- 动态申请的内存
9. 动态分配内存
9.1 malloc
#include<stdlib.h>
void* malloc(size_t size);
- malloc申请的空间的大小是以字节为单位的
- 返回的类型是 void*,需要类型转换为 自己需要的类型,比如 (int*)malloc(n * sizeof(int))
- 如果什么失败则返回0,或者叫做NULL
输入数据时,先告诉你个数n,再输入n个数字,要记录每个数据
C99可以用变量n做数组定义的大小,C99之前呢?用 int a = (int )malloc(n * sizeof(int));
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
int number;
int* a;
printf("输入数量:");
scanf("%d", &number);
a = (int*)malloc(number * sizeof(int));
int i;
for(i = 0; i < number; i++){
scanf("%d", &a[i]);
}
for(i = number - 1; i >= 0; i--){
printf("%d ", a[i]);
}
free(a);
return 0;
}
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
//你的系统能给你多大空间?
void *p;
int cnt = 0;
while((p=malloc(100 * 1024 * 1024))) {
cnt++;
}
printf("分配了%d00MB的空间\n", cnt); // 分配了10300MB的空间
return 0;
}
9.2 free
- 把申请得来的空间还给系统
- 只能还申请来的空间的首地址
常见问题
- 申请了没free,长时间运行内存逐渐下降
- 新手:忘了
- 老手:找不到合适的free的时机
- free过了再free
- 地址变了,直接去free