当前位置: 首页 > news >正文

嵌入式面试刷题(day3)

文章目录

  • 前言
  • 一、怎么判断两个float是否相同
  • 二、float数据可以移位吗
  • 三、数据接收和发送端大小端不一致怎么办
  • 四、怎么传输float类型数据
    • 1.使用联合进行传输
    • 2.使用字节流
    • 3.强制类型转换
  • 总结


前言

本篇文章我们继续讲解嵌入式面试刷题,给大家继续分享嵌入式中的面试笔试经验和技巧。

一、怎么判断两个float是否相同

在C语言中,可以使用以下代码来比较两个float类型的数据是否相同:

#include <stdio.h>
#include <math.h>int main() {float a = 1.234;float b = 1.234;float epsilon = 0.000001; // 误差范围if (fabs(a - b) <= epsilon) {printf("两个浮点数相同\n");} else {printf("两个浮点数不同\n");}return 0;
}

上述代码中,通过计算两个浮点数之差的绝对值,并与给定的误差范围进行比较。如果差值小于等于指定的误差范围,则判定两个浮点数相同。

请注意,选择适当的误差范围是很重要的,它需要根据具体的应用场景和浮点数的精度要求来调整。在实际应用中,你可以根据需要调整epsilon的值来满足要求。

二、float数据可以移位吗

在C语言中,浮点数类型(如float)不直接支持移位操作。移位操作通常适用于整数类型,如int或unsigned int,而不适用于浮点数类型。

三、数据接收和发送端大小端不一致怎么办

当数据的接收端和发送端大小端不一致时,需要进行大小端转换(Endianness Conversion)以确保数据的正确解析。以下是一些常见的处理方法:

1.手动字节交换:将接收到的数据字节按照对应的顺序进行交换。例如,对于一个4字节的整数,可以将接收到的字节0、1、2、3分别与字节3、2、1、0进行交换。

2.使用联合体(Union)进行转换:定义一个联合体,其中包含原始数据类型和适应目标大小端的数据类型,并将原始数据读入联合体的原始数据类型中,然后从联合体的大小端适应数据类型中读取数据。

#include <stdio.h>typedef union interview
{unsigned int val;unsigned char data[4];
}EndianConverter;int main(void)
{EndianConverter mydata;mydata.val = 0xffeeccdd;printf("mydata.val : %x\n", mydata.val);for(int i = 0; i < 4; i++){printf("data[%d] : %x\n", i, mydata.data[i]);}return 0;
}

运行结果:
在这里插入图片描述

3.使用库函数:一些编程语言和库提供了内置的函数或方法来进行大小端转换。例如,C语言中可以使用htons和htonl函数将主机字节序转换为网络字节序,使用ntohs和ntohl函数将网络字节序转换回主机字节序。类似地,其他编程语言和库通常也提供了类似的功能函数。

四、怎么传输float类型数据

1.使用联合进行传输

使用联合(union)传输float类型数据的原理是通过共享内存空间来实现类型转换。联合是一种特殊的数据结构,它允许在同一段内存中使用不同的数据类型。

在使用联合传输float类型数据时,我们定义一个联合体,其中包含一个float类型字段和一个unsigned char类型的字节数组字段。这样,float类型字段和字节数组字段共享同一段内存空间。

在发送端,将float类型的数据赋值给联合体的float字段,这样数据就会存储在联合体的内存空间中。然后,通过访问联合体的字节数组字段,我们可以以字节序列的形式访问float类型数据的每个字节。

在接收端,接收到的字节序列存储在与发送端相同的联合体中的字节数组字段中。通过访问联合体的float字段,我们可以将字节序列重新解释为float类型数据。

示例代码:

发送端:

#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <string.h>
#include <arpa/inet.h>int main(int argc, char**argv)
{int fd = socket(AF_INET, SOCK_STREAM, 0);int err;char input[32];char recvbuf[64];int r = 0;int i = 0;union Mydata{float send_data;unsigned char data[4];};union Mydata F_data;F_data.send_data = 3.1456;if(fd < 0){printf("socket err\n");return -1;}struct sockaddr_in addr = {0};addr.sin_family = AF_INET;addr.sin_addr.s_addr = inet_addr("192.168.244.175");addr.sin_port = htons(8888);err = connect(fd, (struct sockaddr*)&addr, sizeof(addr));if(err == -1){printf("connect err\n");return -1;}printf("connect success\n");while(1){send(fd, F_data.data, 4, 0);sleep(1);}close(fd);return 0;
}

接收端:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>int main()
{int server = 0;struct sockaddr_in saddr = {0};int client = 0;struct sockaddr_in caddr = {0};socklen_t asize = 0;int len = 0;char buf[32] = {0};int r = 0;float mydata;union server1_data{float val;unsigned char data[4];};union server1_data recv_data;server = socket(PF_INET, SOCK_STREAM, 0);if( server == -1 ){printf("server socket error\n");return -1;}saddr.sin_family = AF_INET;saddr.sin_addr.s_addr = htonl(INADDR_ANY);saddr.sin_port = htons(8888);if( bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1 ){printf("server bind error\n");return -1;}if( listen(server, 1) == -1 ){printf("server listen error\n");return -1;}printf("server start success\n");while( 1 ){asize = sizeof(caddr);client = accept(server, (struct sockaddr*)&caddr, &asize);if( client == -1 ){printf("client accept error\n");return -1;}printf("client: %d\n", client);do{r = recv(client, recv_data.data, 4, 0);if( r > 0 ){mydata = recv_data.val;printf("mydata : %f\n", mydata);}} while ( r > 0 );close(client);}close(server);return 0;
}

2.使用字节流

使用字节流传输float类型数据的原理是将float数据拆分为字节,并按照特定的顺序传输这些字节。在接收端,再将接收到的字节重新组合成float类型数据。

在传输float数据时,float类型通常占用4个字节(32位)。可以根据系统的字节序(大端序或小端序)选择数据的传输顺序。

在发送端,首先将要传输的float数据的地址强制转换为uint8_t类型的指针,这将允许按字节访问数据。然后通过依次访问指针位置的字节,可以获得float数据的每个字节。按照约定的字节序(大端序或小端序),将这些字节依次发送到接收端。

在接收端,按照相同的字节序,依次接收到字节,将其存储到一个uint8_t类型的缓冲区中。然后,将这些字节按照字节序重新组合成float类型数据。

代码示例:

发送端:

float data = 3.1456;
unsigned char send_data[4];
memcpy(send_data, &data, 4);
send(fd, send_data, 4, 0);

接收端:

float mydata;
float recv_data[4];r = recv(client, recv_data, 4, 0);if( r > 0 )
{memcpy(&mydata, recv_data, 4);printf("data : %f\n", mydata);
}

3.强制类型转换

发送端:

float send_data = 3.1456;
send(fd, (char*)&send_data, 4, 0);

接收端:

float mydata;
r = recv(client, (char*)&mydata, 4, 0);

总结

本篇文章就讲解到这里,下篇文章我们继续讲解嵌入式面试笔试技巧和难点。

http://www.lryc.cn/news/116918.html

相关文章:

  • JVM源码剖析之Java命令行参数全解
  • 抽象工厂模式-java实现
  • 机器学习笔记 - 基于Python发现最佳计算机视觉模型的神经架构搜索技术NAS
  • 机器学习---自编码器
  • vuejs 设计与实现 - 渲染器的设计
  • openCV 图像对象的创建和赋值
  • idea - 刷新 Git 分支数据 / 命令刷新 Git 分支数据
  • 线上电影购票选座H5小程序源码开发
  • QT正则校验
  • ChatGPT“侵入”校园,教学评价体制受冲击,需作出调整
  • 函数的声明和定义
  • 06微服务间的通信方式
  • 研发工程师玩转Kubernetes——local型PV和PVC绑定过程中的状态变化
  • HTTP——十一、Web的攻击技术
  • Python-OpenCV中的图像处理-图像金字塔
  • ArcGIS、ENVI、InVEST、FRAGSTATS技术教程
  • Unity-Linux部署WebGL项目MIME类型添加
  • MySQL:表的约束和基本查询
  • mysql统计近7天数据量,,按时间戳分组
  • 无涯教程-Perl - endnetent函数
  • Selenium的xpath高级写法-实用篇
  • 阿里云官方关于数据安全保护的声明
  • 【神经网络手写数字识别-最全源码(pytorch)】
  • React、Vue和Angular的优缺点
  • ArcGIS Pro根据不同条件显示不同标注
  • DynamicsCRM专栏导览
  • Vue自定义指令使用
  • python爬虫之scrapy框架介绍
  • winform中嵌入cefsharp, 并使用selenium控制
  • 【leetcode】349. 两个数组的交集(easy)