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

Rub*_*ozo 9 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;
}
Run Code Online (Sandbox Code Playgroud)

这个说法

iterator = ds + (sizeof(dummy_struct)*5);
Run Code Online (Sandbox Code Playgroud)

不管用.我将不胜感激任何建议.

Sou*_*osh 30

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

iterator = ds + 5;
Run Code Online (Sandbox Code Playgroud)

将完成工作.

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

为了完整起见,解释为什么iterator = ds + (sizeof(dummy_struct)*5);是错误的,在这里,你实际上是在尝试将指针移动到索引的元素,因为(sizeof(dummy_struct)*5它超出了界限.请注意,这会调用未定义的行为 !! 请注意以下

引用C11,章节§6.5.6/ P8

当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有指针操作数的类型.如果指针操作数指向数组对象的元素,并且数组足够大,则结果指向偏离原始元素的元素,使得结果元素和原始数组元素的下标的差异等于整数表达式.换句话说,如果表达式P指向i数组对象的-th元素,则表达式(P)+N(等效地N+(P))和 (P)-N(其中N有值n)分别指向数组对象的i+n第-th和i?n-th元素,前提是它们存在.[....]

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

[....]如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义.如果结果指向数组对象的最后一个元素之后,则不应将其用作*已计算的一元运算符的操作数.


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

相关的,从章节§7.21.6.1/ P2,

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

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

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

  • @Joe,这就是为什么选择答案总是对SO有用的原因.Sourav Ghosh喜欢使用标准参考文献,这使他的答案具有参考质量.我倾向于不这样做,主要是因为我基本上是一个不知道标准和我应该知道的骗子.请记住,SO是一个问答网站,而不是一个帮助个人用户的论坛(虽然这确实是辍学的必然结果). (5认同)
  • 为了完成我的代码工作,我用这行修改了:`iterator = ds + 5`.谢谢!!! (3认同)
  • @Bathsheba我从Mariana Trench到珠穆朗玛峰的顶部. (2认同)

Bat*_*eba 8

的行为

iterator = ds + (sizeof(dummy_struct) * 5);
Run Code Online (Sandbox Code Playgroud)

如果将指针设置为超出数组最后一个元素的指针,则未定义.你实际上是在设置iterator数组中的元素而不是你想象的因素sizeof(dummy_struct)!不要那样做.

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

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