为什么我可以在同时在别处定义指针时使用它?

问题描述

假设我有一个这样的 struct

typedef struct {
    char* author;
    uint32_t isbn;
} Book;

int
main( int arg_c; char* arg_v[] ) {
    Book* b = malloc( sizeof *b );
    char* author = "Miller";

    //[...]

    free(b);
    return 0;
}

现在有点让我失望的是第 8 行:Book* b = malloc( sizeof *b ); 在这里,我在等号的左侧创建了一个 b 类型的指针 Book,但是在同时,我取消引用右侧的 bb 分配内存。

这是如何工作的?

如何同时定义一个指针,因为我使用该指针为其分配内存。 如果它们是 Book* b = malloc( sizeof (Book) );,那对我来说很直观,因为 sizeof 询问 类型 的大小。但在这里,就好像标识符同时在两个地方使用,同时它正在被定义。

是否有一些我遗漏的双关事件?

解决方法

这个表达

sizeof *b

不被评估。编译器只是尝试确定表达式 *b 的类型,该类型为 Book。所以实际上这个表达式等价于

sizeof( Book )

变量 b 的类型在其声明符定义完成后就知道了。所以初始化表达式已经知道初始化对象的类型了。

为了更清楚,请考虑以下演示程序

#include <stdio.h>

int main(void) 
{
    int x = 10;
    
    size_t n = sizeof( x += 20 );
    
    printf( "n = %zu,x = %d\n",n,x );
    
    return 0;
}

程序输出为

n = 4,x = 10

作为这个表达

sizeof( x += 20 )

未求值(编译器仅确定表达式的类型),则变量 x 的值未更改。

另一个更复杂的例子。

#include <stdio.h>

int i = 1;

int main(void) 
{
    size_t i[i],b = sizeof( i );

    printf( "b = %zu\n",b );

    return 0;
}

程序输出为

b = 8

在数组 i 的声明中使用了在文件作用域中声明的变量 i,因为数组 i 的声明符尚未完成。但是在变量 b 的声明中使用了表示数组的标识符 i

,

它不会取消对指针的引用。
它仅使用指针指向的大小。
看看更奇怪的 Book* b = malloc( sizeof (Book) ); 对您来说可能是合理的,它根本没有真正访问任何东西,只使用一个类型。