如何不使用 ++ 运算符直接移动到指针位置?

How can I move to a pointer position directly without using the ++ operator?

我正在使用指向结构的指针。我想知道是否可以在不使用 ++ 运算符的情况下直接移动到特定位置。

#include <stdio.h>
#include <stdlib.h>

#define ARRAY_SIZE 10

struct dummy{
    int id;
    char buffer[10];
};

typedef struct dummy dummy_struct;

int main()
{
    int i=0;
    dummy_struct *ds = malloc(sizeof(dummy_struct)*ARRAY_SIZE);
    dummy_struct *iterator = ds;

    for(i=0;i<ARRAY_SIZE;i++)
    {
        iterator->id = i;
        sprintf(iterator->buffer,"%d",i);
        iterator++;
    }

    iterator = ds;

    for(i=0;i<ARRAY_SIZE;i++)
    {
        printf("%d:%s:%p\n",iterator->id,iterator->buffer,iterator);
        iterator++;
    }

    // I want to access directly to 5th position
    iterator = ds + (sizeof(dummy_struct)*5);
    printf("5th position %d:%s:%p\n",iterator->id,iterator->buffer,iterator);

    return 0;
}

此声明

iterator = ds + (sizeof(dummy_struct)*5);

无效。我将不胜感激任何建议。

好吧,指针算法尊重数据类型!!

iterator = ds + 5;

会完成任务的。

具体来说,上面的表达式将通过将指针移动 5 次,乘以 ds 的类型大小(以字节为单位)来生成一个指针。这与 &(ds[5]).

相同

为了完整起见,解释为什么 iterator = ds + (sizeof(dummy_struct)*5); 是错误的,在这里,您实际上是在尝试将指针移动到索引为 (sizeof(dummy_struct)*5 的元素,这完全超出了界限。请注意,这会调用 undefined behavior!! 注意下方

引用 C11,章节 §6.5.6/P8

When an expression that has integer type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integer expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist. [....]

然后,关于上述未定义的行为,

[....] If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.


也就是说,printf() 的说法也是错误的。您有两个转换说明符,但提供了三个参数。这不是有害,而是useless/meaningless。

相关,来自章节 §7.21.6.1/P2,

[...] If the format is exhausted while arguments remain, the excess arguments are evaluated (as always) but are otherwise ignored. [...]

基于这种情况,可以直接使用

printf("5th position %d:%s:\n",ds[5].id,ds[5].buffer);

似乎您正在尝试使 iterator 指针指向 ds 数组的 5th 元素。但是这个语句会给你错误的结果:

iterator = ds + (sizeof(dummy_struct)*5);

sizeof(dummy_struct)*5的结果将导致结构dummy_struct的所有元素的总大小乘以5,这将被添加到ds引用的地址并分配至 iterator。因此,iterator 可能指向您的程序不拥有的内存位置。你需要做的:

iterator = ds + 5;

或者你也可以这样做:

iterator = &ds[5];

的行为
iterator = ds + (sizeof(dummy_struct) * 5);

undefined 如果您将指针设置为超出数组最后一个元素的指针。您实际上将 iterator 设置为数组中比您想象的更多的元素,增加了 sizeof(dummy_struct) 倍!不要那样做。

该语言允许您使用符号 iterator = ds + 5;。这个惯用的 指针算法 5 很多 sizeof(dummy_struct) 添加到地址 iterator。换句话说,编译器会为您进行 sizeof 调整。这就是指针运算如此强大的原因之一。

最后注意*(ds + 5)等价于ds[5]。我发现后者在处理数组时更加清晰。