结构数组的指针

时间:2013-12-18 09:57:10

标签: c loops pointers struct

好的,我有这段代码:

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

所以,我已经实现了指针但是我在编写第二个循环的代码时遇到了问题。任何帮助表示赞赏。

6 个答案:

答案 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地址,该地址不在下一个结构中,而是紧挨着它。