问题标签 [pointer-arithmetic]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
c - C中取消引用和括号引用的操作顺序
如果我这样做*ptr[x]
,那是否等同于*(ptr[x])
, 或(*ptr)[x]
?
c++ - 如何解决指针别名问题?
不小心使用模板会导致臃肿。避免这种膨胀的一种方法是使用一个精简的类型安全模板来包装非类型安全的非模板代码。为此,包装器需要为非模板代码提供某种方式来访问它一无所知的东西。
例如,在数据结构中,包装器定义节点结构。不安全代码需要读取和写入节点,但必须通过包装器指定的某种接口间接地这样做。
实现此接口的一种方法是在结构(由不安全代码定义)中填充详细信息,例如由包装器确定的函数指针和常量。一种相关的常量是特定字段的偏移量(在某些结构内)。不安全的代码可以使用该偏移量(和一些指针算法)直接访问该字段。
但是,这会带来问题 - 随着优化器变得更加积极,这可能会导致指针别名问题。如果节点可以逃离库,情况尤其如此。例如,可以从二叉树中提取节点并重新链接以形成链接列表。另一个令人讨厌的例子是在单元测试时发生。
我目前有一个按照这些思路编写的容器库,目前它不会导致这些问题 - 但很快就会出现。它避免这些问题的原因是因为所有单元测试都应用于容器(而不是底层代码),并且因为节点永远不会逃脱容器。也就是说,节点总是以相同的指针算术方式访问,因此指针别名优化问题永远不会出现。
不幸的是,我很快将需要允许从容器中提取节点,并且我可能还需要对底层不安全代码进行单元测试。
我没有处理这个特定的库,而是从这里遇到相同问题的旧二叉树库中提取了一个更简单的提取物。在 VC++9 中它可以正常工作。使用 MinGW GCC 4.4.0,调试构建工作,但发布构建失败。问题是内联和优化器未能发现指针别名的混合。
只是要清楚 - 我不想在这里“WTF - GOTO !!!” 管他呢。问题是解决优化/指针问题。虽然如果你能找到一种Tree_To_List
结构合理且不使用隐藏/伪装的 goto 来实现它的编写方法,我很感兴趣。
此外,缺少一层基于模板的抽象(模板 c_Bin_Tree_Tool 不能完成整个工作 - c_Tool 完成包装,但以每次使用的方式而不是以可重复使用的形式。这只是一个副作用提取相关代码。
这段代码所做的是通过一个接一个地插入节点来创建一个不平衡的二叉树,然后平衡该树。平衡的工作原理是将树转换为列表(在某种程度上它已经是),然后将列表转换回树。树在平衡前后都被转储到 stdio。
bintree.h
...
test_bintree.cpp
...
预期的结果是...
实际发生了什么(MinGW GCC 4.4.0,优化的发布版本)......
据我所知,Balance 操作运行正常,但 BT_Dump 函数无法看到m_Left
和m_Right
字段的所有更改。
编辑那是错误的 - 否则为什么我将节点 1 视为新根。我想这就是当你过分依赖几个月前进行的调查的记忆时会发生的情况。
编辑实际上,节点 1 作为根是一个问题,但由于它是旧根 - 好吧,最好忽略这个问题是什么,并制定你自己的理论;-)
就代码中未定义标准而言,存在许多问题。我认为最大的问题是节点结构中的链接是 c_Node*,但由于不安全的代码对 c_Node 一无所知,因此它(通过指针算法)将它们作为 void* 访问。
一种解决方法是让不安全的代码通过 getter 和 setter 函数指针进行所有读取和写入,避免所有指针算术并确保对 c_Node 实例的所有访问都是通过 c_Node* 指针完成的。更好的是 - 接口变成了一个带有 getter/setter 方法等的类。在完整的二叉树库中,我有替代策略类来执行此操作,但老实说,当问题出现时,我真正的解决方法是将所有代码放入“垃圾”文件夹,因为我很少使用它,并且无论如何应该使用 boost 侵入性列表。
但是,这仍然留下了另一个更复杂且使用率更高的容器库,它并没有消失。我想我将不得不进行非常痛苦的重构来摆脱 offsetof 和指针算术的东西,但是......
C++ 规则到底是什么 - 究竟什么时候允许编译器无法发现可能的指针别名?是否可以重写上面的二叉树代码,使其仍然使用指针算法,仍然允许在库内部和外部访问/修改节点,并且不受这个优化问题的影响?
c - void * 赋值问题
我想使用指针算法从数据包结构中获取一些字段。但是下面的代码有什么问题?
在第一种情况下,我认为如果我从数据包的开头开始 4 个字节(2 个短字段),我会得到 tLow。但它没有给出预期值。另外,第二种情况我想通过从数据包的开头开始 12 个字节来获取数据字段。什么我的想法有问题吗?
c# - 新的 IntPtr.Add 方法 - 我错过了 int 的要点吗?
从 FW 4.0 开始,该IntPtr
结构具有以下Add
方法:
太好了,因为它应该解决IntPtr
我们遇到的所有数学问题(1、2,可能更多)。
但为什么是offset
int
?
一定不是IntPtr
吗?我可以很容易地想象将 64 位指针偏移一个超出int
范围的值。
例如,考虑Marshal.OffsetOf
:
它返回一个IntPtr
作为结构成员的偏移量。这很有意义!并且您不能轻松地将此偏移量与新Add
方法一起使用。您必须将其转换为Int64
,然后Add
在循环中多次调用。
此外,它似乎扼杀了IntPtr.Size
与正确编写的应用程序无关的想法。您必须将偏移量转换为特定类型,例如Int64
,此时您必须开始管理大小差异。想象一下当 128 位IntPtr
出现时会发生什么。
我的问题是,为什么?
我的结论是正确的,还是我错过了重点?
c - C中按内存地址的人口结构
我在使用地址引用填充结构成员时遇到问题,但是当它使用它自己的成员完成时,它就很好了。
带结构件
带内存地址
其中 actual_data_length 是变量的大小,data_start 是指向数据缓冲区的指针。
内存在我打印字段时给出垃圾值并且在执行整个之后我得到一个分段错误但是当使用 GDB 调试时程序正常退出。没有分段错误
请建议
提前致谢
问候, Soheb
c - strchr 的问题
我不明白为什么以下 C 代码不起作用:
c1
这个想法是找出和之间有多少个字符c2
:
不幸的是,这总是打印 1。有什么问题?不应该strchr
像 C# 那样工作string.IndexOf()
吗?
c - C 中明显的 NULL 指针取消引用实际上是指针算术吗?
我有这段代码。它似乎在这里取消引用空指针,但随后将结果与unsigned int
. 我真的不明白整个部分。它的目的是什么?这是指针算术的一种形式吗?
我得到的输出是 44。但它是如何工作的?
c - 常量指针数组还是指向数组的指针?C中什么速度更快?
您好,我现在正在上中级 C 班,我突然想到了这个想法:
那么,对于访问多维数组位置来说,什么是更快/更小/优化的呢?
这:
或者
或(更新)
由于“multi”是一个 const 数组,编译器应该“知道”元素位置的本地化,如果使用指向该数组的变量指针可能需要更多处理时间,另一方面在搜索时可能会更快我要显示的项目。什么是更快/更小/优化的方法?
先感谢您。
visual-c++ - uintptr_t 便携式替代品
我想检查某种类型的内存对齐T
。直接的方法是
但是,uintptr_t
它不是现有 C++ 标准的一部分,并且某些编译器不支持它,因此我正在寻找一种可移植的替代方法来执行此操作,并且std::ptrdiff_t
对我来说看起来不错。std::ptrdiff_t
保证能够存储两个指针之间的差异,但谁说这些指针之一不能是空指针?在这种情况下std::ptrdiff_t
,必须至少与指针本身的大小相同。
或像那样(摆脱乘法sizeof(T)
)
您如何看待这样的解决方案?便携性够吗?我看不出这会失败的任何原因,但是我想确认一下。
谢谢。
c - 指针算术说明
如果将 a*size 添加到地址 (p),那么为什么将 b*size 添加到 *(p+a)?*(p+a) 似乎是该位置的值,将 b*size 添加到它会改变它的值,而不是地址。但是,根据我读到的内容,这意味着要添加到地址中。