欢迎来到博主的专栏:C语言进阶指南
博主id:reverie_ly
指针可以进行加和减以及自加和自减算术运算。运算结果是
地址值加或减指针类型指向的元素的空间大小。
尝试运行以下代码
char c;
int i;
double d;
char* pc=&c;
int *pi=&i;
double* pd=&d;
printf("pc=%p\tpc+1=%p\n", pc, pc + 1);
printf("pc=%p\tpc+1=%p\n", pi, pi + 1);
printf("pc=%p\tpc+1=%p\n", pd, pd + 1);
%p是指针类型参数的转换声明。
我们可以发现pc+1与pc的地址差为1.
pi+1与pi的地址差为4
pd+1与pd的地址差为8
这是由于char*类型的指针指向的类型是char,所以加1是指向下一个char类型元素的空间大小(1字节)
以此类推
图中每一个空格表示一个内存中的字节
数组的元素都是在内存中连续排序的,那么也就是说可以用指针加减的方式来访问数组元素。
pi+1仍然是一个指针类型的值,所以想要访问元素或者对元素进行操作,那么就需要用到解引用操作符‘*’。
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9 ,10};
int* pi = arr;
for (i = 0; i < 10; i++) {
printf("%d ", *(pi + i));
}
return 0;
可以发现一个很有意思的现象
*(arr+i)=arri
上面将数组名赋予了指针pi
int*pi=arr;
这是不是说明数组名本身是一个指针呢?我们可以在监视窗口中看到
arr作为数组时,是一个int[10的类型。这里在下例中可以看到
sizeof(arr);
sizeof的将会显示整个数组的大小。
但如果将arr作为指针使用时(arr+1),arr会被降级为int*类型(这一点在二维数组更为明显)
所以当我们将arr作为指针变量的值时,
赋予指针变量的是int*类型的arr中第一个元素的地址
数组arr降级的例子是
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9 ,10};
for (i = 0; i < 10; i++) {
printf("%d ", *(arr + i));
}
return 0;
这里没有使用指针变量来进行操作,而是使用数组名来进行指针操作。可以发现这两个例子的结果都是一致的。
所以可以得出结论
当数组名作为指针层面的使用时,会发生类型降级,arr从int[]变为int*。
void print(int arr[])
{
for (int i = 0; i < N; i++)
{
printf("%d", arr[i]);
}
}
int main()
{
int arr[N] = { 1,2,3,4,5,6,7,8,9,10 };
print(arr);
return 0;
}
这个print函数的参数是一个int[]类型的数组,所以可以将arr作为实参来传递。但是在这个函数中,数组名会被作为指针来操作(arri等价于(arr+i)).所以这个数组名被降级为int类型。
所以我们也可以一开始就让arr发生类型降级,直接将函数形参设定为int*类型的指针
void print(int* arr)//不再是int[]类型的arr。
{
for (int i = 0; i < N; i++)
{
printf("%d", arr[i]);
}
}
int main()
{
int arr[N] = { 1,2,3,4,5,6,7,8,9,10 };
print(arr);
return 0;
}
这两个函数在使用时的效果完全一致。
敲重点:
1)int[]类型的数组名作为指针使用时,会被降级成int*类型的数组名
在大部分情况下,int[]类型与int的变量是可以互通的,但是为什么说int[]降级成int呢。
这两个类型的区别就在于声明阶段了
int arr[10]={1,2,3,4,5,6,7,8,9,10};//正确
int* pi = {1,2,3,4,5,6,7,8,9,10};//非法
int[]可以声明一个数组,而int*类型不能用于声明一个数组。
当数组名作为指针来使用时(比如作为函数的参数或者用数组名进行指针算术运算时),int[]和int*的变量是可以互通的。
比如
void print(int arr[])
{
for (int i = 0; i < N; i++)
{
printf("%d", arr[i]);
}
}
int main()
{
int arr[N] = { 1,2,3,4,5,6,7,8,9,10 };
int* pi = {1,2,3,4,5,6,7,8,9,10};
print(pi);
return 0;
}
这里是将int*的实参(pi)传递到int[]的形参(arr)中。
2)当数组名(arr)发生降级时,数组名将是首元素的地址、
int *pi=arr;
实际上pi的值是数组首元素的地址,(即&arr0,类型是int*)
我们在前面的例子中已经很明显的发现了这么一个规律
我们知道将指针解引用得到就是该地址的数据。
所以(arr)=arr0(可以理解成(arr+0))。
由此可得*(arr+i)=arri。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。