代码之家  ›  专栏  ›  技术社区  ›  Zenxn

C星号运算符使用

  •  0
  • Zenxn  · 技术社区  · 1 年前

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

    如果我们假设“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而不是该地址处的整数值?提前感谢

    2 回复  |  直到 1 年前
        1
  •  1
  •   Some programmer dude    1 年前

    请记住,对于任何数组或指针 a 和索引 i ,表达式 a[i] 确切地 与…一样 *(a + i)

    如果我们将其应用于您的示例,那么 a + 1 是指向数组的第二个元素的指针 。和 &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 *

        2
  •  1
  •   Vlad from Moscow    1 年前

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

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

    3除非它是sizeof运算符或一元& 运算符,或者是用于初始化数组的字符串文字 具有类型为的类型数组的表达式转换为 类型为指针的表达式,指向指向初始值的类型 元素,而不是左值。如果数组对象 具有寄存器存储类,行为未定义。

    在提供的代码片段中,数组 a 被声明为

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

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

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

    例如 输出函数

    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 *