指针数组
本质是数组 只是每个元素的类型是指针。
图示
代码示例
#include <stdio.h>
int main() {
int num1 = 10;
int num2 = 20;
int num3 = 30;
int num4 = 40;
int *arr[4] = {&num1, &num2,&num3,&num4};
int n = sizeof(arr) / sizeof(arr[0]);
for (size_t i = 0; i < n; i++)
{
printf("%d ", *arr[i]);
}
return 0;
}
一维数组
代码示例
#include <stdio.h>
int main() {
// 1.定义数组
int arr[5] = { 10,20,30,40,50 };
//arr作为类型
printf("sizeof(arr) = %d
",sizeof(arr));//数组的总大小
//arr作为地址 代表首元素的地址
printf("arr = %u
", arr);//int *
printf("arr+1 = %u
", arr+1);
printf("arr[1] = %d
", arr[1]);//20
printf("*(arr+1) = %d
", *(arr+1));//20
printf("---------------------
");
//arr[1]展开成*(arr+1):[]外边的值 在+的左边 []里面的值在+的右边
printf("*(1+arr) = %d
", *(1 + arr));//20
printf("1[arr] = %d
", 1[arr]);//20
//[] 是 *() 的缩写(重要)
for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
{
//printf("%d ", arr[i]);
printf("%d ", i[arr]);
}
printf("
");
//arr 作为地址 是首元素的地址
//&arr[0] == &*(arr+0) == arr+0 == arr
return 0;
}
程序运行结果
一维数组名
一维数组名是个指针常量,他存放的是一维数组第一个元素的地址 。
代码示例
#include <stdio.h>
int main(void)
{
int a[5]; //a是数组名 5是数组元素的个数 元素就是变量 a[0] -- a[4]
//int a[3][4]; //3行4列 a[0][0]是第一个元素 a[i][j]第i+1行j+1列
int b[5];
//a = b;//error a是常量
printf("%#X
", &a[0]);
printf("%#X
", a);
return 0;
}
程序运行结果
总结
-
一维数组名是个指针常量。
-
它存放的是一维数组第一个元素的地址。
-
常量是不能被改变的,也就是说,一维数组名是不能被改变的。
-
数组名a存放的是一维数组第一个元素的地址,也就是a = &a。
下标和指针的关系
如果p是个指针变量,则p[i]永远等价于*(p+i)
# include <stdio.h>
int main(void)
{
int a[5] = {1,2,3,4,5};
int i;
for (i=0; i<5; ++i)
printf("%d
", a[i]); //a[i] == *(a+i)
return 0;
}
数组元素指针
代码示例
#include <stdio.h>
int main() {
/**
* 需求:定义一个指针变量 保存arr数组元素的地址
*/
// 声明一个数组
int arr[5] = { 10,20,30,40,50 };
int *p = arr;//int *p; p=arr;
for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++)
{
//printf("%d ", *(p + i));
printf("%d ", p[i]);
}
printf("
");
printf("sizeof(arr) = %d
", sizeof(arr));//20
printf("sizeof(p) = %d
", sizeof(p));//4
/**
*不要认为p只能保存首元素地址
* 指针变量 起始指向哪儿? p[x] == *(p+x)
*/
int *p1 = &arr[2];
printf("p1[1] = %d
", p1[1]);//40
printf("p1[-1] = %d
", p1[-1]);//20
return 0;
}
程序运行结果
案例说明
#include <stdio.h>
int main() {
int arr[5] = { 10,20,30,40,50 };
int *p = arr;
printf("%d
", *p++);//10;; *p; p++
printf("%d
", (*p)++);//20 ; *p; (*p) = (*p) +1
printf("%d
", *(p++));//21
printf("
");
return 0;
}
程序运行结果
10
20
21
同一数组的两个元素指针的关系
- 指向同一数组的两个元素指针变量相减,是两指针变量间元素的个数。
- 指向同一数组的两个元素指针变量相加,无意义。
- 指向同一数组的两个元素指针变量 p1 = p2(p1和p2指向同一处)。
一维数组需要几个参数
代码示例
# include <stdio.h>
/*
a是个指针变量,所以上面局部函数f的pArr则要定义成指针函数才可以,而len则是int类型。
代表接收的是整型的数字。fmin函数可以输出任何一个一维数组的内容
*/
// 声明函数
void fmax(int * pArr, int len)
{
int i;
for (i=0; i<len; ++i)
printf("%d ", pArr[i] ); //*pArr *(pArr+1) *(pArr+2)
printf("
");
}
int main(void)
{
int a[5] = {1,2,3,4,5};
int b[6] = {-1,-2,-3,4,5,-6};
// 调用函数
fmax(a, 5); //a是 int *
fmax(b, 6);
return 0;
}
总结:
因为数组a的名称代表的是a的第一个元素的地址,所以在函数fmax中所定义的指针变量pArr和a是相同的,因为a也是指针变量类型。
也就是说pArr=a=a[0],pArr[1]=a[1]=*(pArr+1)=*(a+1),pArr[2]=a[2]=*(pArr+2) =*(a+2).
二级指针
图示
代码示例
#include <stdio.h>
int main() {
int num = 10;
int *p = #
int **q = &p;
printf("&num = %u
", &num);
printf("p = %u
", p);
printf("&p = %u
", &p);
printf("q = %u
", q);
printf("*q = %u
", *q);
printf("**q = %u
", **q);
return 0;
}
程序运行结果
&num = 6422036
p = 6422036
&p = 6422024
q = 6422024
*q = 6422036
**q = 10
地址变量
1、Sizeof(变量名/数据类型) 其返回值就是该变量或数据类型所占字节数
2、一个指针变量无论其指向变量占几个字节,其本身所占大小都是4字节。
3、*p具体指向几个字节,要靠前面类型确定,如果为int则为4字节,如果double则占8字节。
4、CPU与内存交互时有32根线,每根线只能是1或0两个状态,所有总共有232个状态。1 个状态对应 一个单元。
5、所有每个地址(硬件所能访问)的用4个字节保存(而不是一 位bit)
代码示例
# include <stdio.h>
int main(void)
{
char ch = 'A';
int i = 99;
double x = 66.6;
char * p = &ch;
int * q = &i;
double * r = &x;
printf("%d %d %d
", sizeof(p), sizeof(q), sizeof(r));
return 0;
}
总结
一个变量的地址—用该变量首字节的地址表示。这也就是为什么指针变量始终只占4字节的原因。