嵌入式开发——结构体指针作为参数传递变量的值不正确

代二毛 代二毛     2022-12-03     347

关键词:

问题描述

由于海思芯片紧缺,公司决定启用一款新的音视频处理芯片,我负责要将原有的算法库移植到新平台。在移植的过程中,发现调用某个图像转换函数时,得不到正确的结果,而且这个函数还是其他的库里实现的,我只是调用。于是我去查看了这个函数的实现,传参主要是通过一个结构体。我在调用这个函数前,将该结构体的成员变量的值都打印出来,发现没有问题,然后在被调用的函数里,打印接收到的变量的值,发现对不上。这就很奇怪了,明明我在调用函数前赋值都是正确的,为什么传进去就不对了,百思不得其解。简单来说,就是我在A库调用B库实现的函数时,发现通过结构体传参,传过去的变量的值不正确。

解决步骤:

1.传参是传的结构体指针,我在调用函数前打印了这个结构体指针,在被调用函数里也打印了这个结构体指针,发现指针是一样的,表明传参是没有问题的。这里存在两种出错的可能,一种是两者数据解析方式不同,毕竟传的是同一内存地址,数据都一样;还有一种可能是该内存地址处的数据被意向不到的地方给修改了,导致两次去读取该内存的数据不一样。
2.接着进一步添加打印,我把结构体里的每个成员变量的地址都打印出来,发现在调用前打印和在被调用函数里打印是不一样的,这就能解释为什么传参的值不正确了,因为两次读取的都不是同一内存地址处的数据。这让我想起来结构体的对齐,毕竟面试时候考结构体最喜欢考对齐,于是我用sizeof()函数在两个库都打印了该结构体占用的字节数,果然两个库里同一结构体占用的字节数不一样,由此推断是两个库的对齐字节数不同导致的。
3.两个库都是运行在同一芯片,默认的对齐字节数就是CPU的位宽,32位机器就是4byte,64位芯片就是8byte。肯定有地方强行修改了对齐字节数,于是我用比对软件对比两个库里同一头文件的差异,发现其中一个库用了#pragma pack(4)将对齐字节数强行修改成4字节,这才导致两个库里结构体不一样。不熟悉的可以参考博客《嵌入式开发——#pragma pack()常见用法介绍》
4.因为海思芯片是32位的,默认就是4byte对齐,所以加不加#pragma pack(4)都是4字节对齐,代码在海思芯片上运行就没有问题。现在移植到的新芯片是64位的,默认是8字节对齐,这样就导致A库是8字节对齐,B库是4字节对齐,导致结构体大小不同,成员变量的地址相对于结构体首地址的偏移量也不同,肯定不能解析出正确的数据。

总结

我遇到的这种情况,最根本的原因就是两个库的交互头文件不一致导致的,正常情况两个库里的同一头文件应该是相同的。这是个历史遗留问题,以前被掩盖了,现在移植新平台才显露出来。同时也提醒自己,修改库之间交互的头文件要慎重。

c语言结构体(结构体作为函数参数|结构体指针作为函数参数)(代码片段)

文章目录一、结构体作为函数参数二、结构体指针作为函数参数三、完整代码示例一、结构体作为函数参数结构体变量作为函数形参,在函数中,只能访问该函数形参,无法修改结构体内存的值;结构体变量通过形参形式传入,会在该p... 查看详情

c语言结构指针变量作函数参数和链表基础

结构体变量作为函数参数(传递整个结构体):指向结构体变量的指针作为实参(传递结构体的地址):数据结构之链表:      查看详情

结构体作为函数参数值传递的问题

参考技术A传结构体地址与传结构体指针二者都可以作为传出参数,因为接受函数必须为其定义一个结构指针来接收,这样在函数内就可以修改结构体,在这点上二者没有区别。定义结构体指针未分配地址空间就作为参数传递会... 查看详情

20170908_郝斌c结构体

为什么要结构体结构体知识点1结构体的赋值和初始化StructStudent{intage;chargender;floatscore;};2   取出结构体中的每一个成员结构体.成员结构体指针变量名->成员3 结构体变量和结构体指针变量作为函数参数传递时的问... 查看详情

结构体指针与结构体变量用作函数参数时有啥区别,在用法上

参考技术A结构体指针与结构体变量用作函数参数区别:(1)结构体指针作为函数参数时,调用时传递的是指向一个结构体变量的指针(即结构体变量的地址);结构体变量作为函数参数时,调用时传递的结构体变量本身。(2)... 查看详情

c语言中,结构体作为函数参数传递,详解?

1.可以把结构体作为参数啊,2.不去取地址的意思,是引用的意思,函数执行时修改L的值,就直接的修改了实参的值,相当于地址传递了。3.真正调用的时,如下:SqListtempStruct;InitList_Sq(tempStruct)这样就可以了。呵呵参考技术A结... 查看详情

c语言关于结构体做参数传递?

...变了。学生一枚,求大神解释一下参考技术A双指针C语言结构体传参小-黯原创关注7点赞·2315人阅读目录C语言结构体传参1.普通传参1.1测试代码1.2测试结果1.3结果分析2.单指针传参2.1修改结构体数据2.1.1测试代码2.1.2测试结果... 查看详情

使用变量与指向变量的指针作为函数的参数

...函数的值的大小吗?我可以理解有人想要传递指向数组或结构的指针,而不是传递整个数组或结构,但他们做出此决定的其他原因是什么 查看详情

结构体(结构体嵌套结构体指针结构体参数传递)(代码片段)

结构体(struct)1、基本概念结构体-----将不同类型的数据成员组织到统一的名字之下,适用于对关系紧密,逻辑相关、具有相同或不同类型的数据进行处理2、结构体定义格式struct结构名(也可称作结构标识符)    &nb... 查看详情

疑问c++结构体(数组)指针作为函数参数,会不会修改实参的值?(代码片段)

C++结构体指针作为函数参数,不会修改实参的值?前言实例原因又一前言最近学了C++的指针和结构体,记得函数传参时,形参传递指针,则可以修改实参的值。可是今天看到一个关于结构体的数组... 查看详情

调用一个动态库中的函数,这个函数有一个参数是结构体指针,我如何使用这个指针?

我是希望利用动态库中的结构体指针,它就好比是一个返回值。在我自己的函数里定义了一个结构体指针,将其传递给这个动态库中的函数,将动态库函数中的结构体指针赋给我定义的结构体指针,但其值并不是动态库函数中结... 查看详情

c++逆向分析——this指针

...下来我们就需要一一学习这些概念。封装之前我们学习过结构体这个概念,那么结构体可以做参数传递吗?我们来看一下如下代码:structStudentinta;intb;intc;intd;; intPlus(Students)returns.a+s.b+s.c+s.d; voidmain()Students=1,2,3,4;intres=Plus(s)... 查看详情

go-常识补充-切片-map(类似字典)-字符串-指针-结构体(代码片段)

...指针向函数传递指针参数传递数组指针(最好是用切片)结构体结构体零值匿名结构体结构体指针结构体匿名字段结构体嵌套结构体嵌套+匿名字段结构体相等比较作业Go常识补充Go命名名字首字母大写可以在外部引用,如果是小... 查看详情

go语言学习之旅--结构体(代码片段)

结构体go语言类型定义go语言类型别名go语言类型定义和类型别名的区别结构体go语言结构体的定义声明一个结构体变量结构体的初始化访问结构体成员匿名结构体结构体指针举例使用new关键字创建结构体指针访问结构体指针成员... 查看详情

c语言结构体(结构体数组作为函数参数|数组在堆内存创建)(代码片段)

文章目录一、结构体数组作为函数参数(数组在堆内存创建)二、完整代码示例一、结构体数组作为函数参数(数组在堆内存创建)在上一篇博客【C语言】结构体(结构体数组作为函数参数|数组在栈内存创建)的基础上,将栈内存中的结... 查看详情

结构体,结构体指针作为函数参数的应用笔记

1.结构体,结构体指针作为函数参数有何区别#include<stdio.h>#include<string.h>structanimal{charname[30];intnum;};//使用结构体作为参数浪费内存需要建立结构体voidchange_struct(structanimalcat){cat.num=17;}//函数内部改变需要地址所以需要指针... 查看详情

如何将不同类型的结构体作为一个函数的参数?

定义一个函数,需要将不同类型的结构体作为参数传递进去,请问怎样实现?这个参数定义为什么类型的呢?(可以用来接收不同的结构体)可以利用函数的重载。比如说定义了两个结构体A和B,函数func()为要接受不同参数的函数... 查看详情

(c语言)多线程beginthreadex的第四个参数(结构体)到底怎么设置才能正确传递数值

...dn.net/morewindows/article/details/7421759。追问不对,没有我要的结构体的传递办法追答将一个long型指针指向结构体就行了啊 查看详情