在现代处理器中,可以从内存加载寄存器,然后将索引指针后修改所需的值。例如,在我们的嵌入式处理器中,这将通过以下方式完成:
ldr r0, [r1], +12
表示 - 将r1指向的值加载到r0,然后将r1递增12:
r0 = [r1]
r1 = r1 + 12
在C语言中,使用指针算术,可以使用指针指定值,然后将指针前进1:
char i, *p, a[3]={10, 20, 30};
p = &(a[0]);
i = *p++;
// now i==10 and p==&(a[1]).
我正在寻找一种方法来取消引用指针,同时用1以外的偏移量对其进行后修改。这在C中是否可行,所以它很好地映射到类似的asm指令?
请注意:
i = *p+=2;
增加[0] w / o修改指针的值,并且:
i = *(p+=2);
预先修改指针,因此在这种情况下i==30
。
答案 0 :(得分:7)
是的,这是可能的。
你不应该做奇怪的指针数学来实现它。
不仅是关于优化设置,您的GCC后端需要告诉 GCC它有这样的功能(即当GCC本身正在编译)。基于这些知识,GCC自动将相关序列组合成一条指令。
即。如果你的后端写得正确,甚至是:
a = *ptr;
ptr += SOME_CONST;
应该成为一个修改后的指令。
如何在编写后端时正确设置?(请求友好的邻居GCC后端开发人员为您完成此操作):
如果您的GCC后端被称为foo
:
gcc/config/foo/
。foo.h
,其中包含许多描述机器功能的#defines
。HAVE_POST_INCREMENT
以评估为true,如果它支持后修改,则将宏HAVE_POST_MODIFY_DISP
定义为true。 (post-increment => ptr++
,post-modify => ptr += CONST
)。也许还有其他一些事情需要处理。假设您的处理器的后端已经做到了这一点,让我们转到编译包含所述修改后序列的代码时会发生什么:
有一个特定的GCC优化传递,它通过属于此类别的指令对并将它们组合在一起。该过程的来源是here,并且对GCC将会做什么以及如何让它做到这一点有一个相当清晰的描述。
但最终,这不是你作为GCC用户的控制权。它是由编写GCC后端的开发人员控制的。所有你应该做的事情,就像最受欢迎的评论所说的那样:
a = *ptr;
ptr += SOME_CONST;
答案 1 :(得分:3)
你可以这样做,但不要这样做:
i = *((p += 2) - 2);
(不完全是后期修改)
答案 2 :(得分:1)
我能想到的最接近:
#define POST_INDEX_ASSIGN(lhs, ptr, index) (lhs = *(ptr), (ptr) += (index))
POST_INDEX_ASSIGN(i, p, 2);
答案 3 :(得分:1)
i = *p;
p = (unsigned char*)p + 12;
其中i是任何类型,p是指向该类型的指针。
如果不添加类型转换,则指针增量将以大小== sizeof(*p)
的步骤完成,这将使代码与发布的汇编程序完全不同。
例如,如果在32位系统上p为int*
,则指针在没有类型转换的情况下会增加4 * 12个字节。