C 星号运算符使用

C Asterisk Operator Using

提问人:Zenxn 提问时间:7/1/2023 最后编辑:Vlad from MoscowZenxn 更新时间:7/3/2023 访问量:59

问:

我试图学习指针,但我在第二行感到困惑,有人可以解释它是如何工作的吗?

如果我们假设“A”基址是 100

  int a[3][3] = {6, 2, 5, 0, 1, 3, 4, 9, 8};
  printf("%p \n", a+1); // output is gonna be 112
  printf("%p \n", *(a+1));// still output is gonna be 112
    

指针算术和取消引用运算符 (*) 在第二行代码中是如何工作的?为什么printf语句printf(“%p \n”, *(a+1));输出内存地址 112 而不是该地址的整数值?提前致谢

c 指针 隐式转换 指针算术 的大小

评论

0赞 Scott Hunter 7/1/2023
第二行(中间的那行)没有。*
0赞 Tolga 7/1/2023
@ScottHunter 实际上确实如此,我的意思是 printf *(a+1) 中的那部分
0赞 Weather Vane 7/1/2023
我认为输出会或不会.10C0x10C112
0赞 yvs2014 7/1/2023
与编写然后用 a、a[0]、a[0][0]、a[0][0][0]、...、...引用相同的指针的方式相同,但演示它更直接一些:)int a[1][1][1][1][1][1][1][1][1] = {1};
0赞 Scott Hunter 7/1/2023
位于第三行。*

答:

2赞 Some programmer dude 7/1/2023 #1

请记住,对于任何数组或指针和索引,表达式与 完全相同。aia[i]*(a + i)

如果我们将其应用于您的示例,则 是指向数组的第二个元素的指针。这与 相同。a + 1a&a[1]

并且是 ,它是一个数组,因此将衰减为指向其第一个元素的指针,这意味着这与 相同。*(a + 1)a[1]a[1]&a[1][0]

虽然这两个指针和 具有不同的类型,但它们都指向同一位置。一旦我们把它画出来,就很容易看到,并添加了指针:&a[1]&a[1][0]

+---------+---------+---------+---------+--------------------+
| a[0][0] | a[0][1] | a[0][2] | a[1][0] | ... (not relevant) |
+---------+---------+---------+---------+--------------------+
                              ^
                              |- &a[1]
                              |- &a[1][0]

要扩展不同的类型,是指向三个元素的数组的指针,或 .&a[1]intint (*)[3]

另一个指针 , 是指向单个元素的指针,因此类型为 。&a[1][0]intint *

1赞 Vlad from Moscow 7/1/2023 #2

表达式中使用的数组指示符(极少数例外)将转换为指向其第一个元素的指针。

来自 C 标准(6.3.2.1 左值、数组和函数指示符)

3 除非它是 sizeof 运算符的操作数或一元 & 运算符,或者是用于初始化数组的字符串文字,一个 类型为 ''array of type'' 的表达式将转换为 类型为“指向类型”的表达式,指向初始 元素,并且不是左值。如果数组对象 具有寄存器存储类,则行为未定义。

在提供的代码片段中,数组声明如下a

int a[3][3] = {6, 2, 5, 0, 1, 3, 4, 9, 8};

因此,在表达式中,数组指示符被转换为 类型的指针。也就是说,它是指向数组的第一个元素(“row”)的指针。因此,表达式指向数组类型的第二个元素(“row”)。表达式生成的地址值与数组第一个元素的地址值不同。如果等于,则地址之间的差值,如果等于 。a + 1aint ( * )[3]a + 1int[3]a + 1sizeof( int[3] )sizeof( int )43 * sizeof( int )12

对于这个表达式,然后取消引用表达式,它会生成 类型数组的第二个元素。在数组指示符的调用中用作表达式,该类型再次被隐式转换为指向其第一个元素的类型的指针。第二个“行”的第一个元素和第二个“行”本身的地址彼此相等,尽管它们具有不同的类型。*( a + 1 )a + 1int[3]printf*( a + 1 )int[3]int *

例如,这些调用:printf

printf( "Address of &a = %p\n", ( void * )&a );
printf( "Address of a = %p\n", ( void * )a );
printf( "Address of &a[0] = %p\n", ( void * )&a[0] );
printf( "Address of a[0] = %p\n", ( void * )a[0] );
printf( "Address of &a[0][0] = %p\n", ( void * )&a[0][0] );

将输出相同的地址值,尽管使用的表达式类型不同。表达式的类型(考虑到数组指示符到指向其第一个元素的指针的隐式转换)是(从上到下):

&a       -> int ( * )[3][3]
a        -> int ( * )[3]
&a[0]    -> int ( * )[3]
a[0]     -> int *
&a[0][0] -> int *