【问题标题】:Address of an address in C. Valid or not? [duplicate]C中地址的地址。有效与否? [复制]
【发布时间】:2021-08-13 14:24:41
【问题描述】:

我以为我理解 c 和指针,但只是在调试别人的代码,我认为我认为不应该工作,但确实做到了。 作为一个(粗略的)例子......

void clear_buffer(char* buff, int len)
{
    while(len)
    {
        *buff++ = ' ';
        len--;
    }
}

main()
{
    char buffer[10];

    clear_buffer(&buffer,10);   // 1. what I found, it still works...
    clear_buffer(buffer,10);    // 2. what I would have wrote
}

让我吃惊的是,上面两个调用的工作方式完全相同。第一个给出编译器警告(不兼容的指针类型),但它仍然可以正确构建和运行。 所以我的问题是:这是 C 中的预期行为,还是只是我使用的编译器很聪明并修复了错误? fwiw,这是使用 microchip xc16 编译器。

【问题讨论】:

  • buffer 是 char 数组类型。当您将数组传递给采用指针的函数时,数组会隐式衰减。它是有效的,但我宁愿通过 &buffer[0] 代替。
  • 澄清重复:一旦clear_buffer函数接收到地址,它将被解释为char*无论参数类型是什么。由于数组的地址与其第一个元素的地址相同,因此您的程序可以工作。
  • "但它仍然可以正确构建和运行" 请参阅What must a C compiler do when it finds an error?

标签: arrays c pointers implicit-conversion addressof


【解决方案1】:

这个电话

clear_buffer(&buffer,10);

不正确,编译器将发出错误消息。

表达式&buffer的类型是char ( * )[10],而对应的函数参数的类型是char *,并且没有从一种类型到另一种类型的隐式转换。

程序按预期运行,因为表达式&bufferbuffer的值相同:尽管表达式的类型不同,但它是数组占用的内存范围的地址。

考虑另一个例子。这是一个演示程序

#include <stdio.h>

int main(void) 
{
    struct A
    {
        int x;
    } a = { 10 };
    
    printf( "&a   = %p\n", ( void * )&a );
    printf( "&a.x = %p\n", ( void * )&a.x );

    return 0;
}

程序输出是

&a   = 0x7ffef64abb84
&a.x = 0x7ffef64abb84

如您所见,尽管表达式 &amp;a&amp;a.x 的类型不同,但程序输出的地址相同。

同样的情况也发生在您的程序中。整个数组的地址等于它的第一个元素的地址,尽管整个数组和它的元素的类型不同。

实际上,在您的函数中,您将指向char ( * )[10] 类型的整个数组的指针重新解释为指向char * 类型的第一个数组元素的指针。

【讨论】:

  • 谢谢,这个例子真的很有帮助。
【解决方案2】:

在表达式clear_buffer(buffer, 10) 中,buffer 被转换为指向其第一个元素的指针,因此等价于&amp;buffer[0]。在表达式clear_buffer(&amp;buffer, 10) 中,buffer 不会转换为指向其第一个元素的指针,因为它是&amp; 地址运算符的操作数。这是数组衰减为表达式中的指针的规则的例外之一。 (该规则的另一个例外是 sizeof 运算符。)

数组的第一个元素与数组本身的地址相同,因此&amp;buffer&amp;buffer[0] 具有相同的地址,但类型不同。 &amp;buffer 的类型为 char (*)[10](指向 char 的数组 [10] 的指针),&amp;buffer[0] 的类型为 char *

警告是由于调用clear_buffer(&amp;buffer, 10)中的指针类型不匹配造成的。

【讨论】:

  • 谢谢,现在一切都说得通了。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-22
  • 1970-01-01
  • 1970-01-01
  • 2013-04-30
  • 2019-09-28
  • 2011-09-09
  • 2021-09-01
相关资源
最近更新 更多