数组与指针
数组是一些相同数据类型的变量组成的集合,其数组名就是指向该数据类型的指针。数组的定义等效于申请内存、定义指针和初始化。
例如:
char a[]={0x33,0x34,0x35};
假设数组a[0]指向地址0x4000,则数组的地址与存储数据的关系如下:
利用下标引用数组数据等效于指针取内容:
-
a[0] 等效 *a;
-
a[1] 等效 *(a+1);
-
a[2] 等效 *(a+2);
注意:
-
在对指针取内容之前,一定要确保指针指在合法的位置上,否则可能会出错。
-
注意同级指针才能相互赋值,跨级可能会报错
(**p)++ 、p++、(p++)区别和联系
当我们将数组 arr[]
更改为 {1, 5, 10}
,我们将再次讨论 (*p)++
、*p++
和 *(p++)
这三个表达式的区别和联系。让我用新的数组值来详细解释它们:
int arr[] = {1, 5, 10};
int *p = arr;
-
(*p)++
:-
(*p)
是指针p
当前指向的内存位置的值,初始时为1
。 -
(*p)++
首先获取指针p
当前指向的内存位置的值(即1
),然后将该值递增1
,结果为2
。 - 此表达式会递增指针
p
指向的内存位置的值,而不是指针本身。
int value = (*p)++; // value = 1, arr[0] 的值递增为 2
-
-
*p++
:-
*p
是指针p
当前指向的内存位置的值,初始时为1
。 -
*p++
首先获取指针p
当前指向的内存位置的值(即1
),然后将指针p
向后移动一个位置,现在指向5
。 - 此表达式会获取指针
p
指向的内存位置的值(即1
),然后将指针p
向后移动。
int value = *p++; // value = 1, p 指向 arr[1](值为 5) 现在
-
-
*(p++)
:-
p++
是指针p
的后缀递增操作,它会先使用指针p
的当前值,然后再将指针p
向后移动一个位置,初始时指向1
。 -
*(p++)
先获取指针p
当前指向的内存位置的值(即1
),然后将指针p
向后移动一个位置,现在指向5
。 - 此表达式与
*p++
的效果相同,都是获取指针p
指向的内存位置的值(即1
),然后将指针p
向后移动。
int value = *(p++); // value = 1, p 指向 arr[1](值为 5) 现在
-
总结:
-
(*p)++
递增的是指针p
指向的内存位置的值,初始时为1
,结果为2
。 -
*p++
和*(p++)
都是获取指针p
指向的内存位置的值(初始时为1
),然后将指针p
向后移动,分别指向5
和10
。
这些表达式的执行效果会根据上下文而不同,但上述解释涵盖了它们的基本行为。
值传递和指针传递
在C语言中,值传递(Pass by Value)和指针传递(Pass by Pointer)是两种传递参数给函数的方式,它们之间有一些重要的区别和联系。
值传递 (Pass by Value):
- 值传递是将实际参数的值复制给函数的形式参数。
- 在函数内部,对形式参数的任何修改都不会影响到实际参数。
- 值传递适用于基本数据类型(如整数、浮点数、字符等)以及结构体和枚举等用户定义的数据类型。
- 值传递通常更安全,因为函数无法修改实际参数的值。
示例:
void modifyValue(int x) {
x = x + 1;
}
int main() {
int num = 5;
modifyValue(num);
// 此时num仍然为5,因为函数中的修改不影响num的值
return 0;
}
指针传递 (Pass by Pointer):
- 指针传递是将实际参数的地址(指针)传递给函数的形式参数。
- 在函数内部,可以通过指针修改实际参数的值。
- 指针传递通常用于需要修改实际参数或传递大型数据结构时,以避免复制整个数据结构的开销。
- 需要小心指针传递中的空指针或悬挂指针问题,以防止未定义行为。
示例:
void modifyPointer(int *ptr) {
*ptr = *ptr + 1;
}
int main() {
int num = 5;
modifyPointer(&num);
// 此时num变为6,因为函数中通过指针修改了num的值
return 0;
}
区别和联系:
- 区别:
- 值传递传递的是实际参数的值的副本,而指针传递传递的是实际参数的地址。
- 值传递不允许在函数内部修改实际参数的值,而指针传递允许通过指针修改实际参数的值。
- 值传递通常更安全,因为不会意外修改实际参数的值,而指针传递可能引入错误。
- 联系:
- 值传递和指针传递都用于将数据传递给函数。
- 两者都允许函数访问实际参数的值。
- 选择使用哪种方式取决于需求和设计目标。指针传递更适合需要在函数内修改实际参数的情况,而值传递更适合不需要修改实际参数的情况。
在实际编程中,应根据需要选择合适的参数传递方式,以确保代码的正确性和性能。