首页 > 其他分享 >嵌入式面试刷题(day3)

嵌入式面试刷题(day3)

时间:2023-08-04 17:31:36浏览次数:30  
标签:字节 int float day3 嵌入式 mydata include data 刷题

(文章目录)


前言

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

一、怎么判断两个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);

总结

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

标签:字节,int,float,day3,嵌入式,mydata,include,data,刷题
From: https://blog.51cto.com/u_16153875/6965341

相关文章

  • 安全学习之路Day39
    ......
  • 嵌入式与物联网:连接现实与数字世界的纽带
    随着科技的发展和智能化的进程,嵌入式系统和物联网技术逐渐融入到我们的日常生活中,成为连接现实世界和数字世界的重要纽带。本文将探讨嵌入式系统与物联网之间的关系,并通过关系图展示二者的紧密联系。一、嵌入式系统的基本概念嵌入式系统是一种特殊的计算机系统,通常被嵌入到其他设备......
  • 【备考实战】计算机二级Python刷题【一】
    时间报名时间:2023-8-31考试时间:2023-9-23第1题计算机完成一条指令所花费的时间称为一个A.执行时序B.存取周期C.执行速度D.指令周期参考解析参考解析:D[解析]一般把计算机完成一条指令所花费的时间称为-一个指令周期。指令周期越短,指令执行就越快。本题答案为D选项......
  • 嵌入式教程_电机控制:2-24 步进电机控制实验
    2-24步进电机控制实验实验目的本节视频的目的是掌握GPIO模拟输出PWM的方法,学习步进电机的控制原理,并实现步进电机的控制。实验原理先来看一下硬件原理图,可看到控制步进电机的管脚分别为:GPIO6[2]、GPIO6[3]、GPIO6[4]和GPIO1[15]。使用的是一路四相五线步进电机,使用的电机驱动芯片......
  • 【安全学习之路】Day38
    ......
  • 数组双指针技巧汇总 [labuladong-刷题打卡 day2]
    https://labuladong.github.io/algo/challenge/ji-chu-tiao-zhan/day02/快慢指针26.删除有序数组中的重复项两个指针分别维护符合条件数组和待删除数组,当快指针移动时将符合条件元素插入已完成数组后即可。通过这两天对双指针的练习,可以发现很多双指针算法其实也是一种迭代算......
  • 前缀和数组技巧 [labuladong-刷题打卡 day3]
    今天是两道前缀和,主要有一维前缀和和二维前缀和,当然扩充到高维也是可以的,只不过状态转移会相对复杂些。这里直接贴一个动态规划的介绍吧:动态规划要素动态规划概念、特点、经典例题和于其它算法思想的比较前缀和其实是备忘录自底向上动态规划算法的一个典型例子,状态转移方程:一......
  • C语言嵌入式面试
    指针1.数组指针与指针数组,函数指针与指针函数区别?答:函数指针指向函数的指针变量,即本质是一个变量。指针函数是指返回值是指针的函数,即本质是一个函数。数组指针是指向数组首元素的地址的指针,其本质为指针。(这个指针存放的是数组首地址的地址,相当于2级指针,这个指针不可移动)指......
  • C语言嵌入式开发
    第一类问题:专业考察题在下面问题中,我附上自己的理解,可能不全面,用到的话再自行补充一些。问题1:问你写在简历上的项目经历,一般问的很细很细,在此基础上考察你项目里用到的技术知识。问题2:IIC协议(1)I2C使用两条线在主控制器和从机之间进行数据通信。一条是SCL(串行时钟线),另外一条......
  • C语言嵌入式面试3
    第一章、进程与线程1、什么是进程、线程,有什么区别?进程是资源(CPU、内存等)分配的基本单位,线程是CPU调度和分配的基本单位(程序执行的最小单位)。同一时间,如果CPU是单核,只有一个进程在执行,所谓的并发执行,也是顺序执行,只不过由于切换速度太快,你以为这些进程在同步执行而已。多核CPU可以......