好的,我有这段代码:
#include <stdio.h>
#include <stdlib.h>
#define ARR_SIZE 5
struct mys
{
double first;
unsigned long second;
char str[10];
};
int main(int argc, char** argv)
{
size_t i = 0;
struct mys thes[ARR_SIZE] =
{
{1.1, 1, "First"},
{2.2, 2, "Second"},
{3.3, 3, "Third"},
{4.4, 4, "Fourth"},
{5.5, 5, "Fifth"}
};//load array of structures with values
for (; i < ARR_SIZE; ++i)
fprintf(stdout, "second->%lu\n", thes[i].second);//loop through array thes and print element second
return (EXIT_SUCCESS);
}
现在,我想获取第0个第0个元素的元素的地址,然后使用它来循环遍历数组并打印每个第二个元素。
#include <stdio.h>
#include <stdlib.h>
#define ARR_SIZE 5
struct mys
{
double first;
unsigned long second;
char str[10];
};
int main(int argc, char** argv)
{
size_t i = 0;
unsigned long * ptr = NULL;//pointer to unsigned long
struct mys thes[ARR_SIZE] =
{
{1.1, 1, "First"},
{2.2, 2, "Second"},
{3.3, 3, "Third"},
{4.4, 4, "Fourth"},
{5.5, 5, "Fifth"}
};
//first loop
for (; i < ARR_SIZE; ++i)
fprintf(stdout, "second->%lu\n", thes[i].second);
ptr = &thes[0].second;//get the address of the second element of the zero'th array structure and store it in ptr
// Now I want to use the above pointer ptr to loop through the array thes and display the second element like I did above, but I can't manage to do that.
//The output of this loop should be the same as the first loop
return (EXIT_SUCCESS);
}
所以,我已经实现了指针但是我在编写第二个循环的代码时遇到了问题。任何帮助表示赞赏。
答案 0 :(得分:4)
for (; i < ARR_SIZE; ++i)
fprintf(stdout, "second->%lu\n", *( unsigned long * )(( char * )ptr + i * sizeof( struct mys ) ));
答案 1 :(得分:3)
你不能(或更重要的是不应该)这样做。你应该做的是安全指向数组的第一个元素的指针,所以你可以迭代它。
struct mys* ptr;
ptr = &thes[0];
for(int i=0; i<10; i++, ptr++)
fprintf(stdout, "second->%lu\n", ptr->second);
但是你必须要小心,因为没有end-element,而iteratig [0-10]只适用于以ptr = &thes[0];
开头的情况。
答案 2 :(得分:2)
你的要求没有多大意义:你所拥有的只是一个指向unsigned long
的指针,没有任何信息可以确定有问题的数字是某些特定结构数组的一部分。
你可以使用指针技巧来做到这一点,但它肯定不是直截了当或我在一般编程中推荐的东西。
为什么需要这样做?
我会通过计算指向结构的指针来做到这一点,以使迭代更清晰:
const struct mys *mysp = (struct mys *) ((char *) ptr -
offsetof(struct mys, second));
这使用offsetof
从指向结构成员的指针“备份”到结构本身。
答案 3 :(得分:2)
你当然可以这样做。不好,没用,但可以通过操纵你的指针来完成。
要理解,请查看内存中结构数组的布局,假设您的数组从地址0x0000开始:
0x0000 : array[0].first - first part of mys.first
0x0004 : array[0].first - second part of mys.first
0x0008 : array[0].second
0x000c : array[0].str[0-3] - first four elements of your string
0x0010 : array[0].str[4-7] - next four elements
0x0014 : array[0].str[8-9] - last two elements and padding
0x0018 : array[1].first - second element !
...
因此,您可以看到在阵列的两个连续元素的相同字段之间,您具有结构的大小。
要迭代内存中几个连续结构的相同字段,您只需要声明一个指向第一个结构元素的指针,然后根据结构的大小增加它,以访问下一个元素的相同字段。阵列。
在您的情况下,它看起来像:
int i;
struct mys my_array[SIZE];
char* my_iterator = &my_array[0].second;
for(i=0; i<SIZE; i++) {
fprintf(stdout, "second->%lu\n", *(unsigned long*)my_iterator);
my_iterator += sizeof(mys);
}
但是这看起来不太好,你可以稍微改进一下,但是当不需要它时,使用指针仍然是不好的做法。
int i;
struct mys my_array[SIZE];
strut mys* my_iterator = &my_array[0].second;
for(i=0; i<SIZE; i++, my_iterator++) {
fprintf(stdout, "second->%lu\n", *(unsigned long*)my_iterator);
}
答案 4 :(得分:1)
这是弗拉德解决方案的一个小解释。这是用c ++编写的(在for循环中声明的变量):
我们将ptr
转换为unsigned char*
(字节ptr),然后将mys
占用的字节数增加,以将其设置为下一个元素的{{1} }。然后我们将它转换回second
,并取消引用指针以获取其值。
ulong
或者另一方面,也许它更容易理解:
ptr = &thes[0].second; //get the address of the second element of the zero'th array structure and store it in ptr
for (i = 0; i < ARR_SIZE; ++i)
{
unsigned char* pointer_as_byte = (unsigned char*)ptr; // get ptr as byte ptr to increment it
unsigned char* pointer_offset = pointer_as_byte += (i * sizeof(struct mys)); // next structure's [second] field
unsigned long* final_pointer = (unsigned long*)pointer_offset; // cast byte ptr back to ulong ptr
fprintf(stdout, "second->%lu\n", *final_pointer);
}
答案 5 :(得分:0)
你做不到。至少不是简单的。你的阵列是结构。他们连续坐在记忆中。在没有任何强制转换的情况下递增指针ptr
会将其移动到内存块中的下一个long
地址,该地址不在下一个结构中,而是紧挨着它。