指针
本章重点
- 指针是什么
- 指针和指针类型
- 指针和数组名
- 指针运算
- 指针和数组
- 二级指针
- 指针数组
什么是指针?
指针是编程语言中的一个对象,利用地址,他的值直接指向存在电脑存储器中另一个地方的值。由于通过地址就能找到所需的变量单元,可以说,地址指向该变量单元,因此将地址形象化的称为指针。
#include<stdio.h>
int main()
{
int a = 10; //在内存中开辟一个空间
int* p = &a; //这里我们对变量a取出他的地址,可以使用&操作符
//将a的地址存在变量p中,p就是一个指针变量。
return 0;
}
总结:指针就是变量,用来存放地址的变量(存放在指针中的值都被当成地址来处理)
一个小的单元到底是多大 ----是一个字节(8个比特位)
总结:
- 指针是用来存放地址的,地址是唯一表示一块空间地址的
- 指针的大小在32位平台是4个字节,在64位平台是8个字节
指针和指针类型
指针的类型决定了指针的权限,当利用指针去访问他所指向的对象的时候,到底能访问几个字节。整形指针解引用可以访问4个字节,字符型指针解引用可以访问1个字节。
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* p = arr; //四个字节四个字节去改变
for (int i = 0; i < 10; i++)
{
*(p + i) = 0;
}
return 0;
}
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
char* p = arr; //一个字节一个字节去改变
for (int i = 0; i < 10; i++)
{
*(p + i) = 0;
}
return 0;
}
总结:指针的类型决定了指针向前或者向后走一步的距离有多大
#include<stdio.h>
int main()
{
int a = 10;
int* pa = &a;
char* pc = &a;
printf("%p\n", pa);
printf("%p\n", pc);
return 0;
}
总结:增型指针加1向后偏移四个字节,字符型指针加1向后偏移一个字节
指针和数组名
数组名表示的是首元素的地址
#include<stdio.h>
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}
指针运算
- 指针±整数
- 指针-指针
- 指针的关系运算
指针±整数
#include<stdio.h>
int main()
{
double d[10] = { 0 };
double* pd = d;
printf("%p\n", pd);
printf("%p\n", pd+4);
//加4实际上是加了32,因为4*8=32
return 0;
}
#include<stdio.h>
#define a 5
int main()
{
float values[a];
float* vp;
for (vp = &values[0]; vp < &values[a];)
{
*vp++ = 0;
}
return 0;
}
//功能是将前五个元素的值都变成0
指针-指针
两个指针需要指向同一块内存空间
指针-指针实际上是得到指针和指针之间的元素个数
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
printf("%d\n", &arr[9] - &arr[0]);
return 0;
}
//结果是9,因为他们之间有9个元素
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
printf("%d\n", &arr[0] - &arr[9]);
return 0;
}
//结果为-9,因为是小地址-大地址
//结果的绝对值为他们之间元素的个数
#include<stdio.h>
int my_strlen(char* str)
{
if (*str == '\0')
return 0;
else
return 1 + my_strlen(str + 1);
}
int main()
{
char arr[] = "Hello World";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
#include<stdio.h>
int my_strlen(char* str)
{
int count = 0;
while (*str != '\0')
{
count++;
str++;
}
return count;
}
int main()
{
char arr[] = "Hello World";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
//利用指针-指针的方法
//得出两个指针之间的元素个数
#include<stdio.h>
int my_strlen(char* str)
{
char* start = str;
while (*str != '\0')
{
str++;
}
return str - start;
}
int main()
{
char arr[] = "Hello World";
int len = my_strlen(arr);
printf("%d\n", len);
return 0;
}
标准规定:允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
指针和数组
数组名就是首元素的地址
#include<stdio.h>
int main()
{
int arr[10] = { 0 };
printf("%p\n", &arr[0]); //数组首元素的地址
printf("%p\n", arr); //数组首元素的地址
printf("%p\n", &arr); //数组的地址
return 0;
}
两个特殊情况,表示整个数组
//&arr //数组名表示的是整个数组,取出的是数组的地址
//sizeof(arr) //数组名表示的是整个数组,计算的是整个数组的大小
//除此之外,所有数组名都是首元素的地址
数组和指针并不相同
二级指针 --二级指针还是占有4个字节
#include<stdio.h>
int main()
{
int a = 10;
int* p = &a;
int** pp = &p;
int*** ppp = &pp;
return 0;
}
指针数组
//指针数组
//指针数组是数组
//指针数组里放的是指针
#include<stdio.h>
int main()
{
int arr[10]; //整形数组
char ch[5]; //字符数组
int* arr2[6];
char* arr[3];
return 0;
}
//指针数组的作用
//指针数组中可以放好多别人的地址
#include<stdio.h>
int main()
{
int a = 1;
int b = 2;
int c = 3;
int d = 4;
int e = 5;
int* arr[5] = { &a,&b,&c,&d,&e };
printf("%d", *arr[4]); //打印的结果为e的值,为5
return 0;
}
#include<stdio.h>
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 2,3,4,5,6 };
int arr3[5] = { 3,4,5,6,7 };
int* arr[3] = { arr1,arr2,arr3 }; //数组名表示首元素的地址
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
//printf("%d ",*(arr[i]+j);
}
printf("\n");
}
return 0;
}
#include<stdio.h>
int main()
{
char* arr1[5]; //sizeof(arr1) 大小为20
int* arr2[5]; //sizeof(arr2) 大小为20
}