文章目录
前言
走进指针的世界,我们先来了解一些指针的概念
1.内存会划分为一个个独立的内存单元
2.每个内存单元都有一个独立的编号 - 编号也成为地址
3.地址在C语言中被称为指针
4.指针(地址)需要储存起来 - 存储到变量中,这个变量就被称为指针变量
5.指针是由类型的,指针的类型决定了+-指针的步长(这一点特别重要哦,后面做很多面试题都会讲到)
6.指针的运算
7.int a = 10; int *pa = &a;
8.指针(地址)的大小是固定的4/8个字节(32位平台。64位平台)
一、字符指针
#include <stdio.h>
int main()
{
char str1[] = "hello bit.";
char str2[] = "hello bit.";
const char* str3 = "hello bit.";
const char* str4 = "hello bit.";
if (str1 == str2)//数组名是首元素的地址,str1和str2是指向不同地址的数组的首元素地址,所以str!=str2
printf("str1 and str2 are same\n");
else
printf("str1 and str2 are not same\n");//not same
if (str3 == str4)//str3 和 str4是两个常量字符串的名字,因为常量字符串是不可以被改变的,
//所以常量字符串只会在内存中存一个,不管名字怎么变,都会指向内存中仅有的一个字符串。
printf("str3 and str4 are same\n");//same
else
printf("str3 and str4 are not same\n");
return 0;
}
二、数组指针
数组指针到底使数组还是指针,答案是指针
类比:
整型指针 - 指向整型变量的指针,存放的是整形变量的地址的指针变量
字符指针 - 指向字符变量的指针,存放的是字符变量的地址的指针变量
数组指针 - 指向数组的指针,存放的是数组的地址的指针变量
下面来考考你,那个才是数组指针呢?
Int *p1 [10]; -> [] 的结合率更高,p1[10] 就先形成了数组类,其次int * 指的是数组的元素类型位整型指针,即Int *p1 [10]是存放指针的数组
Int (*p2) [10]; -> p2前面放了一颗*,有小括号,则p2和*先结合,形成指针,int []使数组的类型,所以是指针数组。(p2是数组指针变量)
数组名的深入理解
1.数组名是数组首元素的地址
2.但有2个例外:
(1)sizeof(数组名),这里的数组名不是数组首元素的地址,数组名表示整个数组,sizeof(数组名)计算的是整个数组的大小,单位是字节
(2)&数组名,这里的数组名表示整个数组, &数组名取出的是整个数组的地址
除此之外,所有的地方的数组名都是数组首元素的地址
int main()
{
int arr[10] = { 0 };
//这里就是数组首元素的两种不同写法 arr <==> &arr[0]
printf("%p\n", arr);
printf("%p\n", &arr[0]);
return 0;
}
int main()
{
int arr[10] = { 0 };
printf("%p\n", arr);
printf("%d\n", sizeof(arr));//4 / 8
return 0;
}
int main()
{
int arr[10] = { 0 };
printf("%p\n", arr); //int *
printf("%p\n", arr+1);//arr是指的首元素,打印%p即打印首元素的地址,加一就相当于指针往后挪一位,加4个字节
printf("%p\n", &arr[0]); //int *
printf("%p\n", &arr[0]+1);//跳过一个整型元素,即4个字节
// 整个数组的地址打印出来也是首元素的地址,和&arr[0]一样
printf("%p\n", &arr); //int(*) [10]
//但是&arr地址加一是跳过整个数组,arr是10个整形元素,即40个字节
printf("%p\n", &arr+1);
return 0;
}
二维数组的的每一行都可以理解为二维数组的一个元素
每一行又是一个二维数组的一个元素
每一行又是一个一维数组
所以二维数组就是一维数组的数组
那么数组指针怎么使用呢?
1.错误用法
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;//&arr,取出来的是整个数组的地址,用什么来储存呢?int(*p)[10],即指针数组来储存
//原来的指针 int * p = arr;可以用for循环直接来遍历数组,但是数组指针一来就是整个数组的地址
//int(*p)[10] = &arr; -> (*p) <=> (*&arr) <=> arr * 和 &抵消了
int i = 0;
for (i = 0; i < 10; i++)
{
//printf("%d ",*( (*p) + i));//这样就可以遍历数组了
printf("%d ", (*p)[i]);//等价于上面一行代码语句
//但终归这样用很麻烦,那数组指针怎么用呢? -> 用于二维数组
}
return 0;
}
2.正确用法(数组指针怎么用呢? -> 用于二维数组)
//常规方法
void Print(int arr[3][5], int r, int c)
{
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
Print(arr, 3, 5);
return 0;
}
//使用数组指针
void Print(int (*p)[5], int r, int c)
{
int i = 0;
for (i = 0; i < r; i++) {
int j = 0;
for (j = 0; j < c; j++) {
printf("%d ", * (*(p + i) + j));
}
printf("\n");
}
}
int main()
{
int arr[3][5] = { 1,2,3,4,5, 2,3,4,5,6, 3,4,5,6,7 };
Print(arr, 3, 5);
return 0;
}
三、 指针数组
我们还是先使用类比的方式来引入指针数组的概念
整型数组 - 存放整形的数组
字符数组 - 存放字符的数组
指针数组 - 存放指针的数组
模拟实现二维数组
int main()
{
int arr1[] = { 1,2,3,4,5 };
int arr2[] = { 1,8,3,9,5 };
int arr3[] = { 1,4,3,0,5 };
int *arr[] = { arr1,arr2,arr3 };
int i = 0;
for (i = 0; i < 3; i++)
{
int j = 0;
for (j = 0; j < 5; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
数组指针,是指向数组的指针,是指针
指针数组,是存放指针的数组,是数组
总结
本片笔记就到这里啦,
指针数组和数组指针这俩概念再初学的是时候真的很容易弄混,要细心一点欧
如果有不懂的宝子们,欢迎在评论区留言,我看到了会一一解答。