【问题标题】:Why can I use a pointer while it's being defined elsewhere at the same time?为什么我可以在其他地方同时定义指针时使用它?
【发布时间】:2021-04-30 21:40:01
【问题描述】:

假设我有一个这样的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 ); 在这里,我在等号的左侧创建了一个 Book 类型的指针 b,但同时,我取消引用右侧的bb 分配内存。

它是如何工作的?

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

是否发生了一些我遗漏的双重通过的事情?

【问题讨论】:

  • sizeof 的操作数不会被计算,所以sizeof(*p) 不会取消引用p。它只查看表达式*ptype。一定有一个重复的地方,但我没有立即看到一个好的。否则你是对的,取消引用未初始化的指针会有问题。
  • 通常不禁止使用您在其自己的初始化程序中定义的标识符。 int x = x; 在语法和语义上是合法的,尽管(我相信)如果执行它会导致未定义的行为。

标签: c pointers initialization declaration sizeof


【解决方案1】:

这个表达式

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 来表示数组。

【讨论】:

  • 我明白这一点,但我不明白的是,可以询问正在为自己的定义定义的过程中的事物的类型。那么在没有为它分配分配的情况下定义了类型,并且它可以在语句的其余部分中使用吗?
  • @polemon 变量b的类型是在其完整的声明符定义之后定义的。
  • 啊啊啊!因此,一旦编译器解释了等号的左侧,它就已经编码了类型并注册了标识符?这样标识符及其类型对于语句的其余部分都是已知的?
  • @polemon 是的,只要声明符被定义,它的类型就知道了。
  • @polemon 查看我的附加帖子。
【解决方案2】:

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

【讨论】:

  • 不起作用:我的编译器 (clang) 抛出错误:“错误:sizeof 表达式 Book* b = malloc( sizeof Book ); 中类型名称周围的预期括号;”
  • 您没有收到问题中显示的代码的警告吗?请提供minimal reproducible example
  • 不,当我使用Book* b = malloc( sizeof *b ); 时,它编译得很好。
  • sizeof 与类型一起使用而不与表达式一起使用时需要括号,请参阅stackoverflow.com/questions/5894892/…
  • 对不起,我承认在发布前没有测试。固定的。感谢@Nate,感谢您指出我到底混淆了什么。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-01
  • 1970-01-01
  • 2010-09-11
相关资源
最近更新 更多