如何修改C指针?

时间:2012-06-26 10:29:53

标签: c pointers gcc

在现代处理器中,可以从内存加载寄存器,然后将索引指针后修改所需的值。例如,在我们的嵌入式处理器中,这将通过以下方式完成:

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

4 个答案:

答案 0 :(得分:7)

  1. 是的,这是可能的。

  2. 你不应该做奇怪的指针数学来实现它。

  3. 不仅是关于优化设置,您的GCC后端需要告诉 GCC它有这样的功能(即当GCC本身正在编译)。基于这些知识,GCC自动将相关序列组合成一条指令。

  4. 即。如果你的后端写得正确,甚至是:

     a = *ptr;
     ptr += SOME_CONST;
    

    应该成为一个修改后的指令。

    如何在编写后端时正确设置?(请求友好的邻居GCC后端开发人员为您完成此操作):

    如果您的GCC后端被称为foo

    1. 在GCC源代码树中,后端描述和挂钩位于gcc/config/foo/
    2. 在那里的文件(与GCC一起编译)中,通常有一个标题foo.h,其中包含许多描述机器功能的#defines
    3. GCC希望支持后增量的后端定义宏HAVE_POST_INCREMENT以评估为true,如果它支持后修改,则将宏HAVE_POST_MODIFY_DISP定义为true。 (post-increment => ptr++,post-modify => ptr += CONST)。也许还有其他一些事情需要处理。
    4. 假设您的处理器的后端已经做到了这一点,让我们转到编译包含所述修改后序列的代码时会发生什么:

      有一个特定的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个字节。