我试图更好地学习指针在C中的工作方式以及指向结构化事物的指针是如何打破我的想法的。这里我有3个问题:
i
所以它指向正确的数组元素和(3)添加结构的id字段的偏移量。之后我会得到地址,我可以在内存中写id
值,对吧?我这样做是对的吗?为什么*测试值发生了变化?缓冲区溢出?
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
P.S。:从一条怪物线到一步一步的行动更新了循环码。
答案 0 :(得分:4)
假设您希望tests
成为array-of-pointers-to-struct-TestCase
,其中包含5个指向5个结构的指针,那么您需要
像这样:
#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)
在你的代码测试中是三倍*,从malloc行中删除附加*并测试[0] - &gt; id赋值将起作用。
如果您需要对偏移量进行高级访问,请按照您最初想要的问题分配值.IE - 测试[0] - &gt; id = 0x3834,或memcpy用于动态分配。不需要所有这些参考和演员表。
因为测试是在迭代器的第一行重新定位的。
答案 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