【问题标题】:Why pointer of pointers are declared with different no. of asterisk when their size is same [closed]为什么指针的指针用不同的编号声明。当它们的大小相同时的星号[关闭]
【发布时间】:2018-02-04 13:01:49
【问题描述】:

根据架构或编译器,“指针”的大小始终相同(4/8B/其他)。

int** b = &pointer;
int***c = &b;

sizeof(b) 和 sizeof(c) 是相同的,所以我们可以用同样的方式取消引用它们。 如果一个指针指向另一个指针或指针的指针不应该是这样,我们只需要用两颗星来声明它。

【问题讨论】:

  • 首先,指针的大小总是相同的......而且并非所有指针的大小都相同。甚至不在同一个架构上。
  • 如果你用两个星号声明它,你怎么知道***c = 0; 有效但******c = 0; 无效?
  • @AnttiHaapala - 请原谅,“C++ 风格”?
  • @AnttiHaapala - 嗯,我很确定火焰战争早于 C++ 本身。此外,我看到它只有一种方式而不是另一种方式(在 C 和 C++ 中)的唯一地方是函数返回类型。祝福他的 Bjarne 并不代表我们所有人。
  • 他们取消引用以产生不同的类型。一个取消引用int,而下一个取消引用指针int*,依此类推...

标签: c++ c pointers


【解决方案1】:

考虑你的例子:

int* a = &integer
int** b = &a;
int*** c = &b;

它们都是不同的类型。它们都是指针,但它们指向不同的类型指针。

第一个是指向整数的指针

第二个是指向整数的指针

第三个是指向整数的指针

在查看指针指向的位置(取消引用)时,这一点很重要。

如果我这样做:

*b; // what is that?

我能从中得到一个整数吗?不!我把我放进去的东西拿出来:

int** b = &a;

我得到a,它是一个指向整数的指针,它不是int,它是一个指向整数的指针

如果我想访问int,我必须再次取消引用:

**b; // now I located the integer

所以*bint***b 是原来的int

【讨论】:

    【解决方案2】:

    没关系。指针运算仅取决于它指向的内容。例如int(*p)[2]int *p 两者都是不同的。同样的方式int **pint ***p 是不同的。您可能会认为即使 sizeof (int*)sizeof(int**) 相同 - 丢失多个间接信息是不合逻辑的。这有助于获得正确的指针算法。 (如果它们的大小相同,它将是相同的,但指针运算不会有问题,但在其他方面会出现问题 - 请参阅问题的第二段)。

    请注意,这些对我们编写非常有帮助 - 考虑一个系统,您将有责任编写正确的代码来解除对变量正确次数的引用。您必须记住它指向的位置?无论是变量的地址还是指向指针的指针。这只会使 C 编程除了用底层汇编语言写下来之外什么都没有——我们将不得不处理原始地址。然后想一想,要记住需要取消引用多少次,您需要维护一些元数据以及该变量 - 正是编译器通过保留类型信息 int*int** 存储的内容。

    【讨论】:

    • @Jean-FrançoisFabre.:我编辑了...感谢之前的评论。
    • @coderredoc thnx 现在说得通了。
    • @shobhit.:感谢您的反馈。
    • @Jean-FrançoisFabre:不能保证。在 x86 和其他一些商品硬件上确实如此,但也有一些奇怪的地方,不同的指针类型确实具有不同的大小。
    【解决方案3】:

    在上面的第 2 行和第 3 行中,变量指针都指向某个地址

    没错。 b 的地址为(指向)ac 的地址为b

    我想你要问的是,由于b 的类型为“指向某物的指针”,而c 的类型为“指向某物的指针”,那么bc 将具有非常类似的表示并将使用非常相似的代码。这是真的……但是。

    C 中的指针运算不仅仅是生成的机器语言。我们不仅仅关心b 是一个“指向某物的指针”,因为我们需要知道如果我们取消引用它会产生的值的类型。因为b实际上是一个指向int的指针,那么*b(也就是b的“内容”,当我们取消引用b时得到的值)就是一个指向诠释。另一方面,*c 是指向 int 的指针。所以bc同一类型。

    如果您真的想这样做,实际上您可以利用您的信念,即所有指向指针的指针都具有基本相同的类型,方法是将void ** 用作“指向指针的通用指针”类型.但是您必须使用一些额外的显式强制转换:

    int integer = 5;
    int *a = &integer;
    void **b, **c;       // "generic pointer to pointer"
    
    b = (void **)&a;
    c = (void **)&b;
    
    printf("the int: %d\n", integer);
    printf("via pointer: %d\n", *a);
    printf("via 2-level pointer: %d\n", **(int **)b);
    printf("via 3-level pointer: %d\n", ***(int ***)c);
    

    但是这段代码更难写、更难阅读、更难思考。而且它也不是严格可移植的,也不符合标准。

    (您可能会问,“实际上,它不能在哪种机器上工作?”,我承认我不能说出一个名字;它可以在我们目前认为实用和传统的任何机器上正常工作。但是代码仍然更难写、更难阅读、更难思考。)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-01-29
      • 2010-09-15
      • 1970-01-01
      • 2016-11-20
      相关资源
      最近更新 更多