提问人:Zenxn 提问时间:7/1/2023 最后编辑:Vlad from MoscowZenxn 更新时间:7/3/2023 访问量:59
C 星号运算符使用
C Asterisk Operator Using
问:
我试图学习指针,但我在第二行感到困惑,有人可以解释它是如何工作的吗?
如果我们假设“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 而不是该地址的整数值?提前致谢
答:
请记住,对于任何数组或指针和索引,表达式与 完全相同。a
i
a[i]
*(a + i)
如果我们将其应用于您的示例,则 是指向数组的第二个元素的指针。这与 相同。a + 1
a
&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]
int
int (*)[3]
另一个指针 , 是指向单个元素的指针,因此类型为 。&a[1][0]
int
int *
表达式中使用的数组指示符(极少数例外)将转换为指向其第一个元素的指针。
来自 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 + 1
a
int ( * )[3]
a + 1
int[3]
a + 1
sizeof( int[3] )
sizeof( int )
4
3 * sizeof( int )
12
对于这个表达式,然后取消引用表达式,它会生成 类型数组的第二个元素。在数组指示符的调用中用作表达式,该类型再次被隐式转换为指向其第一个元素的类型的指针。第二个“行”的第一个元素和第二个“行”本身的地址彼此相等,尽管它们具有不同的类型。*( a + 1 )
a + 1
int[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 *
评论
*
10C
0x10C
112
int a[1][1][1][1][1][1][1][1][1] = {1};
*