- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
在 C(和其他一些类似 C 的语言)中,我们有 2 个用于处理指针的一元运算符:解引用运算符 (*
) 和“地址”运算符 (&
)。它们是左一元运算符,这会在运算顺序中引入不确定性,例如:
*ptr->field
或
*arr[id]
操作顺序是由标准严格定义的,但从人类的角度来看,这是令人困惑的。如果 *
运算符是右一元运算符,则顺序将很明显并且不需要额外的括号:
ptr*->field vs ptr->field*
和
arr*[id] vs arr[id]*
那么,为什么运算符左是一元运算符而不是右运算符,这有充分的理由吗?我想到的一件事是类型声明。左运算符留在类型名称附近(char *a
vs char a*
),但是有类型声明,这已经打破了这个规则,所以为什么还要麻烦 ( char a[num]
, char (*a)(char)
等)。
显然,这种方法也存在一些问题,比如
val*=2
可以是 *=
的简写 val = val * 2
或取消引用并分配 val* = 2
。然而,这可以通过在取消引用的情况下要求 *
和 =
标记之间的空格来轻松解决。再一次,没有什么开创性的,因为有这样一个规则的先例(--a
vs --a
)。
那么为什么它们是左运算符而不是右运算符?
编辑:我想指出,我问了这个问题,因为 C 的许多更奇怪的方面都有有趣的解释,为什么它们是这样的,比如 existence of the ->
operator或类型声明或从 0 开始的索引。等等。原因可能不再有效,但在我看来它们仍然很有趣。
最佳答案
确实有权威来源:"The Development of the C Language" by the creator of the language, Dennis M. Ritchie :
An accident of syntax contributed to the perceived complexity of the language. The indirection operator, spelled
*
in C, is syntactically a unary prefix operator, just as in BCPL and B. This works well in simple expressions, but in more complex cases, parentheses are required to direct the parsing. For example, to distinguish indirection through the value returned by a function from calling a function designated by a pointer, one writes*fp()
and(*pf)()
respectively. The style used in expressions carries through to declarations, so the names might be declaredint *fp();
int (*pf)();In more ornate but still realistic cases, things become worse:
int *(*pfp)();
is a pointer to a function returning a pointer to an integer. There are two effects occurring. Most important, C has a relatively rich set of ways of describing types (compared, say, with Pascal). Declarations in languages as expressive as C—Algol 68, for example—describe objects equally hard to understand, simply because the objects themselves are complex. A second effect owes to details of the syntax. Declarations in C must be read in an `inside-out' style that many find difficult to grasp [Anderson 80]. Sethi [Sethi 81] observed that many of the nested declarations and expressions would become simpler if the indirection operator had been taken as a postfix operator instead of prefix, but by then it was too late to change.
因此 *
在 C 中位于左侧的原因是因为它是 on the left in B .
B 部分基于 BCPL ,其中取消引用运算符是 !
。这是在左边;二进制 !
是一个数组索引运算符:
a!b
is equivalent to
!(a+b)
.
!a
is the content of the cell whose address is given by a; it can appear on the left of an assignment.
还50岁BCPL手册甚至没有提及 !
运算符 - 相反,运算符是单词:一元 lv
和 rv
。由于这些被理解为好像它们是函数,所以很自然地它们先于操作数;后来较长的 rv a
可以用语法糖 !a
代替。
许多当前的 C 运算符实践都可以通过这条路线进行追踪。 B 同样有 a[b]
等同于 *(a + b)
到 *(b + a)
到 b[ a]
就像在 BCPL 中一样,可以使用 a!b
<=> b!a
。
请注意,在 B 中变量是未类型化的,因此与声明的相似性肯定不是在左侧使用 *
的原因。
所以一元 *
在 C 中位于左侧的原因和 一样无聊“在使用一元 *
的更简单的程序中没有任何问题> 在左边,在每个人都习惯于使用其他语言的解引用运算符的情况下,没有人真正认为其他方法会更好,直到为时已晚才改变它“。
关于c - 为什么 'dereference' 和 'address of' 运算符在左边?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46759733/
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。如需帮助澄清这个问题以便重新打开它,visit the help center .
有谁知道区别吗? 最佳答案 如果您想玩可移植的可执行文件,就没有办法绕过 the specs 的副本。 . 已经有一段时间了,但如果内存正确地为我服务:IT 和 IAT 是相同的,除了 IAT 在解析
我正在尝试在 ec2-instance 上安装 Hadoop-2.6.0。 我下载并安装了 Hadoop。我还设置了环境变量。尝试启动 hdfs 服务时出现以下错误。 [ec2-user@ip-10-
我写了一个示例程序。如果我打印 pa 和 pb 的地址都是不同的。你能告诉我为什么会这样吗? #include using namespace std; class A { int x; }; cla
*&x 是否总是等于 x?如果不是,什么时候不是? &*x 是否总是等于 x?如果不是,什么时候不是? 我的猜测是 (1) 总是正确的,但 (2) 并不总是正确的,因为 x 可能并不总是一个指针,所以
我有一个 Address 类,它是一个非常简单的元数据容器。 (在底部。) 我有一个 Address 对象数组,它不是可选的 - 它肯定存在。我还有一个类维护这些引用的可选列表,如下所示: publi
我在理解 wsdl 中 soap:address 和 http:address 标签之间的区别时遇到了一些问题。它可以互换吗?我可以使用 soap:address 代替 http:address 吗?
关于AT (...) ld 的指令, this source状态: AT ( ldadr ) The expression ldadr that follows the AT keyword spec
我正在使用 Tensorflow 的 C API 在并行模拟中进行推理。因为我想要 AVX 支持,所以我从源代码编译了 Tensorflow。我链接它并使用 wmake 编译所有内容。 现在,如果我开
就像标题一样,我是cxf的新手。只是想知道 soap:address 和发布时在应用程序上下文中的 jaxws:endpoint 中指定的地址有什么区别? 此外,在jaxws:endpoint中,地址
#include #include using namespace std; class myexception: public exception { virtual const char*
C/C++ 应用程序抛出该错误,如何开始调试(比添加打印语句更好的主意)? 最佳答案 第二个地址是不是一个非常小的数字,比如 0x00000001 或 0x00000000?如果是这样,您可能只是忘记
如果我没记错的话,几天前它曾经显示“localhost”。我不确定是什么改变了 server.address().address 返回双冒号 (::) 。我在这里读到,如果它可用,它会返回一个 IPv
我现在正在使用 MPI 练习简单的并行编程。该代码旨在通过随机生成 N*N 矩阵并使用简单的邻域加权平均滤波器来模拟图像处理,而不处理第一行和最后一行和列。我在编译时没有出错,但在运行时出现了一些我无
这个问题在这里已经有了答案: How to retrieve range.address which is longer than 255 character? (2 个回答) 5年前关闭。 觉得很奇
当我尝试启动 Apache2 时收到以下消息: * Restarting web server apache2
我正在阅读一些有关指针和结构的内容,但我就是不明白:微 Controller 的头文件中有这样的内容: #define NVIC_BASE (SCS_BASE + 0x0100) /*ICER[0]
我有 alertmanager 作为 docker 容器在两台不同的主机上运行,并且两者都应该作为集群运行。两台机器都在同一个 vpc 内,并与私有(private) IP 地址通信。 我需要知道
在 Organization schema两者都有属性 address和 location . 什么时候应该使用每一个的真实世界例子? 地点 事件、组织或行动的地点。 地址 项目的物理地址。 最佳答案
我想要具有 FIFO 的服务器-客户端模型和客户端获取目录路径,但我收到错误“读:错误地址”和“写:错误地址”。 客户端 服务器错误:“读取:地址错误” 客户端错误:“写入:地址错误” 最佳答案 您可
我是一名优秀的程序员,十分优秀!