什么是"数组/指针等价的现代术语"?

时间:2018-02-19 14:33:28

标签: c arrays pointers terminology

几乎每个读这篇文章的人都熟悉这三个关于C的关键事实:

  1. 当你在表达式中提到数组的名称时,它会(大部分时间)评估指向数组第一个元素的指针。
  2. "数组下标" operator []与指针一样适用于指针。
  3. 似乎是数组的函数参数实际上声明了一个指针。
  4. 这三个事实绝对是C中数组和指针处理的核心。它们甚至不是三个独立的事实;它们是一个中心概念的相互关联的方面。如果不理解这个概念,就不可能正确地进行相当基本的C编程。

    我今天的问题很简单,这个概念的名称是什么?

    我认为我是老式的,但我总是称之为" C"中的数组和指针之间的等价,或者#34;数组/指针等效&#34 ;简而言之。但我已经知道你几乎无法在SO上说出那些话;他们几乎是禁忌。

    这似乎是一个抽象的或哲学的问题,所以更具体地说,我正在寻找的是一个简单的名词或名词短语,我可以在句子中使用"是的,由于_____,数组下标可以被认为是指针算法的语法糖",作为答案,比如this question

    (但请注意,我正在寻找该问题的答案,或者问题的答案"“等同”这个词有什么问题&# 39;?"。是的,我知道,它可能误导学习者想象数组和指针在某种程度上是相同的。当我写this FAQ list entry时,我确实有这种困惑。)

11 个答案:

答案 0 :(得分:26)

  
      
  1. "数组下标" operator []和指针一样适用于指针。
  2.   

不,实际上它只适用于指针。每当在表达式中键入[]时,总会得到指向第一个元素的指针。由于arr[i]必须等同于*(arr + i),因此保证会发生这种情况。前者是"语法糖"对于后者。

  
      
  1. 似乎是数组的函数参数实际上声明了一个指针。
  2.   

这实际上是一种特殊情况,称为"数组调整",其中编译器隐式地将数组类型的函数参数的声明更改为指向第一个元素的指针。理由肯定是使功能与'#34;阵列衰减"表达式,但C标准将术语分开。

这两种情况,表达式和函数参数通常被非正式地称为"数组衰减"。虽然有时这只用于表达式而不用于函数参数。我不认为这个术语有单一,一致的用法。 "阵列衰变"是我认为最好的,尽管C标准在任何地方都不使用该术语。

(我不喜欢术语"等价",因为一个数组可以变成一个指针,但不是相反的方式。确实总是有无数的初学者提出混淆的信念,比如& #34;数组和指针是相同的东西"。调用它们"等效的"并没有完全帮助。)

答案 1 :(得分:13)

C标准没有一个字。它在6.3.2.1p3中定义行为(1)时使用“转换”一词,在6.5.2.1p2中定义行为(2)时使用“等效”,在6.7.6.3p7中定义行为(3)时使用“调整”。

我是老式的,并且认为调用这个“数组/指针等价”没有任何问题,只要在上下文中你明白你正在讨论表达式(1)发生或函数声明在哪里(3) ) 发生。然而,对于那些不喜欢“等价”的人来说,一个更可口的术语可能是“数组到指针的转换”,因为我认为这会使人们最常混淆(1)。

答案 2 :(得分:9)

我会选择数组衰减这个术语。这个词与它的建议很顺利。 C标准在这种情况下并没有说出来,是的,第一天我听到了我在标准中搜索它的术语,但是我找不到它(所以它有点令人困惑。谁创造了这个术语等)。另外,由于 &#34,大多数情况下阵列都会被转换为指针" ... - 但这不是一个名词。但这不会让任何误解发生。标准本身称它为"转换"。

大多数时候我试着说很长一段时间然后把这个词("数组衰减")放在括号中。事实上有些答案我甚至没有提及它,只是按照标准的 转换成指针 的话。

答案 3 :(得分:5)

我建议“阵列到指针衰减”是一个合理的简写,因为“衰变” 在引用类型转换方面是常见的术语,具有先例 C FAQ中的其他地方:Question 6.12

  

问:由于数组引用会衰减为指针,如果arr是一个数组,   arr和& arr之间有什么区别?

包括这个的“衰变”的扩展技术含义 自C ++ 11以来被采纳为C ++标准库术语:std::decay

答案 4 :(得分:5)

所提到的三个概念没有单一的名称,但我认为将它们描述为暗示任何类型的“等价”是适得其反的,至少在描述“现代”C时。虽然阵列衰减的结果通常表现得很好与指针类似,C99指定由数组衰减产生的指针不需要以与通过其他方式实现的指针相同的方式运行。给出:

char fetch_byte_at(void *p, int x) { return ((char*)p)[x]; }

struct {char arr[5][7];} s;
char test1(int x) { return s.arr[0][x]; }
char test2(int x) { return fetch_byte_at(&s, x); }

标准没有直接指明为什么s.arr[0]中使用的指针值test1不应等于从((char*)(void*)s)调用fetch_byte_at时使用的指针值test2的原因test2。但是,它确实同时暗示s应该能够读出x的所有字节[暗示它应该可预测地使用s.arr[0][x]的值至少达到34],同时说x仅对[]最高为6的值有意义。

虽然标准中的任何内容都不会单独与前两个点相矛盾,但两者都不可能成立。数组衰减的结果不是指向数组第一个元素的“普通”指针,或者将.linkblock li a:after {content:" |"; white-space: pre;} 运算符应用于数组与将其应用于指针有不同的语义。虽然目前还不清楚C99中#1和#2中的哪一个已被无效,但它们不再在现代C中形成任何“等价”。

如果你认识到传统C和“现代”C之间的区别,那么为使前者有用的事物建立术语可能是有用的。然而,这些事情超出了你提到的要点。不幸的是,我不知道这些事情的任何标准术语,并且当它不再支持所涉及的概念时,不会寻求标准提供这样的术语。

答案 5 :(得分:2)

谢谢大家。我正在使用这个"回答"总结一下人们给出的答案以及我对它们的评价,而不是一个正确的答案,我希望任何人都可以投票或任何事情。

很多人都认真思考这个问题,我很欣赏。但在这一点上,我唯一可以得出的结论是,至少今天我没有回答我的想法。

很多人建议"阵列衰减",这是一个非常好的镜头,但它对我不起作用。它主要指的是事实1,也许是事实3,如原始问题所列,但事实并非如此2.你不能说"是的,由于数组衰减,数组下标可以被认为是语法糖用于指针算术。" (或者至少,你不能说如果你的意图要明确和有启发性。)你必须说出类似的事情,因为阵列衰减和指针运算的方式是为了与它保持一致,数组下标可以被认为是指针算法的语法糖,而且,它完全是一个不同的鱼。

虽然我没有明确说出来,但我一直在寻找一个共同的,广泛的,被接受的用语,尽管没有要求它涉及标准中实际使用的单词。考虑到每个人都参与了一定程度的猜测,而没有人咳出这样一个术语,并且"那么......?",我得出的结论是,没有一个术语可以广泛用于三个相关事实背后的概念。 (除了"等价",这是排除的。)

许多回答者和评论员以各种方式说这个(没有一个答案)。我会在此基础上继续接受Lundin的答案,因为其他人似乎最喜欢它。

我,继续我可能会尝试使用"数组和指针之间的对应关系C"并看看它是否抓住了。数组和指针与男人和女人一样不同,他们实际上相距甚远,但他们经常交换信件。 : - )

答案 6 :(得分:1)

这是一个微妙的问题。在浏览英语词库和词典后,我发现相似一词可能适合您的上下文。

通过牛津大学的在线词典定义,单词Similar被定义为:

  

外观,性格或数量相似,但不相同。

和单词Similitude为:

  

与某事物相似的品质或状态。

由于数组和指针不相同,但有时会被视为相似,我们可能会说:

  

是的,由于Array / Pointer similitude ,数组下标可以被认为是指针算术的语法糖“

答案 7 :(得分:1)

  

这似乎是一个抽象或哲学问题,所以更具体地说,我正在寻找的是一个简单的名词或名词短语我可以使用句子“是的,由于_____,数组订阅可以是被认为是指针算术的句法糖“,回答这个问题。

你正在寻找的短语是“是的,由于数组订阅是引擎盖下的指针算术,数组订阅可以被认为是指针算术的语法糖。”

这当然是愚蠢的,因为说数组订阅的原因是指针算术的语法糖是因为它正是它的原因,它不需要进一步解释,除非你说这个人要么没有知道什么'数组订阅','指针算术'或'语法糖'的意思。这并不是说编译器不知道两者的区别(因为它是负责你因此得到的所有语法糖的人)。

同样的问题可以提出任何语言为我们所做的一切,我们可以通过使用更多的低级指令自己做,因此可以使用多个术语来引用它只会改变句法的数量用糖。重点不是假装它们不同(它们总是在路上,但这不是重点),而是为了使编程更容易(只需考虑编写代码而不使用[]运算符作为指针算术的语法糖,并且你很快意识到它存在的原因 - 它不是因为它是不同的,而是因为它更容易来编写,阅读和管理)。

  

(但请注意,我不是在寻找这个问题的答案,也不是为了回答“'等同'这个词有什么问题?”。是的,我知道,这可能会误导学习者想象数组和指针在某种程度上是相同的。当我写这个FAQ列表条目时,我确实记得这一点。)

你的问题似乎是“数组指针等价的现代术语是什么,在数组订阅只是指针算术的语法糖?”

答案是:

    使用[]运算符索引数组时,
  1. “数组预订”。
  2. “指针算术”,当您手动移动指针时(与使用[]运算符相反)。您可能也觉得使用这个术语来表示您对[]运算符的值所做的任何数学运算,但是你并没有真正在那里做指针算术,而是“计算索引”,这是句法的术语。自动考虑内存中对象大小的糖(再次,不同,只是更容易编写,阅读和管理,因此:语法糖)。

答案 8 :(得分:0)

标准使用术语转换为数组和指针等效仍然比数组衰减更好地保持指针。标准提到这个术语没有,但它只是程序员之间的相互理解,当它出现在数组和指针的上下文中时,它被认为是数组和指针等价。而指针和数组的等价意味着:pointer arithmetic and array indexing [that] are equivalent in C, pointers and arrays are different.

答案 9 :(得分:0)

我同意“指针/数组等效”或“数组衰减”(插入指针)之类的说法不准确,并且可能会引起误解。

我建议以下内容:

使用[]运算符并使用索引进入数组具有等效的指针算术表达式。但是,指针和数组之间没有等效项:我可以很高兴地更改指针的值(内容),也许可以保存一个单独的迭代计数器,但是我不能使用“衰减”数组来实现;它是不可变的,并且在某些方面表现出与C ++引用相似的行为。

英语中的“去衰变”和“转化”这两个动词总是表示原始词在此过程中发生了变化。使用数组名称或使用一元'&'运算符时,请勿更改其操作数。

因此,诸如“产生指针”或“创建指针”之类的表达式将更准确。这反映在以下事实中:在两种情况下,所得的指针都是临时的(通常)位于GP寄存器中CPU,并且无法分配给它。

至少这是我的理解,看着反汇编似乎可以证实这一点。

答案 10 :(得分:-3)

如果您指的是类型转换,为什么不使用术语“投射”?已经通常理解为暗示编译器被强制处理两个相关但不相同的类型,就好像它们是期望的类型一样。是的,这里有一个等价,但'casting'用作表示类型不是字面上相同的方式,但编译器应该将类型视为不同的类型,并且该过程对于编译器是可接受的,如向上转换为byte-> long

第二选择:“同义词”