【问题标题】:structure array member address problems结构体数组成员地址问题
【发布时间】:2021-09-01 15:04:41
【问题描述】:
#include<stdio.h>

struct Book {
    char * name;
    int page;
};

void demo(struct Book bookArr[]);

int main(){
    struct Book bookArr[] = {{"c struct",1},{"c struct",2}};
    printf("bookArr address from main: %p\n",&bookArr);
    printf("bookArr[0] address from main: %p\n",&bookArr[0]);
    demo(bookArr);
    return 0;
}

void demo(struct Book bookArr[]){
    printf("bookArr address from demo: %p\n",&bookArr);
    printf("bookArr[0] address from demo: %p\n",&bookArr[0]);
}
The output: 
bookArr address from main: 0x1040bb350
bookArr[0] address from main: 0x1040bb350
bookArr address from demo: 0x1040bb328
bookArr[0] address from demo: 0x1040bb350
Program ended with exit code: 0

demo 中的 bookArr 在启动时复制 main 中的 bookArr,所以我可以理解为什么两个函数的 bookArr 地址不同,但我不明白为什么两个函数的 bookArr[0] 地址相同。演示不是已经分配了完整的 BookKarr 吗? bookArr[0] 和 bookArr[1] 都是指针吗?但事实并非如此

【问题讨论】:

  • 我没明白这个问题是什么“bookArr[0] 和 bookArr[1] 都是指针?”什么意思?
  • 不明白为什么这两个函数的bookArr[0]地址是一样的。

标签: arrays c pointers pass-by-reference implicit-conversion


【解决方案1】:

首先考虑一个简单的例子:

#include <stdio.h>

void f( int *px )
{
    printf( "in f &( *px ) = %p\n", ( void * )&( *px ) );
    
}
int main(void) 
{
    int x = 10;
    
    printf( "in main &x    = %p\n", ( void * )&x );
    
    f( &x );
    
    return 0;
}

程序输出可能如下所示:

in main &x    = 0x7ffccc31de34
in f &( *px ) = 0x7ffccc31de34

即变量x通过指向它的指针通过引用传递给函数f。

取消引用函数*px 中的指针,您可以直接访问存储变量x 的内存。变量x 本身没有传递给函数。它是一个指向被传输变量的指针。

因此,使用表达式&amp;( *px )&amp;( px[0] ) 或只是px,您将获得main 中原始变量x 的地址。

当您传递一个数组时,它会隐式转换为指向其第一个元素的指针。另一方面,具有数组类型的函数参数也被调整为指向数组元素类型的类型指针。

就是这个函数声明:

void demo(struct Book bookArr[]);

相当于:

void demo(struct Book * bookArr);

所以数组本身并没有复制到函数中。它是传递给函数的第一个元素的指针。

所以参数bookArr的值得到了数组第一个元素的地址。实际上,参数 bookArr 获得了 bookArr 在 main 中声明的表达式 book &bookArr[0] 的值。所以实际上在 main 中声明的数组的所有元素都通过引用传递给函数,因为使用指针算法可以得到数组每个元素的地址。即 bookArr 是数组第一个元素的地址 *表达式也可以写成 &bookArr[0]),bookArr + 1 是数组第二个元素的地址,以此类推。

注意这个调用中的main

 printf("bookArr address from main: %p\n",&bookArr);

表达式&amp;bookArr 没有struct Book * 类型。它的类型为 struct Book ( * )[2] 因为在 main 中有一个数组。另一方面,在函数演示 bookarr 的类型为 struct Book *(由于将参数调整为指向数组元素类型的指针),表达式 &bookArr 的类型为 struct Book ** 并产生参数的地址(局部变量函数)。

【讨论】:

  • 非常感谢!讲解很全面,教过
  • 我在demo中尝试输出sizeof(bookArr),结果为8,验证了你的解释。非常感谢
【解决方案2】:

事实上,只有一个 Book 数组存在,并且两个函数都引用同一个数组。但是,每个函数都通过不同的局部变量访问该数组。

在任一函数中,&amp;bookArr 都不是数组的起始地址。它是 局部变量 的地址,它保存指向数组开头的指针。

如果您要打印 bookArr 本身,它本身就是一个指针,您会看到它们都指向同一个内存位置。

【讨论】:

    【解决方案3】:

    main 函数中的bookArr 是一个数组。

    表达式中的大多数数组都会自动转换为指向其第一个元素的指针,但一元 &amp; 运算符的操作数是例外之一。

    通常,数组的位置和它的第一个元素在内存中的地址相同。 (数组中第一个元素之前没有多余的空间。)

    bookArr[0]bookArr[1] 不是指针而是结构体(struct Book`)。

    【讨论】:

    • 'bookArr[0] 和 bookArr[1] 不是指针,而是结构(struct Book`)。' ,所以,我不明白为什么两个函数有相同的 bookArr[0] 地址。
    • bookArr[0] 的地址相同,因为它们在数组中查看相同的结构。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-11
    • 1970-01-01
    • 2011-04-26
    • 1970-01-01
    相关资源
    最近更新 更多