这里看到,地址相近,有利于提高运行效率
指针操作数组 一维数组: 数组名: 表示整个数组占用的空间的首地址 对于int array[4]来说 array是数组名 等效于 &array[0] 两者都是整个数组的首地址
#include <stdio.h> int main() { int array[4] = { 1,2,3,4 }; int* p = array; p = &array[0]; //与上一个语句等效 for (int i = 0; i < 4; i++) //一维指针打印一个数组 { //*(p+i) 等效p[i] 等效array[i] printf("%d\t", *(p + i)); //p+i是地址,*(p + i)是数字 //printf("%d\t", p[i]); 和上面等效 } } //不正常的情况的 //p[i] 等效*(p+i) p = &array[2]; //说明*p指向了array[2] printf("\n%d\n", p[1]); //p[1]此时等效于array[2+1],也等效于*(&array[2]+1) 见下图 printf("%d\n", *(&array[1] + 2));//该式操作比较麻烦,因此指针操作数组时,直接用上式的指针名替换数组的名的用法 //不用指针名替换数组的名时的情况,输入的时候用用指针 for (int i = 0; i < 3; i++) { scanf_s("%d", array + i); //array是一个地址,array + i也是一个地址,不用取地址符 } int array2D[2][2] = { 1,2,3,4 }; p = &array2D[0][0]; for (int i = 0; i < 4; i++) //降维打击 { printf("%d\t", p[i]); } printf("\n");万能指针: void * 类型的指针 1.万能指针可以操作任何类型指针 2.使用前必须强制类型 3.当做函数返回值,当做函数参数时使用,可以忽略数据类型进行操作
void* mytime() //函数是void*类型时,需要强制类型转换 { return NULL; } int main() { int num = 0; void* pNum = # //使用的时候必须强制类型转换 printf("%d\n", *(int*)pNum); //printf("%d\n", *pNum); 此时有语法错误 char cNum = 'A'; pNum = &cNum; int* p = (void*)mytime(); //使用时需要强制类型转换 printf("%c\n", *(char*)pNum); return 0; }堆区 :动态内存申请的内存 手动申请,手动释放 栈区 : 局部变量,函数 自动释放,当使用完后系统会回收资源 栈结构: FILO,后进先出 堆: 随机访问 静态区: 全局变量+静态变量 常量区: 不能改变 代码区: 写的代码编译后存储的位置
#include <stdio.h> //不能返回局部变量地址 //warning C4172: 返回局部变量或临时变量的地址: num int* ReturnPoint() { int num = 1001; return # } int* returnNum(int a) //形参存在局部变量里 { return &a; } int* returnMyNum(int *a) //不算 { return a; //返回指针变量的值 } int main() { //写入访问权限冲突 char* p = "ILoveyou"; //不会修改,只做打印显示需求,把字符串从常量区的首地址赋值给p //常量区,不能修改 //*p = "I"; 错误,写入访问权限冲突 //*p = 'I'; 错误 //printf("%d\n", *p); char str[] = "ILoveyou"; //数组去存,指针操作,可以修改 p = &str[0]; //一个是用p指向常量区,一个是用p指向数组地址 //*p相当于*(p+0) p[0] str[0] *p = 'C'; printf("%s", p); int* pReturn = ReturnPoint(); printf("\n第一次:%d\n", *pReturn); printf("第二次:%d\n", *pReturn); return 0; }