如何在不使用++运算符的情况下直接移动到指针位置?

时间:2017-12-13 08:09:25

标签: c pointers operators pointer-arithmetic

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

#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);

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

3 个答案:

答案 0 :(得分:30)

嗯,指针算术尊重数据类型!!

iterator = ds + 5;

将完成工作。

详细说明,上面的表达式将通过将其移动5次,乘以ds的类型大小(以字节为单位)来生成指针。这与&(ds[5])相同。

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

引用C11,章节§6.5.6/ P8

  

当指针中添加或减去具有整数类型的表达式时,   result具有指针操作数的类型。如果指针操作数指向的元素   一个数组对象,并且该数组足够大,结果指向一个偏移的元素   原始元素使得结果和原始的下标不同   数组元素等于整数表达式。换句话说,如果表达式P指向   数组对象的i - 元素,表达式(P)+N(等效地,N+(P))和   (P)-N(其中N的值为n)分别指向i+n - 和i−n - 元素   数组对象,只要它们存在。 [....]

然后,关于上面提到的未定义行为,

  

[....]如果两个指针   操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素   数组对象的元素,评估不得产生溢出;否则,   行为未定义。如果结果指向一个超过数组对象的最后一个元素的那个,那么   不得用作被评估的一元*运算符的操作数。

话虽如此,printf()陈述也是错误的。您有两个转换说明符,但提供了三个参数。它不是有害,但无用/无意义。

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

  

[...]如果参数保留时格式已用尽,则多余的参数为   评估(一如既往),否则被忽略。 [...]

根据这种情况,您可以直接使用

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

答案 1 :(得分:8)

的行为
AirCookiePersister
如果将指针设置为超出数组最后一个元素的指针,则

undefined 。您实际上将iterator = ds + (sizeof(dummy_struct) * 5); 设置为数组中的其他元素而不是您想象的因素iterator!不要那样做。

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

最后请注意,sizeof相当于*(ds + 5)。我发现后者在使用数组时更加清晰。

答案 2 :(得分:2)

似乎您试图使iterator指针指向5th数组的ds元素。但是这个陈述会给你错误的结果:

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

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

iterator

或者您也可以这样做:

iterator = ds + 5;