我正在使用指向结构的指针。我想知道是否可以在不使用++
运算符的情况下直接移动到特定位置。
#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);
无效。我将不胜感激任何建议。
答案 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;