【问题标题】:Are arrays in C a syntactic sugar for pointers?C 中的数组是指针的语法糖吗?
【发布时间】:2018-07-28 19:52:38
【问题描述】:

我们来看看下面的代码:

int arr[n];
// s.t. i<n
arr[i] = 12;
// s.t. i<n 
*(arr + i) = 12;

arr[i]*(arr+ i) 的语法糖吗?

【问题讨论】:

  • 对你的标题:不,对正文中的问题:是的。
  • 您应该清楚索引数组和实际数组之间的区别。
  • 数组索引操作极有可能被称为“语法糖”。但是,数组本身绝对不是指针的语法糖。
  • +- - 的语法糖。去死那些懒惰的程序员!

标签: c syntactic-sugar


【解决方案1】:

严格来说,数组不是指针的语法糖。根据定义,“语法糖”是一种语言结构,它允许您编写更短/更清晰的等价于其他语言结构。指针和数组的情况不同。指针是包含某个值的内存地址的变量。不同的是,数组是包含这些值本身的变量。但是,C 的语法是以某种方式构建的,它允许您将指针视为数组第一个元素的地址并对其应用索引运算符。但我不会说这是语法糖,这是语言的基本语法。

【讨论】:

    【解决方案2】:

    是的,您可以使用 arr[i]/*(arr+i) 访问数组的元素。

    您甚至可以对数组指针使用增量操作。 *ptr = &arr, 指针++

    这意味着每次向数组指针添加整数或增量时,指针都会将(数据类型的大小)*i 添加到前一个指针。

    【讨论】:

      【解决方案3】:

      是的,arr[i]*(arr+i) 相同,*(i+arr)i[arr] 相同

      来自法比奥·图拉蒂的评论: 详情请见"Why is a[5] == 5[a]"

      【讨论】:

      【解决方案4】:

      是的,你可以说 - 数组下标访问 与使用 * 取消引用的指针访问相同。

      来自6.5.2.1p2C11标准N1570

      后缀表达式后跟方括号中的表达式[] 是数组对象元素的下标名称。 下标运算符[]的定义是E1[E2](*((E1)+(E2)))相同。由于适用于二进制+ 运算符的转换规则,如果E1 是一个数组对象(等效地,一个指向数组对象初始元素的指针)并且E2 是一个整数,E1[E2] 指定E2-E1 的第一个元素(从零开始计数)。

      绝不应该给你一个数组是指针的印象。有趣的是,当您应用 [] 时,数组会衰减为指向第一个元素的指针,并用于访问后续元素。

      数组对象是另一回事——在某些情况下,数组不会衰减为指针。它们不是语法糖——你可以考虑一个例子——

      int p[] = {1, 2 ,3};
      int *t = p;
      size_t sz1 = sizeof p;
      size_t sz2 = sizeof t;
      printf("%zu %zu\n", sz1, sz2);
      

      运行它,我会理解与您的问题更相关的内容。数组不能使用数组本身以外的东西来实现。数组访问与指针取消引用相同,但这并不意味着指针占据数组的位置,反之亦然。

      C 编程的关键外卖或红色药丸:

      数组是数组,指针是指针。它们是不同的东西。


      顺便说一句,如果sizeof 欺骗了你一点 - 不要担心有一个标准部分这么说。来自6.3.2.1p3

      除非它是 sizeof 运算符_Alignof 运算符或一元&amp; 运算符的操作数,或者是用于初始化数组的字符串字面量、表达式类型为 'array of type' 的表达式被转换为类型为 'pointer to type' 的表达式,该表达式指向数组对象的初始元素并且不是左值...

      当用作sizeof 的操作数时,数组不会转换为指针。就是这样。这就是为什么你会得到你在早期代码 sn-p 中得到的东西。

      【讨论】:

        【解决方案5】:

        绝对不是!要看到这一点,只需在您的示例中用指针替换数组:

        int *arr;
        // s.t. i<n
        arr[i] = 12;
        // s.t. i<n 
        *(arr + i) = 12;
        

        这编译得很好,但它是未定义的行为。它不能保证工作。事实上,没有这个程序可能会被认为是编译器中的错误。

        数组是数组;包含数据的类型。指针指向数据所在的位置。指针不包含实际数据,而数组包含。

        一些情况下,数组名称的行为方式与指针相同。这不会使两者相同。

        例如,看看这个:

        int arr[12];
        int ptr;
        
        ptr = arr; // Legal
        printf("array size %ld\n", sizeof(arr)); // Usually prints 12*4=48
        printf("pointer size %ld\n", sizeof(ptr)); // Depending on your arch, will likely print either 4 or 8.
        

        【讨论】:

        • 这一切都归功于 Dennis Ritchie 在设计 C 语言特性时表现出色:'我知道,我将允许数组参数作为指针自动传递,而不需要 '&' 地址运算符' 节省了一次字符输入,导致数十年的混乱:(“嘿,参数是数组,参数是指针,所以数组和指针必须是同一个东西”。
        • 这与问题的关系有多大?
        • 问题不在于“数组是否为指针”。它是关于下标运算符和取消引用运算符的等价。
        • @MartinJames 我知道你在开玩笑说 dmr 是“高”的,但是 C 中数组和指针的实际历史要微妙得多。如果好奇,请参阅The Development of the C Language。 (尤其参见“空方括号 [...] 是活化石”这句话。)
        • @Gerhardh 问题的主体是关于下标,但问题本身是关于数组和指针的。我阅读了正文(我认为以其他方式阅读它是不合理的)作为实际问题的一个例子。人们总是混淆数组和指针。
        猜你喜欢
        • 2017-12-21
        • 1970-01-01
        • 2020-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-28
        • 1970-01-01
        • 2020-03-11
        相关资源
        最近更新 更多