"array/pointer equivalence" 的现代术语是什么?
What's a modern term for "array/pointer equivalence"?
几乎所有阅读本文的人都可能熟悉关于 C 的这三个关键事实:
- 当您在表达式中提及数组名称时,它的计算结果(大多数情况下)是指向数组第一个元素的指针。
- "array subscripting" 运算符
[]
对指针的作用与对数组的作用一样好。
- 看似数组的函数参数,其实声明的是指针
这三个事实绝对是 C 中数组和指针处理的核心。它们甚至不是三个独立的事实;它们是一个中心概念的相互关联的方面。如果没有对这个概念的正确理解,即使是相当基本的 C 编程也是不可能的。
我今天的问题很简单,这个概念的名称是什么?
我以为我是守旧的,但我一直称它为"The equivalence between arrays and pointers in C",或简称为"array/pointer equivalence"。但是我了解到您几乎不能在 SO 上说这些话;他们几乎是禁忌。
这似乎是一个抽象或哲学问题,所以为了更具体地构建它,我正在寻找的是一个简单的名词或名词短语,我可以在句子 "Yes, due to _____, array subscripting can be thought of as syntactic sugar for pointer arithmetic" 中使用,作为答案比如说,.
(但请注意,我不是寻找那个问题的答案,或者"What's wrong with the word 'equivalence'?"这个问题的答案。是的,我知道,它可能会误导学习者开始想象数组和指针在某种程度上是相同的。我在写 this FAQ list entry 时确实有这种困惑。)
C 标准对此没有一个词。它在 6.3.2.1p3 中定义行为 (1) 时使用 "conversion",在 6.5.2.1p2 中定义行为 (2) 时使用 "equivalent",在定义行为 (3) 时使用 "adjustment"在 6.7.6.3p7.
我是 old-fashioned,并且不认为调用这个 "array/pointer equivalence" 有什么问题,前提是在上下文中清楚地表明您正在谈论发生 (1) 的表达式或函数声明其中 (3) 发生。然而,对于不喜欢 "equivalence" 的人来说,一个更可口的术语可能是 "array-to-pointer conversion",因为我认为这在 (1) 时最容易让人感到困惑。
我会选择数组衰减这个术语。该术语与它的含义相得益彰。 C 标准在这种情况下并没有说明它,是的,第一天我听到这个术语,我去标准中搜索它,但我找不到它(所以关于谁创造了这个术语等有点令人困惑)。也可以写为 "most scenarios array is converted into pointer"... - 不,这不是一个名词。但这并不是让任何误解发生。标准本身称其为 "conversion"。
大多数时候我会尽量说得长一点,然后把 ("array decaying") 这个词放在括号里。事实上,有些答案我什至没有提到它,只是按照标准的话 conversion into pointer。
我建议 "array-to-pointer decay" 是合理的 shorthand,因为 "decay"
是指类型转换的俗语,有先例
C FAQ 的其他地方:Question 6.12:
Q: Since array references decay into pointers, if arr is an array,
what's the difference between arr and &arr?
"decay" 的扩展技术含义包括这个
自 C++11 起采用 C++ 标准库命名法:std::decay
标准使用术语转换为。 数组和指针等价 仍然优于 数组 衰减 到指针 。标准没有在任何地方提到这个术语,但它只是程序员之间的相互理解,当它出现在数组和指针的上下文中时,它被认为是数组和指针等价的。而指针和数组等价的意思是:pointer arithmetic and array indexing [that] are equivalent in C, pointers and arrays are different.。
- The "array subscripting" operator [] works just as well for pointers as it does for arrays.
不,实际上 。每当您在表达式中键入 []
时,您总会得到一个指向第一个元素的指针。这肯定会发生,因为 arr[i]
必须等同于 *(arr + i)
。前者对后者来说是"syntactic sugar"。
- A function parameter that seems to be an array actually declares a pointer.
这实际上是一种特殊情况,简称"array adjustment",编译器隐式地将数组类型的函数参数声明更改为指向第一个元素的指针。基本原理肯定是使函数与表达式的 "array decay" 兼容,但 C 标准将术语分开。
这两种情况,表达式和函数参数,通常被非正式地称为 "array decay"。尽管有时这仅用于表达式而不用于函数参数。我不认为存在单一、一致的术语用法。 "Array decay" 是我认为最好的,尽管 C 标准没有在任何地方使用该术语。
(我不喜欢"equivalence"这个词,因为数组可以变成指针,但反过来不行。确实总是有无数的初学者想出"arrays and pointers are the same thing"这样的困惑信念。称他们为 "equivalent" 并没有什么帮助。)
没有为提到的三个概念指定一个名称,但我认为将它们描述为暗示任何类型的 "equivalence" 是 counter-productive,至少在描述 "modern" 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); }
标准没有直接说明为什么 test1
中使用的指针值 s.arr[0]
不应该等同于 fetch_byte_at
时使用的指针值 ((char*)(void*)s)
来自 test2
。然而,它确实同时暗示 test2
应该能够读出 s
的所有字节 [暗示它应该可以预测地使用 x
的值至少达到 34] 而说 s.arr[0][x]
只对 x
到 6 的值有意义。
虽然标准中的任何内容都不会与您的前两点中的任何一个相矛盾,但不可能两者都成立。数组衰减的结果不是指向数组第一个元素的 "ordinary" 指针,或者将 []
运算符应用于数组与将其应用于指针具有不同的语义。虽然不清楚 #1 和 #2 中的哪一个已被 C99 无效,但它们在现代 C 中不再一起构成任何类型的 "equivalence"。
如果您认识到传统 C 和 "modern" C 之间的区别,那么为使前者有用的事物建立术语可能会很有用。但是,这些事情超出了您提到的要点。不幸的是,我不知道此类事物的任何标准术语,并且当它不再支持所涉及的概念时,我不会寻找标准来提供此类术语。
如果您指的是类型转换,为什么不使用术语“casting”?它已经被普遍理解为暗示编译器被强制处理两个相关但 not-the-same 类型,就好像它们是所需类型一样。是的,这里有一个等价关系,但是 'casting' 被用来表示类型在字面上并不相同,但编译器应该将一个类型视为不同的类型,并且编译器可以接受该过程, 像 up-casting for byte->long
第二选择:"Synonym"
这是一个微妙的问题。在浏览英语词库和词典后,我发现 similitude 一词可能适合您的上下文。
根据牛津在线词典的定义,Similar
这个词的定义是:
having a resemblance in appearance, character, or quantity, without being identical.
和单词 Similitude
为:
the quality or state of being similar to something.
由于数组和指针并不完全相同,但有时被相似对待,我们可能会说:
Yes, due to Array/Pointer similitude, array subscripting can be thought of as syntactic sugar for pointer arithmetic"
This may seem like an abstract or philosophical question, so to frame it more concretely, what I'm looking for is is a simple noun or noun phrase I could use the sentence "Yes, due to _____, array subscription can be thought of as syntactic sugar for pointer arithmetic", in answer to, say, this question.
您要查找的词组是"Yes, due to array subscribing being pointer arithmetic under the hood, array subscribing can be thought of as syntactic sugar for pointer arithmetic."
这当然是愚蠢的,因为说数组订阅是指针运算的语法糖的原因是因为它正是它的本质,它不需要进一步解释,除非你要对他们说这句话的人不知道 'array subscribing'、'pointer arithmetics' 或 'syntactic sugar' 是什么意思。这并不是说编译器不知道两者的区别(它知道是因为它负责你因此获得的所有语法糖)。
对于任何语言为我们所做的一切,我们都可以提出同样的问题,我们可以通过使用更多数量的低级指令来自己做,因此能够使用仅改变数量的多个术语来引用它使用的语法糖。重点不是假装它们是不同的(它们总是在路上,但这不是重点),而是使编程更容易(只需考虑编写代码而无需 [] 运算符作为指针算术的语法糖,并且您很快就会意识到它存在的原因 - 并不是因为它不同,而是因为它更容易编写、阅读和管理)。
(But please note that I am not looking for answers to that question, or for answers to the question "What's wrong with the word 'equivalence'?". Yes, I know, it can mislead learners into imagining that arrays and pointers are somehow the same. I did have that in mind when I wrote this FAQ list entry.)
你的问题好像是"What's a modern term for array pointer equivalence in the sense that array subscription is just syntactic sugar for pointer arithmetics?"
答案是:
- "Array subscription" 当您使用 [] 运算符索引数组时。
- "Pointer arithmetics" 当您手动移动指针时(与使用 [] 运算符相反)。您可能还想使用这个术语来表示您对输入 [] 运算符的值所做的任何数学运算,但您并不是真正在那里进行指针运算,而是 "calculating an index",这是语法术语自动为您考虑内存中对象的大小的糖分(同样,没有什么不同,只是更容易编写、阅读和管理,因此:语法糖分)。
谢谢大家。我正在使用这个 "answer" 来总结人们给出的答案和我对他们的评估,而不是作为一个正确的答案,我希望任何人都支持或任何东西。
很多人认真思考过这个问题,对此我表示赞赏。但在这一点上,我唯一可以得出的结论是,至少在今天,我想到的问题没有答案。
很多人建议 "array decay",这是一个非常好的镜头,但它不适合我。它主要指的是原始问题中列出的事实 1 和事实 3,但不是真正的事实 2。你不能说 "Yes, due to array decay, array subscripting can be thought of as syntactic sugar for pointer arithmetic." (或者至少,如果你的意图是清晰且有指导意义。)你必须说出类似 "Yes, due to array decay and the way pointer arithmetic is defined so as to be consistent with it, array subscripting can be thought of as syntactic sugar for pointer arithmetic" 的内容,这完全是另一回事。
虽然我没有这么明确地说,但我一直在寻找一个通用的、广泛的、被接受的术语,尽管没有要求它涉及标准中实际使用的词。并且鉴于没有人说出这样一个术语,鉴于每个人都进行了一定程度的猜测并且 "What about ...?",我得出结论,对于这三个相关事实背后的概念,没有一个被广泛使用的术语。 (除 "equivalence" 外,已排除。)
许多回答者和评论者以各种方式表达了这一点(没有一个答案)。我将继续并在此基础上接受 Lundin 的回答,因为其他人似乎最喜欢它。
我,以后我可能会尝试使用 "The correspondence between arrays and pointers in C" 看看它是否流行起来。数组和指针就像男人和女人一样不同,它们实际上相距甚远,但它们确实经常交换字母。 :-)
我同意像 "pointer/array equivalence" 或 "array decay"(变成指针)这样的术语是不准确的,并且可能会产生误导。
我建议如下:
使用 [] 运算符访问数组 with 索引 has 一个等价物指针算术表达式。然而,指针和数组之间并不等价:我可以愉快地更改指针的值(内容),也许可以保存一个单独的迭代计数器,但我不能用 "decayed" 数组这样做;它是不可变的,并且在某些方面表现出与 C++ 引用类似的行为。
英语中的动词"to decay"和"to convert"无一例外地表示原文在这个过程中发生了变化。使用数组名称或使用一元“&”运算符不要更改其操作数。
因此,"yields a pointer" 或 "creates a pointer" 这样的表达式会更准确这反映在以下事实中,在这两种情况下,结果指针都是临时的,(通常)位于 GP 中-CPU的寄存器,不能赋值给.
至少这是我的理解,看反汇编似乎证实了这一点。
几乎所有阅读本文的人都可能熟悉关于 C 的这三个关键事实:
- 当您在表达式中提及数组名称时,它的计算结果(大多数情况下)是指向数组第一个元素的指针。
- "array subscripting" 运算符
[]
对指针的作用与对数组的作用一样好。 - 看似数组的函数参数,其实声明的是指针
这三个事实绝对是 C 中数组和指针处理的核心。它们甚至不是三个独立的事实;它们是一个中心概念的相互关联的方面。如果没有对这个概念的正确理解,即使是相当基本的 C 编程也是不可能的。
我今天的问题很简单,这个概念的名称是什么?
我以为我是守旧的,但我一直称它为"The equivalence between arrays and pointers in C",或简称为"array/pointer equivalence"。但是我了解到您几乎不能在 SO 上说这些话;他们几乎是禁忌。
这似乎是一个抽象或哲学问题,所以为了更具体地构建它,我正在寻找的是一个简单的名词或名词短语,我可以在句子 "Yes, due to _____, array subscripting can be thought of as syntactic sugar for pointer arithmetic" 中使用,作为答案比如说,
(但请注意,我不是寻找那个问题的答案,或者"What's wrong with the word 'equivalence'?"这个问题的答案。是的,我知道,它可能会误导学习者开始想象数组和指针在某种程度上是相同的。我在写 this FAQ list entry 时确实有这种困惑。)
C 标准对此没有一个词。它在 6.3.2.1p3 中定义行为 (1) 时使用 "conversion",在 6.5.2.1p2 中定义行为 (2) 时使用 "equivalent",在定义行为 (3) 时使用 "adjustment"在 6.7.6.3p7.
我是 old-fashioned,并且不认为调用这个 "array/pointer equivalence" 有什么问题,前提是在上下文中清楚地表明您正在谈论发生 (1) 的表达式或函数声明其中 (3) 发生。然而,对于不喜欢 "equivalence" 的人来说,一个更可口的术语可能是 "array-to-pointer conversion",因为我认为这在 (1) 时最容易让人感到困惑。
我会选择数组衰减这个术语。该术语与它的含义相得益彰。 C 标准在这种情况下并没有说明它,是的,第一天我听到这个术语,我去标准中搜索它,但我找不到它(所以关于谁创造了这个术语等有点令人困惑)。也可以写为 "most scenarios array is converted into pointer"... - 不,这不是一个名词。但这并不是让任何误解发生。标准本身称其为 "conversion"。
大多数时候我会尽量说得长一点,然后把 ("array decaying") 这个词放在括号里。事实上,有些答案我什至没有提到它,只是按照标准的话 conversion into pointer。
我建议 "array-to-pointer decay" 是合理的 shorthand,因为 "decay" 是指类型转换的俗语,有先例 C FAQ 的其他地方:Question 6.12:
Q: Since array references decay into pointers, if arr is an array, what's the difference between arr and &arr?
"decay" 的扩展技术含义包括这个
自 C++11 起采用 C++ 标准库命名法:std::decay
标准使用术语转换为。 数组和指针等价 仍然优于 数组 衰减 到指针 。标准没有在任何地方提到这个术语,但它只是程序员之间的相互理解,当它出现在数组和指针的上下文中时,它被认为是数组和指针等价的。而指针和数组等价的意思是:pointer arithmetic and array indexing [that] are equivalent in C, pointers and arrays are different.。
- The "array subscripting" operator [] works just as well for pointers as it does for arrays.
不,实际上 []
时,您总会得到一个指向第一个元素的指针。这肯定会发生,因为 arr[i]
必须等同于 *(arr + i)
。前者对后者来说是"syntactic sugar"。
- A function parameter that seems to be an array actually declares a pointer.
这实际上是一种特殊情况,简称"array adjustment",编译器隐式地将数组类型的函数参数声明更改为指向第一个元素的指针。基本原理肯定是使函数与表达式的 "array decay" 兼容,但 C 标准将术语分开。
这两种情况,表达式和函数参数,通常被非正式地称为 "array decay"。尽管有时这仅用于表达式而不用于函数参数。我不认为存在单一、一致的术语用法。 "Array decay" 是我认为最好的,尽管 C 标准没有在任何地方使用该术语。
(我不喜欢"equivalence"这个词,因为数组可以变成指针,但反过来不行。确实总是有无数的初学者想出"arrays and pointers are the same thing"这样的困惑信念。称他们为 "equivalent" 并没有什么帮助。)
没有为提到的三个概念指定一个名称,但我认为将它们描述为暗示任何类型的 "equivalence" 是 counter-productive,至少在描述 "modern" 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); }
标准没有直接说明为什么 test1
中使用的指针值 s.arr[0]
不应该等同于 fetch_byte_at
时使用的指针值 ((char*)(void*)s)
来自 test2
。然而,它确实同时暗示 test2
应该能够读出 s
的所有字节 [暗示它应该可以预测地使用 x
的值至少达到 34] 而说 s.arr[0][x]
只对 x
到 6 的值有意义。
虽然标准中的任何内容都不会与您的前两点中的任何一个相矛盾,但不可能两者都成立。数组衰减的结果不是指向数组第一个元素的 "ordinary" 指针,或者将 []
运算符应用于数组与将其应用于指针具有不同的语义。虽然不清楚 #1 和 #2 中的哪一个已被 C99 无效,但它们在现代 C 中不再一起构成任何类型的 "equivalence"。
如果您认识到传统 C 和 "modern" C 之间的区别,那么为使前者有用的事物建立术语可能会很有用。但是,这些事情超出了您提到的要点。不幸的是,我不知道此类事物的任何标准术语,并且当它不再支持所涉及的概念时,我不会寻找标准来提供此类术语。
如果您指的是类型转换,为什么不使用术语“casting”?它已经被普遍理解为暗示编译器被强制处理两个相关但 not-the-same 类型,就好像它们是所需类型一样。是的,这里有一个等价关系,但是 'casting' 被用来表示类型在字面上并不相同,但编译器应该将一个类型视为不同的类型,并且编译器可以接受该过程, 像 up-casting for byte->long
第二选择:"Synonym"
这是一个微妙的问题。在浏览英语词库和词典后,我发现 similitude 一词可能适合您的上下文。
根据牛津在线词典的定义,Similar
这个词的定义是:
having a resemblance in appearance, character, or quantity, without being identical.
和单词 Similitude
为:
the quality or state of being similar to something.
由于数组和指针并不完全相同,但有时被相似对待,我们可能会说:
Yes, due to Array/Pointer similitude, array subscripting can be thought of as syntactic sugar for pointer arithmetic"
This may seem like an abstract or philosophical question, so to frame it more concretely, what I'm looking for is is a simple noun or noun phrase I could use the sentence "Yes, due to _____, array subscription can be thought of as syntactic sugar for pointer arithmetic", in answer to, say, this question.
您要查找的词组是"Yes, due to array subscribing being pointer arithmetic under the hood, array subscribing can be thought of as syntactic sugar for pointer arithmetic."
这当然是愚蠢的,因为说数组订阅是指针运算的语法糖的原因是因为它正是它的本质,它不需要进一步解释,除非你要对他们说这句话的人不知道 'array subscribing'、'pointer arithmetics' 或 'syntactic sugar' 是什么意思。这并不是说编译器不知道两者的区别(它知道是因为它负责你因此获得的所有语法糖)。
对于任何语言为我们所做的一切,我们都可以提出同样的问题,我们可以通过使用更多数量的低级指令来自己做,因此能够使用仅改变数量的多个术语来引用它使用的语法糖。重点不是假装它们是不同的(它们总是在路上,但这不是重点),而是使编程更容易(只需考虑编写代码而无需 [] 运算符作为指针算术的语法糖,并且您很快就会意识到它存在的原因 - 并不是因为它不同,而是因为它更容易编写、阅读和管理)。
(But please note that I am not looking for answers to that question, or for answers to the question "What's wrong with the word 'equivalence'?". Yes, I know, it can mislead learners into imagining that arrays and pointers are somehow the same. I did have that in mind when I wrote this FAQ list entry.)
你的问题好像是"What's a modern term for array pointer equivalence in the sense that array subscription is just syntactic sugar for pointer arithmetics?"
答案是:
- "Array subscription" 当您使用 [] 运算符索引数组时。
- "Pointer arithmetics" 当您手动移动指针时(与使用 [] 运算符相反)。您可能还想使用这个术语来表示您对输入 [] 运算符的值所做的任何数学运算,但您并不是真正在那里进行指针运算,而是 "calculating an index",这是语法术语自动为您考虑内存中对象的大小的糖分(同样,没有什么不同,只是更容易编写、阅读和管理,因此:语法糖分)。
谢谢大家。我正在使用这个 "answer" 来总结人们给出的答案和我对他们的评估,而不是作为一个正确的答案,我希望任何人都支持或任何东西。
很多人认真思考过这个问题,对此我表示赞赏。但在这一点上,我唯一可以得出的结论是,至少在今天,我想到的问题没有答案。
很多人建议 "array decay",这是一个非常好的镜头,但它不适合我。它主要指的是原始问题中列出的事实 1 和事实 3,但不是真正的事实 2。你不能说 "Yes, due to array decay, array subscripting can be thought of as syntactic sugar for pointer arithmetic." (或者至少,如果你的意图是清晰且有指导意义。)你必须说出类似 "Yes, due to array decay and the way pointer arithmetic is defined so as to be consistent with it, array subscripting can be thought of as syntactic sugar for pointer arithmetic" 的内容,这完全是另一回事。
虽然我没有这么明确地说,但我一直在寻找一个通用的、广泛的、被接受的术语,尽管没有要求它涉及标准中实际使用的词。并且鉴于没有人说出这样一个术语,鉴于每个人都进行了一定程度的猜测并且 "What about ...?",我得出结论,对于这三个相关事实背后的概念,没有一个被广泛使用的术语。 (除 "equivalence" 外,已排除。)
许多回答者和评论者以各种方式表达了这一点(没有一个答案)。我将继续并在此基础上接受 Lundin 的回答,因为其他人似乎最喜欢它。
我,以后我可能会尝试使用 "The correspondence between arrays and pointers in C" 看看它是否流行起来。数组和指针就像男人和女人一样不同,它们实际上相距甚远,但它们确实经常交换字母。 :-)
我同意像 "pointer/array equivalence" 或 "array decay"(变成指针)这样的术语是不准确的,并且可能会产生误导。
我建议如下:
使用 [] 运算符访问数组 with 索引 has 一个等价物指针算术表达式。然而,指针和数组之间并不等价:我可以愉快地更改指针的值(内容),也许可以保存一个单独的迭代计数器,但我不能用 "decayed" 数组这样做;它是不可变的,并且在某些方面表现出与 C++ 引用类似的行为。
英语中的动词"to decay"和"to convert"无一例外地表示原文在这个过程中发生了变化。使用数组名称或使用一元“&”运算符不要更改其操作数。
因此,"yields a pointer" 或 "creates a pointer" 这样的表达式会更准确这反映在以下事实中,在这两种情况下,结果指针都是临时的,(通常)位于 GP 中-CPU的寄存器,不能赋值给.
至少这是我的理解,看反汇编似乎证实了这一点。