使用指向指针的指针处理C中的结构数组

时间:2014-11-19 20:48:33

标签: c++ c

我试图更好地学习指针在C中的工作方式以及指向结构化事物的指针是如何打破我的想法的。这里我有3个问题:

  1. 如果我有一个结构和一个指向指针**的指针测试这个结构(所以这就像一个数组)如何使用p来访问数组成员(最好的方法)? tests [i] - > id失败(源代码示例如下)
  2. 使用下面带有指针的怪异行是代码中的不好之处,但我也希望能够使用它。我认为我错误地使用了它的模板,每个下一个结构的地址的输出看起来像前面的32字节跳转,而结构的大小只有4个字节。所以在我想要的行中(1)取测试顶部指针的初始地址,(2)添加结构TestCase的大小乘以i所以它指向正确的数组元素和(3)添加结构的id字段的偏移量。之后我会得到地址,我可以在内存中写id值,对吧?我这样做是对的吗?
  3. 为什么*测试值发生了变化?缓冲区溢出?

    struct TestCase{
        int id;
    };
    int main()
    {
        TestCase ** tests;
        cout << "Size of TestCase: " << sizeof(TestCase) << endl;
        *tests = (TestCase*)malloc(sizeof(TestCase*)*5);
        cout << "*tests = " << *tests << endl;
        for(int i = 0; i < 5; i++)
        {
            //*(int*)(tests+sizeof(TestCase)*i+(int)&(((struct TestCase*)NULL)->id)) = i;
    
            int addr = tests; // address of structures array in memmory;
            addr += sizeof(TestCase)*i; //address of current structure;
            addr += (int)&(((struct TestCase*)NULL)->id); // Adding id parameter offset in memory to current address
            *(int*)addr = i; // setting id for current structure equal to i
            cout << (int*)(tests+sizeof(TestCase)*i+(int)&(((struct TestCase*)NULL)->id)) << endl;
        }
        cout << "*tests = " << *tests << endl;
        return 0;
    }
    

    输出是:

    Size of TestCase: 4
    *tests = 0x600048600
    0x23ab90
    0x23abb0
    0x23abd0
    0x23abf0
    0x23ac10
    *tests = 0x600000000
    
  4. P.S。:从一条怪物线到一步一步的行动更新了循环码。

3 个答案:

答案 0 :(得分:4)

假设您希望tests成为array-of-pointers-to-struct-TestCase,其中包含5个指向5个结构的指针,那么您需要

  • 分配一个包含5个指针的数组,
  • 通过为struct
  • 分配内存来初始化每个指针

像这样:

#include <stdio.h>
#include <stdlib.h>

struct TestCase
{
    int id;
};

int main( void )
{
    int i;
    struct TestCase **tests;

    // allocate memory for an array of 5 pointers
    tests = malloc( 5 * sizeof(struct TestCase *) );
    if ( tests == NULL )
        exit( 1 );

    // allocate memory for 5 structures (and save each pointer in the array)
    for ( i = 0; i < 5; i++ )
    {
        tests[i] = malloc( sizeof(struct TestCase) );
        if ( tests[i] == NULL )
            exit( 1 );
    }

    // initialize the id in each struct
    for ( i = 0; i < 5; i++ )
        tests[i]->id = i;

    // print the id in each struct
    for ( i = 0; i < 5; i++ )
        printf( "%d\n", tests[i]->id );

    // free memory
    for ( i = 0; i < 5; i++ )
        free( tests[i] );
    free( tests );

    return 0;
}

我无法重现第2点中描述的问题。这是我尝试的代码(我放在释放内存的代码之前)

printf( "%p\n", tests );
for ( i = 0; i < 5; i++ )
{
    intptr_t addr = (intptr_t)tests;
    addr += sizeof(struct TestCase)*i;
    addr += (int)&(((struct TestCase*)NULL)->id);

    printf( "%p\n", (void *)addr );
}

代码的输出是

0xc03950
0xc03950
0xc03954
0xc03958
0xc0395c
0xc03960

地址按预期增加4个字节。请注意,我将addr的类型更改为intptr_t以保证指针可以正确转换,但这不会影响后续两行中的数学运算。

答案 1 :(得分:1)

  1. 在你的代码测试中是三倍*,从malloc行中删除附加*并测试[0] - &gt; id赋值将起作用。

  2. 如果您需要对偏移量进行高级访问,请按照您最初想要的问题分配值.IE - 测试[0] - &gt; id = 0x3834,或memcpy用于动态分配。不需要所有这些参考和演员表。

  3. 因为测试是在迭代器的第一行重新定位的。

答案 2 :(得分:0)

感谢@ user3386109,我终于可以做我想做的一切。好吧,我没有用令人毛骨悚然的公式写地址,而是使用相同的令人毛骨悚然的公式从地址读取:

    #include <stdio.h>
    #include <iostream>
    #include <string.h>
    #include <stdlib.h>

    using namespace std;

    struct TestCase{
        int ida;
        int idb;
    };

    int main()
    {
        TestCase ** tests; //create pointer to pointer
        cout << "Size of TestCase: " << sizeof(TestCase) << endl;
        tests = malloc(sizeof(TestCase*)*5);
        if(tests == NULL)
            exit(1);
        for(int i=0; i< 5; i++)
        {
            tests[i] = malloc(sizeof(struct TestCase));
            if(tests[i] == NULL)
                exit(1);
        }
        cout << "*tests = " << *tests << endl;
        for(int i = 0; i < 5; i++)
        {
            tests[i]->ida = i;
            tests[i]->idb = i+6;
            cout << std::hex << &(tests[i]->idb) << ": " << *(long*)((long)(long*)(tests[i])+(long)&(((TestCase *)NULL)->idb)) << endl;
        }
        for(int i=0; i<5; i++)
        {
            free(tests[i]);
        }
        cout << "*tests = " << *tests << endl;
        free(tests);
        return 0;
    }

输出:

    $ ./a.exe
    Size of TestCase: 8
    *tests = 0x600048630
    0x600048634: 6
    0x600048654: 7
    0x600048674: 8
    0x600048694: 9
    0x6000486b4: a
    *tests = 0x600048630