数组与指针

数组是一些相同数据类型的变量组成的集合,其数组名就是指向该数据类型的指针。数组的定义等效于申请内存、定义指针和初始化。

例如:

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;
  1. (*p)++

    • (*p) 是指针 p 当前指向的内存位置的值,初始时为 1
    • (*p)++ 首先获取指针 p 当前指向的内存位置的值(即 1),然后将该值递增 1,结果为 2
    • 此表达式会递增指针 p 指向的内存位置的值,而不是指针本身。
    int value = (*p)++; // value = 1, arr[0] 的值递增为 2
    
  2. *p++

    • *p 是指针 p 当前指向的内存位置的值,初始时为 1
    • *p++ 首先获取指针 p 当前指向的内存位置的值(即 1),然后将指针 p 向后移动一个位置,现在指向 5
    • 此表达式会获取指针 p 指向的内存位置的值(即 1),然后将指针 p 向后移动。
    int value = *p++; // value = 1, p 指向 arr[1](值为 5) 现在
    
  3. *(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 向后移动,分别指向 510

这些表达式的执行效果会根据上下文而不同,但上述解释涵盖了它们的基本行为。

值传递和指针传递

在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;
}

区别和联系

  1. 区别:
    • 值传递传递的是实际参数的值的副本,而指针传递传递的是实际参数的地址。
    • 值传递不允许在函数内部修改实际参数的值,而指针传递允许通过指针修改实际参数的值。
    • 值传递通常更安全,因为不会意外修改实际参数的值,而指针传递可能引入错误。
  2. 联系:
    • 值传递和指针传递都用于将数据传递给函数。
    • 两者都允许函数访问实际参数的值。
    • 选择使用哪种方式取决于需求和设计目标。指针传递更适合需要在函数内修改实际参数的情况,而值传递更适合不需要修改实际参数的情况。

在实际编程中,应根据需要选择合适的参数传递方式,以确保代码的正确性和性能。

最后修改:2023 年 11 月 10 日
如果觉得我的文章对你有用,请随意赞赏