关于指针在结构体中的调用

在学习《数据结构》编程时遇到一些问题,是关于C语言指针的。

这里就没有必要上传整个工程源码了,而只将问题本质总结如下:(若有问题还请各位指正)

typedef struct
{
	int dat;
	int *ptr;
}Sample;

Sample	temp;

printf("%d\n",&temp.dat);	//输出temp.dat的地址
printf("%d\n",&temp.ptr);	//输出temp.ptr的地址
printf("%d\n",temp.dat);	//输出temp.dat中存放的数值,该数值就是一个普通数值。
printf("%d\n",temp.ptr);	//输出temp.ptr中存放的数值,该数值也是一个地址,但是是默认分配的地址,未被初始化。

执行结果如下:

 

下面开始分析。

为便于分析,可将上述执行结果总结在下表中:

&temp.dat1245020

temp.dat-858993460

&temp.ptr1245024

temp.ptr-858993460

 

下面两条语句都不正确:

printf("%d\n",*temp.dat); //非法的,因为dat并非指针变量
printf("%d\n",*temp.ptr); //编译无错,但是执行时会出错,因为此时指针ptr没有被初始化,它不指向任何内存,temp.ptr中存放的是默认的数值-858993460。而*temp.ptr是取指针变量所指存储空间的内容,暂时就认为-858993460
所指存储空间并不存在或者该存储空间的内容不可取,具体原因也许哪一天会通过别的渠道得知。

 

若执行下面两条语句:

 scanf("%d",&temp.dat);
 scanf("%d",&temp.ptr);

比如说执行时输入1和2,则上表变内容变成如下所示:

&temp.dat1245020

temp.dat1

&temp.ptr1245024

temp.ptr2

若此时再执行下面四条语句:

printf("%d\n",&temp.dat); //输出temp.dat的地址,当然还是1245020

printf("%d\n",&temp.ptr); //输出temp.ptr的地址,当然还是1245024

printf("%d\n",temp.dat); //输出temp.dat中存放的数值1,该数值就是一个普通数值

printf("%d\n",temp.ptr); //输出temp.ptr中存放的数值2,该数值是一个地址,即地址单元为2存储空间。

地址为2的存储单元一般是不可写也不可读的。

比如在执行语句scanf("%d",temp.ptr)和语句printf("%d\n",*temp.ptr)时都是错误的,但当temp.ptr指向了确定的存储空间时,这两条语句便是正确的了。

 

若执行语句 temp.ptr = (int *)malloc(sizeof(int)) 后,再执行scanf("%d",temp.ptr)和printf("%d\n",*temp.ptr),就是可以的了,因为此时temp.ptr执向一个确定的存储空间,该存储空间是由malloc函数分配的。

 

上面所有的分析都是基于定义了Sample temp,即定义了Sample类型的变量temp,倘若要是定义Sample类型的指针变量*temp呢?

若定义的是Sample类型的指针变量*temp,则也要对其初始化,使其指向一个确定的存储空间,否则temp自己都不指向确定的存储空间,更别说temp下的dat和ptr了。

初始化方式如下(也可叫作分配存储空间):

temp = (Sample *)malloc(sizeof(Sample));

在初始化后,便可操作temp结构了,但要注意此时的temp.ptr并没有初始化,它并没有指向任何确定的存储空间,temp.ptr的初始化方式在前面已经说了。

在初始化temp之后,后面的操作与上文类似。

结构体指针结构体调用可以通过C#调用C++的DLL实现。具体步骤如下: 1.在C++定义结构体指针结构体,例如: ```c++ typedef struct _tagPerson { char name[20]; int age; }Person; typedef struct _tagPersonList { Person* pPerson; int count; }PersonList; ``` 2.在C++编写导出函数,例如: ```c++ extern "C" __declspec(dllexport) PersonList* GetPersonList() { PersonList* pList = new PersonList; pList->count = 2; pList->pPerson = new Person[2]; strcpy_s(pList->pPerson[0].name, "Tom"); pList->pPerson[0].age = 20; strcpy_s(pList->pPerson[1].name, "Jerry"); pList->pPerson[1].age = 22; return pList; } ``` 3.在C#定义结构体指针结构体,例如: ```c# [StructLayout(LayoutKind.Sequential)] public struct Person { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 20)] public string name; public int age; } [StructLayout(LayoutKind.Sequential)] public struct PersonList { public IntPtr pPerson; public int count; } ``` 4.在C#声明导出函数,例如: ```c# [DllImport("TestDll.dll", CallingConvention = CallingConvention.Cdecl)] public static extern IntPtr GetPersonList(); ``` 5.在C#调用导出函数,例如: ```c# IntPtr pList = GetPersonList(); PersonList list = (PersonList)Marshal.PtrToStructure(pList, typeof(PersonList)); Person[] persons = new Person[list.count];IntPtr ptr = list.pPerson; int size = Marshal.SizeOf(typeof(Person)); for (int i = 0; i < list.count; i++) { persons[i] = (Person)Marshal.PtrToStructure(ptr, typeof(Person)); ptr = new IntPtr(ptr.ToInt64() + size); } ``` 以上代码演示了如何在C#调用C++ DLL结构体指针结构体。需要注意的是,在C#使用指针时需要使用IntPtr类型,并且需要进行内存管理,避免内存泄漏。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值