目录
在指针初识里,数组与指针只是浅浅了解一下,重点还在指针进阶里面!
一、指针运算
1、指针 + - 整数
例1:
int main()
{
int arr[5];
int* p = &arr[0];
for (p; p < &arr[5];)
{
*p++ = 0;
}
}
注意:
1、*p++和(*p)++的区别:
*p++指的是,先*p然后再给p++
(*p)++指的是,先解引用,然后给其所指向的元素++
2、注意,代码中的&arr[5]并不算指针越界,因为内存中确实是有这样一块空间的,我们并没有使用它,就只是和它比了一下大小而已,就好比,我去商店买东西,那零食太贵了,我不买它,我只是看它一眼,拿它的价格做了个对比而已,你总不能说我在偷东西吧!
但这里也有规定的
标准规定:
允许指向数组元素的指针与指向数组最后一个元素后面的那个内存位置的指针进行比较,但是不允许与指向第一个元素之前的那个内存位置的指针进行比较。
只不过呢,如果你非要与第一个元素的前一个位置的指针进行比较,在绝大多数的编译器上还是可以顺利完成任务的,然而我们还是应该避免这样写,因为标准并不保证它可行。
例2:
int main()
{
int arr[5] = { 0 };
int i = 0;
//写法一:
/*for (i = 0; i < 5; i++)
{
arr[i] = 1;
}*/
//写法二:
/*int* p = arr;
for (i = 0; i < 5; i++)
{
*p = 1;
p++;
}*/
//写法三:
int* p = arr;
for (i = 0; i < 5; i++)
{
*(p + i) = 1;
}
return 0;
}
写法一:是数组下标的写法
写法二:是一直给p++,不断改变p,++就跳过4个字节(int)
写法三:是给p+i解引用,i=1,跳过一个整型空间,i=2跳过2个整型空间......
2、指针 - 指针
指针 - 指针的绝对值得到的是指针和指针之间的元素个数
代码:
int main()
{
int arr[10] = { 0 };
printf("%d\n", &arr[9] - &arr[0]);
printf("%d\n", &arr[0] - &arr[9]);
return 0;
}
考虑一下,到底会输出什么呢?注意上面强调的绝对值
运行结果:
不是所有的指针都可以相减,指向同一块空间的2个指针才能相减,换句话说,它们满足这个条件相减才有意义的!
可能会有人疑惑,中间不是应该有10元素吗?嗯...不对哦,看下面的图,你就明白了
用途举例:
计算字符串长度
int my_strlen(char* str)
{
char* start = str;
while (*str != '\0')
{
str++;
}
return (str - start);
}
int main()
{
int len = my_strlen("asdfghjkl");
printf("%d\n", len);
return 0;
}
注:指针加指针没有什么意义
二、数组与指针
数组通过指针来访问
指针变量用来存放地址的一个变量,数组是用来存放一组相同类型元素的集合
二者针对的对象是不同的,看似是没有什么关联
但是数组所占空间是内存中一块连续的空间,而他们的地址就可以存放在指针变量里面,通过指针就可以访问这个数组。
数组名表示的是数组首元素的地址(2种情况除外):
1、sizeof(数组名)这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节
2、&数组名,这里的数组名表示整个数组,取出的是整个数组的地址
先看如下代码,再来分析:
int main()
{
int arr[10] = { 0 };
int* p = arr;
int i = 0;
for (i = 0; i < 10; i++)
{
printf("%p--------%p\n", &arr[i], p + i);
}
return 0;
}
运行结果:
我们会发现,p+i与&arr[i]取出的地址是相同的,结合下图,理解一下:
p+i是通过指针+i获得的地址,&arr[i]是通过数组元素取地址
所以打印数组元素时,有如下两种方式:
printf("%d\n", *(p + i));
printf("%d\n", arr[i]);
代码中,我们时int* p=arr;将arr赋给了p,说明p和arr是同一个意思,所以也可以写成
printf("%d\n", *(arr + i));
注:arr[i]在计算时,其实是按照*(arr+i)的方式计算的
代码:
void test1(int arr[], int n)
{
int i = 0;
for (i = 0; i < n; i++)
{
printf("%d ", arr[i]);
//printf("%d ", *(arr + i));//或
}
}
void test2(int* p, int n)
{
int i = 0;
for (i = 0; i < n; i++)
{
printf("%d ", *(p + i));
}
}
int main()
{
int arr[10] = { 0 };
test1(arr, 10);
test2(arr, 10);
return 0;
}
所以在数组传参时,函数的形参,用指针来接收,因为数组名就是表示首元素的地址,即是一个指针。
这一期,就到这里啦!