指针和数组的纠缠
1. 指针表示法和数组表示法
数组完全可以使用指针来访问, days[3] 和 *(days+3) 等同
#include <stdio.h>
#include <stdlib.h>
void print_months(int days[], int months) {
int index = 0;
for (index = 0; index < months; index++) {
// Array notation
// printf("month %2d has %d days.\n", index+1, days[index]);
// Pointer notation
printf("Month %2d has %d days.\n", index+1, *(days+index));
}
}
void print_months2(int *days, int months) {
int index = 0;
for (index = 0; index < months; index++) {
// Pointer notation
printf("Month %2d has %d days .\n", index+1, *(days+index));
// Array notation
printf("Month %2d has %d days. \n", index+1, days[index]);
}
}
int main() {
int days[12] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
int index = 0;
/*for (index = 0; index < 12; index++) {
// Array notation
printf("Month %2d has %d days.\n", index+1, days[index]);
// Pointer notation
printf("Month %2d has %d days.\n", index+1, *days+index);
}
*/
print_months(days, 6);
//print_months2(days, 12);
return 0;
}
运行结果:
存储指针的数组
定义: 类型 *指针数组名[元素个数] ;
#include <stdio.h>
#include <stdlib.h>
int main()
{
int girls[4][3] = {
{173, 158, 166},
{168, 155, 171},
{163, 164, 165},
{163, 164, 172}};
int *qishou[2];
if (girls[0][0] > girls[0][1]) {
qishou[0] = &girls[0][0];
qishou[1] = &girls[0][1];
}else {
qishou[0] = &girls[0][1];
qishou[1] = &girls[0][0];
}
for (int i = 2; i < 12; i++) {
if (*qishou[1] >= girls[i/3][i%3]) {
continue;
}
// 候选者高于第二位棋手候选女兵
// 1.候选者比"冠军"矮
if (girls[i/3][i%3] <= *qishou[0]) {
qishou[1] = &girls[i/3][i%3];
}else {
qishou[1] = qishou[0];
qishou[0] = &girls[i/3][i%3];
}
}
printf("Highest female soldier height: %d, Second highest female soldier height: %d\n", *qishou[0], *qishou[1]);
return 0;
}
运行结果:
指针和二维数组
1. 指向数组的指针
int (*p)[3]; //定义一个指向三个成员的数组的指针
访问元素的两种方式:
数组法: (*p)[j]
指针法: *((*p)+j)
#include <stdio.h>
#include <stdlib.h>
int main() {
/*据同学们报告,A 栋学生楼有学生用高倍望眼镜偷看别人洗澡,
宿管办领导决定逐个宿舍排查,得到的线报是 A0 到 A3 宿舍的
某个子最矮的男生。 */
int A[4][3] = {
{173, 158, 166},
{168, 155, 171},
{163, 164, 165},
{163, 164, 172}};
//定义一个指向三个成员的数组的指针
int (*p)[3];
int * boy = NULL;
p = &A[0];
// The first kind of
/*for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
// (*p) 等同于 a[0] ,a[0][0]等同于 (*p)[0]
printf(" %d", (*p)[j]);
}
printf("\n");
p++;
}*/
boy = &(*p)[0];
// boy = (*p);
// The second //int a[3]; int * p ; p = a; Array members: *p *(p+1) *(p+2)
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 3; j++) {
printf(" %d", *((*p)+j));
if (*boy > *((*p)+j)) {
boy = (*p) + j;
}
}
printf("\n");
p++;
}
printf("The student who peeps is: %d\n", *boy);
return 0;
}
运行结果:
使用普通指针访问二维数组
int A[4][3];
int *p; //定义一个指针
p = A[0]; 或者 p=&A[0][0];
访问元素的两种方式:
#include <stdio.h>
#include <stdlib.h>
int main() {
/*据同学们报告,A 栋学生楼有学生用高倍望眼镜偷看别人洗澡,
宿管办领导决定逐个宿舍排查,得到的线报是 A0 到 A3 宿舍的
某个子最矮的男生。 */
int A[4][3] = {{173, 158, 166},
{168, 155, 171},
{163, 164, 165},
{163, 164, 172}};
int *boy = NULL;
int *p = NULL;
//p = A[0];
p = &A[0][0];
boy = p;
for (int i = 1; i < 4*3; i++, p++) {
//*p 可以替换成 A[i/3][i%3]
if (*boy > *p) {
boy = p;
}
}
printf("The students were: %d\n", *boy);
// Calculate the index according to the pointer
int pos = boy - A[0];
printf("index: %d\n", pos);
printf("locate A[%d] dormitory\n", pos/3);
printf("Is the first %d Is the first\n", pos%3);
return 0;
}
运行结果:
“我们不一样“之数组与指针的区别
数组:数组是用于储存多个相同类型数据的集合。
指针:指针是一个变量,但是它和普通变量不一样,它存放的是其它变量在内存中的地址。
1. 赋值
数组:只能一个一个元素的赋值或拷贝 指针:指针变量可以相互赋值
2. 表示范围
数组有效范围就是其空间的范围,数组名使用下表引用元素,不能指向别的数组
指针可以指向任何地址,但是不能随意访问,必须依附在变量有效范围之内
3. sizeof
数组:数组所占存储空间的内存:sizeof(数组名)
数组的大小:sizeof(数组名)/sizeof(数据类型)
指针:在 32 位平台下,无论指针的类型是什么,sizeof(指针名)都是 4.
在 64 位平台下,无论指针的类型是什么,sizeof(指针名)都是 8.
指针数组和数组指针
***针指数组:***
int *qishou[2];//定义一个有两个元素的指针数组,每个元素都是一个指针变量
int girl1= 167;
int girl2 = 171;
qishou[0] = &girl1;
qishou[1] = &girl2;
***数组指针:***
int (*p)[3]; //定义一个指向三个成员的数组的指针
访问元素的两种方式:
int A[4][3]={{173, 158, 166},
{168, 155, 171},
{163, 164, 165},
{163, 164, 172}};
p = &A[0];
数组法: (*p)[j]
指针法: *((*p)+j)
传参
数组传参时,会退化为指针!
(1)退化的意义:C 语言只会以值拷贝的方式传递参数,参数传递时,如果只拷贝整个数 组,效率会大大降低,并且在参数位于栈上,太大的数组拷贝将会导致栈溢出。
(2)因此,C 语言将数组的传参进行了退化。将整个数组拷贝一份传入函数时,将数组名 看做常量指针,传数组首元素的地址。