c - 为什么 *num 不显示第零个元素值?

标签 c arrays pointers address-operator

在此代码中:

#include<stdio.h>
  int main()
  {
    int num[2] = {20, 30};
    printf("%d", num);
    printf("%d", &num[0]);
    return 0;
  }

据我所知,两个printf语句都会打印num中第一个元素的地址,因为在第一个语句中,num是一个指向int的指针.

但是如果 num 是一个指针,那么它也应该有任何地址,但在打印其地址时(使用 printf("%d", &num)),它是显示第一个元素的地址。

在二维数组中,整个事情也变得困惑:

#include<stdio.h>
int main(void)
{
    int num[ ] [2]={20,30,40,50};
    printf("%d",*num);
    return 0;
}

该程序正在打印第零个元素的地址,即num[0][0]的地址。但它为什么要这样做呢?为什么它不打印存储在其中的值,因为它们都有相同的地址(num,num[0]num[0][0])?

最佳答案

要事第一;数组变量不是指针;它们存储任何东西的地址。

对于诸如这样的声明

T a[N];

内存将布局为

         +---+
   a[0]: |   |
         +---+
   a[1]: |   |
         +---+
          ...
         +---+
 a[N-1]: |   |
         +---+

对于 2D MxN 数组,它看起来像

              +---+
     a[0][0]: |   |
              +---+
     a[0][1]: |   |
              +---+
               ...
              +---+
   a[0][N-1]: |   |
              +---+
     a[1][0]: |   |
              +---+
     a[1][1]: |   |
              +---+
               ...
              +---+
 a[M-1][N-1]: |   |
              +---+

对于 3D 和更高维的数组,该模式应该是明显的。

如您所见,没有为包含第一个元素的地址的单独变量a预留存储空间;相反,C 语言中有一条规则,类型为“T 的 N 元素数组”的表达式将被转换(“衰变”) ") 到“指向 T”类型的表达式,表达式的值将是数组第一个元素的地址,除非当数组表达式为以下之一:

  • sizeof 运算符的操作数
  • 一元 & 运算符的操作数
  • _Alignof 运算符的操作数(C99 及更高版本)
  • 用于在声明中初始化数组的字符串文字

因此给出声明

T a[N];

以下所有内容均正确:

Expression         Type        Decays to         Value
----------         ----        ---------         -----
         a         T [N]       T *               address of first element, &a[0]
        *a         T           n/a               value stored in first element
        &a         T (*)[N]    n/a               address of the array, which is 
                                                   the same as the address of the
                                                   first element of the array
      a[i]         T           n/a               value stored in the i'th element
     &a[i]         T *         n/a               address of the i'th element
  sizeof a         size_t      n/a               total number of bytes used by the
                                                   array
 sizeof *a         size_t      n/a               total number of bytes used by the
                                                   first element of the array
 sizeof &a         size_t      n/a               total number of bytes used by a 
                                                   pointer to the array 

表达式a的类型为“T的N元素数组”;它不是一元 &sizeof 运算符的操作数,因此它被转换为指向数组第一个元素的指针,amd 它的值是该元素的地址元素。

表达式&a的类型为“指向T的N元素数组的指针”;由于 a 是一元 & 运算符的操作数,因此不应用上面的转换规则(这就是表达式具有类型 T (*)[N ] 而不是 T **)。但是,由于数组的地址与数组第一个元素的地址相同,因此它产生与表达式 a 相同的

表达式&a[0]的类型为“指向T的指针”,并显式指向数组的第一个元素。同样,该值将与前两个表达式相同。

对于二维数组

T a[M][N];

以下所有内容均正确:

Expression         Type        Decays to         Value
----------         ----        ---------         -----
         a         T [M][N]    T (*)[N]          address of first subarray, a[0]
        *a         T [N]       T *               address pf first subarray, a[0]
        &a         T (*)[M][N] n/a               address of the array, which is 
                                                   the same as the address of the
                                                   first subarray, which is the same
                                                   as the address of the first element
                                                   of the first subarray.
      a[i]         T [N]       T *               address of first element of i'th
                                                   subarray
     *a[i]         T           n/a               value of first element of i'th subarray
     &a[i]         T (*)[N]    n/a               address of the i'th subarray
  sizeof a         size_t      n/a               total number of bytes used by the
                                                   array
 sizeof *a         size_t      n/a               total number of bytes used by the
                                                   first subarray
 sizeof &a         size_t      n/a               total number of bytes used by a 
                                                   pointer to the array 

最后一点:要打印指针值,请使用 %p 转换说明符并将参数强制转换为 (void *) (这几乎是唯一一次将指针显式转换为 void * 被认为是正确的):

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

编辑

回答评论中的问题:

num,num[] and num[][] are all different thing. There types are different.Here num decays and became pointer to a pointer and num[] decays and became pointer to int and num[][] is a int. Right?

不完全是。

假设声明如下

int arr[10][10];

然后表达式arr将衰减为类型int (*)[10](指向int的10个元素数组的指针),不是 int ** ;再次引用上表。否则你是对的; arr[i] 将衰减为 int * 类型,并且 arr[i][j] 将具有 int 类型>。

T 的 N 元素数组”类型的表达式衰减为“指向 T 的指针”类型;如果 T 是数组类型,则结果是“指向数组的指针”,而不是“指向指针的指针”。

关于c - 为什么 *num 不显示第零个元素值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26588906/

相关文章:

更改 char* 数组中元素的地址? C

c - 什么时候值得在结构定义中使用指向结构的指针?

c - 通过引用将动态创建和填充结构数组的函数传递结构

在C中将多维数组转换为一维

javascript - 使用 jquery 从 div 中拆分文本

c - 意外的 C 字符串定义行为

c - 数组指针作为参数传递给其他函数时会更改值

c - 如何限制用户或应用程序使用大页面支持?

python - SWIG 和 Mingw-64 与 Python 一起使用……不是有效的 Win32 应用程序

ruby - 如何将字符串切成对