问题描述
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
,但是在同时,我取消引用右侧的 b
为 b
分配内存。
这是如何工作的?
如何同时定义一个指针,因为我使用该指针为其分配内存。
如果它们是 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) );
对您来说可能是合理的,它根本没有真正访问任何东西,只使用一个类型。