嵌入式面经篇三——数据类型

news2024/11/26 22:22:06

文章目录

  • 前言
  • 一、数据类型
    • 1、用变量 a 给出下面的定义
    • 2、下面的代码输出是什么,为什么?
    • 3、写出 float x 与“零值”比较的 if 语句。
    • 4、下面代码有什么错误?
    • 5、下面代码输出是什么?
    • 6、下面代码运行后会是什么现象?
    • 7、下面函数的返回值是?
    • 8、结构体内存对齐原则?
    • 9、结构体内存对齐的原因?
    • 10、给定的位域结构体,它在内存中占用多少字节(32位编译器)?
    • 11、在32位系统中,有如下结构体,那么sizeof(fun)的数值是?
    • 12、数组首元素地址和数组地址的异同?
    • 13、下面代码输出是什么?
    • 14、判断下列表达式正确与否?
    • 15、查看下面代码,p[6] 等于几?
    • 16、下面代码的输出结果是什么?
    • 17、变长数组是什么?
    • 18、bool 类型包含于哪个头文件?
    • 19、结构体struct和联合体union的区别?
    • 20、给了一个地址a,分别强转类型为:int变量、int指针、数组指针、指针数组、函数指针。
    • 21、执行完下面代码,c 的值是多少?
    • 22、C语言中不同数据类型之间的赋值规则?


前言

记录一些招聘公司在招聘嵌入式软件岗位时的一些问题,此文为第三篇。


一、数据类型

1、用变量 a 给出下面的定义

  • 一个整型数: int a。
  • 一个指向整型数的指针(一重指针): int *a。
  • 一个指向指针的的指针,它指向的指针是指向一个整型数的指针(二重指针): int **a。
  • 一个有10个整型数的数组 :int a[10]。
  • 一个有10个指针的数组,这10个指针是指向整型数的(指针数组): int *a[10]。
    • 由于 [] 的优先级高于 *,所以首先是一个数组,然后数组的元素是指向int的指针。
  • 一个指向有10个整型数数组的指针(数组指针):int (*a)[10]。
    • 由于括号 () 的优先级高于 [],所以首先是一个指针,然后这个指针指向一个包含10个整数的数组。
  • 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(函数指针):int (*a)(int)。
  • 一个有10个指针的数组,这10个指针均指向函数,该函数有一个整型参数并返回一个整型数(函数指针数组): int (*a[10])(int)。

2、下面的代码输出是什么,为什么?

void foo(void)   
{   
    unsigned int a = 6;   
    int b = -20;   
    (a + b > 6)? printf("> 6") : printf(" <= 6");   
}   

答:输出是 “>6”。
解读:当运算表达式中存在有符号数和无符号数时,有符号数隐式转换成了无符号数(即底层的补码不变,但是此数从有符号数变成了无符号数)。注意,正数的补码为其本身,负数的补码为其反码+1。因此-20变成了一个非常大的正整数,所以该表达式计算出的结果 ”>6”。

3、写出 float x 与“零值”比较的 if 语句。

答:

if(x > -0.000001 && x < 0.000001);  

解读:因为计算机在处理浮点数的时候是有误差的,所以不能将浮点型变量用 “==” 或 “!=” 与数字比较,应该设法转化成 “>” 或 “<” 此类形式。

4、下面代码有什么错误?

#include<stdio.h>  
void main()  
{  
    char *s = "AAA";  
    s[0] = 'B';  
    printf("%s", s);  
} 
  • "AAA"是字符串常量,s 是指针,指向这个字符串常量,所以声明 s 的时候就有问题,应该是 const char* s=“AAA”。
  • 然后又因为是常量,所以对是 s[0] 的赋值操作是不合法的。

5、下面代码输出是什么?

#include<stdio.h>  
void main()  
{  
    int *a = (int *)2;  
    printf("%d", a + 3);   
}  

答:输出是14。
解读:代码将数值 2 强制类型转换为 int 类型指针,int 类型指针加 3 相当于指向后面第三个 int 类型变量的首地址,一个 int 类型变量占 4 个字节,所以加 3 相当于指针往后移了 12 个字节,指向地址 14 处。

6、下面代码运行后会是什么现象?

#include<stdio.h>  
#define N 500  
void main()  
{  
    unsigned char count;  
    for(count = 0; count < N; count++)  
    {  
        printf("---%d---\n", count);  
    }  
} 

答:进入不断打印 count 值的死循环。
解读:因为 unsigned char 类型变量的最大值为 255,所以 count 只能从 0 一直增加到 255,然后又恢复为 0,无法退出 for 循环。

7、下面函数的返回值是?

int foo(void)  
{  
    int i;  
    char c = 0x80;   
    i = c;  
    if(i > 0)  
        return 1;  
    return 2;  
} 

答:返回值为2。
解读:因为 0x80 == 128,超出了char类型变量c的表示范围(-128~127),所以c == -128,进而 i == -128,i < 0。

8、结构体内存对齐原则?

答:

  • 第一个成员的首地址(地址偏移量)为0。
  • 成员对齐:以 4 字节对齐为例,如果自身类型小于 4 字节,则该成员的首地址是自身类型大小的整数倍;如果自身类型大于等于 4 字节,则该成员的首地址是 4 的整数倍。若内嵌结构体,则内嵌结构体的首地址也要对齐,只不过自身类型大小用内嵌结构体的最大成员类型大小来表示。数组可以拆开看做 n 个数组元素,不用整体看作一个类型。
  • 最后结构体总体补齐:以 4 字节对齐为例,如果结构体中最大成员类型小于 4 字节,则大小补齐为结构体中最大成员类型大小的整数倍;如果大于等于 4 字节,则大小补齐为 4 的整数倍。内嵌结构体也要补齐。
  • 示例:
    • 示例 1:基本对齐

      #include <stdio.h>
      
      typedef struct {
          char a;      // 1字节,对齐到1字节
          int b;       // 4字节,对齐到4字节
      } SimpleStruct;
      
      int main() {
          printf("Size of SimpleStruct: %lu\n", sizeof(SimpleStruct));
          // 预期输出是8,因为`char a`后面会填充3字节,以确保`int b`对齐到4字节。
          return 0;
      }
      
    • 示例 2:内嵌结构体

      #include <stdio.h>
      
      typedef struct {
          double d;    // 8字节,对齐到8字节
      } InnerStruct;
      
      typedef struct {
          char c;      // 1字节,对齐到1字节
          InnerStruct s;   // 内嵌结构体,对齐到8字节
      } OuterStruct;
      
      int main() {
          printf("Size of OuterStruct: %lu\n", sizeof(OuterStruct));
          // 预期输出是16,因为`char c`后面会填充7字节以确保`InnerStruct s`对齐到8字节。
          return 0;
      }
      
    • 示例 3:数组对齐

      #include <stdio.h>
      
      typedef struct {
          char x;          // 1字节,对齐到1字节
          int arr[2];      // 8字节,数组的每个元素对齐到4字节
      } ArrayStruct;
      
      int main() {
          printf("Size of ArrayStruct: %lu\n", sizeof(ArrayStruct));
          // 预期输出是12,因为`char x`后面填充3字节以确保数组`arr`的首元素对齐到4字节。
          return 0;
      }
      
    • 示例 4:结构体补齐

      #include <stdio.h>
      
      typedef struct {
          char x;          // 1字节,对齐到1字节
          short y;         // 2字节,对齐到2字节
      } PaddedStruct;
      
      int main() {
          printf("Size of PaddedStruct: %lu\n", sizeof(PaddedStruct));
          // 预期输出是4,因为总体大小补齐到2的整数倍。
          return 0;
      }
      

注意:32 位编译器,一般默认对齐方式是 4 字节。

9、结构体内存对齐的原因?

  • 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据。
  • 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐,因为访问未对齐的内存,处理器需要做两次内存访问,而访问对齐的内存仅需要一次。如下图所示,访问对齐的short变量只需要一次,而访问未对齐的int变量则需要访问两次。

10、给定的位域结构体,它在内存中占用多少字节(32位编译器)?

struct A   
{         
     char t : 4;        // 4位         
     char k : 4;        // 4位         
     unsigned short i : 8;  // 8位               
     unsigned long m;     // 4字节  
};   

根据结构体内存对齐原则,共占用 8 字节。

11、在32位系统中,有如下结构体,那么sizeof(fun)的数值是?

#pragma pack(1)  
struct fun  
{  
    int i;   // 4字节  
    double d;  // 8字节  
    char c;  // 1字节  
}; 

答:sizeof(fun) 得到的结果是 13。
解读:因为预处理语句 ”#prama pack(1)” 将编译器的字节对齐数改为 1 了,根据结构体内存对齐原则,该结构体占用的字节数为 13。

12、数组首元素地址和数组地址的异同?

  • 异:数组首元素地址和数组地址是两个不同的概念。例如 int a[10],a 的值是数组首元素地址,所以 a+1 就是第二个元素的地址,int 类型占用 4 个字节,所以两者相差 4。而 &a 是数组地址,所以 &a+1就是向后移动(10*4)个单位,所以两者相差 40。
  • 同:数组首元素地址和数组地址的值是相等的。

13、下面代码输出是什么?

#include <stdio.h>  
void main()  
{  
    int a[5] = {1, 2, 3, 4, 5};  
    int *ptr = (int *)(&a + 1);  
    printf("%d, %d", *(a + 1), *(ptr - 1));  
} 

答:输出为 2, 5。
解读: a是数组首元素地址,所以 *(a + 1)就是第二个元素 a[1]。&a是数组地址,所以&a + 1是整个数组结尾的下一个地址,*(ptr - 1)就是a[4]。

14、判断下列表达式正确与否?

char str[2][3] = {“a”, “b”};         // 正确,str是一个可存放两个字符串的字符串数组  
char str[2][3] = {{1, 2}, {3, 4}, {5, 6}};  // 错误,行列不匹配  
char str[] = {“a”, “b”};           // 错误,字符数组不能存放两个字符串  
char str[2] = {“a”, “b”};          // 错误,字符数组不能存放两个字符串  

答:以注释形式展示。
注意:在 C 语言中字符用 ’ ’ 括起来,而字符串用 ” ” 括起来。

15、查看下面代码,p[6] 等于几?

int a[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};  
int *p = &a[1];   

答:等于8。
解读:p 是一个int类型指针,指向 a[1],p[6] 表示 p 往后移了6个单位(每个单位4个字节)并解引用,因此 p[6] 等于8。

16、下面代码的输出结果是什么?

#include <stdio.h>  
void main()   
{   
     char *str[] = {"ab", "cd", "ef", "gh", "ij", "kl"};  //指针数组  
     char *t;   
     t = (str + 4)[-1];    
     printf("%s", t);    
}

答:输出 “gh”。
解读:str 表示数组首元素地址,str + 4 表示数组第五个元素地址,(str + 4)[-1] 表示在第五个元素地址的基础上往前移一个元素并解引用,因此输出是第四个元素。

17、变长数组是什么?

在 C99 标准中,允许定义数组时 [] 中的值是整型变量或整型表达式,比如说下面的代码在支持 C99 标准的编译器中可编译通过:

#include <stdio.h>  
void main()  
{  
    int n;  
    scanf(%d”, &n);  
    int array[n];  
} 

18、bool 类型包含于哪个头文件?

在 C99 标准中位于 stdbool.h。
注意:C89 标准中则不支持,需要自己定义,代码如下:

#define TRUE 1  
#define FALSE 0  
typedef int bool;  
bool res = TRUE; 

19、结构体struct和联合体union的区别?

  • 两者最大的区别在于内存的使用。
  • 结构体各成员拥有自己的内存,各自使用且互不干涉,遵循内存对齐原则。
  • 联合体所有成员共用一块内存空间,并且同时只有一个成员可以得到这块内存的使用权。一个联合体变量的总长度应至少能容纳最大的成员变量,且需要进行内存补齐。

20、给了一个地址a,分别强转类型为:int变量、int指针、数组指针、指针数组、函数指针。

在这里插入图片描述

21、执行完下面代码,c 的值是多少?

unsigned int a = 1;  
int b = 0;   
int c = 0;  
c = a + b > 0 ? 1 : 2;  

答:c 的值是1。
解读:有符号数与无符号数一起运算时,有符号数转为无符号数。有符号数int b = 0的在内存中的补码是0,因此转为无符号数之后依然是0,a + b == 1 > 0,c == 1。

22、C语言中不同数据类型之间的赋值规则?

  • 整数与整数之间(char, short, int, long):
    • 长度相等:内存中的数据不变,只是按不同的编码格式来解析。
    • 长赋值给短:截取低位,然后按短整数的数据类型解析。
    • 短赋值给长:如果都是无符号数,短整数高位补0;如果都是有符号数,短整数高位补符号数;如果一个有符号一个无符号,那么先将短整数进行位数扩展,过程中保持数据不变,然后按照长整数的数据类型解析数据。
  • 整数与浮点数之间
    • 浮点数转整数:截取整数部分。
    • 整数转浮点数:小数部分为0,整数部分与整数相等。
  • float 与 double之间
    • double 转 float会丢失精度。
    • float 转 double不会丢失精度。

注意:整数在内存中都是以补码的形式存储的。


我的qq:2442391036,欢迎交流!


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2035350.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

24年日语能力(JLPT)考试报名流程图解

报名方式 搜索JLPT中国教育考试网&#xff0c;在线报名&#xff0c;一般学生党从教育网入口登录&#xff0c;社会人士从公网入口登录 报名时间 N1-N5 8月20日 7:00 - 8月27日14:00 注册时间 8月13日7:00 - 8月27日14:00 报名步骤 阅读报考提示&#xff0c;注册个人信息→…

此处不允许使用 ‘空‘ 类型

说明&#xff1a;受最近看的书《设计模式之美》&#xff08;小争哥&#xff09;的影响&#xff0c;最近编码有意将一些业务逻辑写在对象里面&#xff0c;增强封装性。在此记录一次项目启动时的报错&#xff0c;如下&#xff1a; 原因&#xff1a;当你在实体类对象中&#xff0c…

UniApp开发的开源工厂设备管理维护系统

本文来自&#xff1a;UniApp开发的开源工厂设备管理维护系统 - 源码1688 前端小程序演示地址&#xff1a; 后台测试网址&#xff1a; https://shebeiguanli.azheteng.cn/pyswkAWtig.php/addon?refaddtabs 测试账户&#xff1a; admin 测试密码&#xff1a; admin888 前端…

【Python】python泰坦尼克号生存预测 (源码+数据集+PPT+论文)【独一无二】

&#x1f449;博__主&#x1f448;&#xff1a;米码收割机 &#x1f449;技__能&#x1f448;&#xff1a;C/Python语言 &#x1f449;公众号&#x1f448;&#xff1a;测试开发自动化【获取源码商业合作】 &#x1f449;荣__誉&#x1f448;&#xff1a;阿里云博客专家博主、5…

黑神话悟空游戏攻略大全 黑神话悟空内存占用多少 国产3A级游戏《黑神话:悟空》评测代码已发 黑神话悟空测试画质130g MacBook可以玩黑神话悟空吗

《黑神话&#xff1a;悟空》的评测代码已向媒体与测评人员发放&#xff0c;评测解禁日期定在8月16日。目前发放的评测代码仅限于PC版&#xff0c;并未涉及PS5版。《黑神话&#xff1a;悟空》将于8月20日发售&#xff0c;登陆PC(Steam/Epic/WeGame)和PS5。玩家将扮演一位“天命人…

Mybatis原理分析

一、总结 MyBatis的基本工作原理就是&#xff1a;先封装SQL&#xff0c;接着调用JDBC操作数据库&#xff0c;最后把数据库返回的表结果封装成Java类。 1. JDBC有四个核心对象&#xff1a; &#xff08;1&#xff09;DriverManager&#xff0c;用于注册数据库连接。 &#xf…

基于单片机的智能楼道灯光控制系统设计

摘要&#xff1a;基于单片机的智能楼道灯光控制系统设计由人体感应模块、光照强度检测模块、灯光控制模块、声音传感器模块、声光报警模块等组成。以单片机为核心&#xff0c;通过检测光照强度和红外人体感应相结合&#xff0c;实现了对楼道内灯光的控制&#xff0c;从而达到节…

vue-cli 中 配置 productionSourceMap 为 false 失效?

背景 最近 发现 vuecli 构建的 项目中配置的 productionSourceMap 为 false 后 &#xff0c;生产代码 还是能够看到 sourceMap 文件 。 原因 生效前提条件 得设置 NODE_ENV 为 production 才会生效&#xff01; 解决 直接修改生产环境的配置 NODE_ENV 为 production 直接覆…

二.PhotoKit - 相册权限(彻底读懂权限管理)

引言 用户的照片和视频算是用户最私密的数据之一&#xff0c;由于内置的隐私保护功能&#xff0c;APP只有在用户明确授权的前提下才能访问用户的照片库。从iOS14 开始&#xff0c;PhotoKit进一步增强了用户的隐私控制&#xff0c;用户可以选择指定的照片或者视频资源的访问权限…

阿里淘天landing,是结束也是新的开始(附校/社招内推码)

阿里3个多月landing成功&#xff0c;是结束也是新开始&#xff0c;望我们往后一切顺利~ 因为个人发展规划&#xff0c;今年开始找工作&#xff0c;但负责的业务实在繁忙&#xff0c;所以一边面试一边整理资料&#xff0c;每天都在挤海绵。 今年的就业形势着实不乐观&#xff0c…

NPN传感器与汉姆485总线驱动器限位功能使用

传感器输出的引脚电平是由传感器是常闭还是常开决定的&#xff1b;light on和 dark on决定的是触发信号&#xff1b; PNP-NO常开&#xff1a;在没有信号触发时&#xff0c;输出线是悬空的&#xff08;即VCC电源线和OUT线断开&#xff09;&#xff0c;输出为低电平或不确定状态…

【推荐】免费一年期的SSL证书现在哪里可以申请到

免费一年期的SSL证书虽然不像以前那样普遍易得&#xff0c;但仍有部分途径可以申请到。以下是一些可能的申请渠道&#xff1a; JoySSL 特点&#xff1a;JoySSL是自主品牌SSL证书&#xff0c;安全性和兼容性都有保障。它提供教育版和政务版域名的一年期免费DV单证书。申请流程&…

java中RSA分段加解密及Data must not be longer than异常处理

谈到RSA非对称加密&#xff0c;作为开发的我们第一想到的是安全&#xff0c;几乎不会被破解&#xff0c;以及公钥加密&#xff0c;私钥解密这些。在Java代码中&#xff0c;我们常使用一些现成的工具类如hutool中提供的工具类、网上在线的或者博客上的RSAUtils工具类来实现公钥私…

解决BkwinProject无法编译运行问题

#ifdef _UNICODE // 如果定义了 _UNICODE&#xff0c;这意味着程序正在使用 Unicode 字符集进行编译。 // Unicode 字符集是现代 Windows 应用程序普遍使用的字符编码方式&#xff0c;支持多语言字符。#if defined _M_IX86 // 如果定义了 _M_IX86&#xff0c;这意味着程序正…

【源码交付】数字化产科管理平台:一个集孕期产检、健康宣教、随访、住院、产后42天管理的专科管理系统

项目介绍&#xff1a; 数字化产科管理平台是一个集孕期产检、健康宣教、随访、住院、产后42天管理的专科管理系统&#xff0c;由门诊、住院、数据统计三大功能模块组成&#xff0c;与院内系统HIS/LIS/PACS数据对接&#xff0c;实现以孕妇为中心的全面、高效、多元的全周期服务…

用的到linux-系统性能监控(内存、CPU、硬盘、IO)-Day6

前言&#xff1a; 在Linux系统中&#xff0c;实时监控系统的资源使用情况&#xff08;如内存、硬盘、CPU、网络和IO等&#xff09;是非常重要的&#xff0c;它可以帮助你了解系统的健康状况&#xff0c;及时发现潜在的性能瓶颈或问题。下面将介绍一些常用的命令和工具&#xff…

私服(Nexus)相关笔记

目录 Nexus服务器安装与启动 仓库分类与手动上传组件 私服资源获取 仓库分类 IDEA环境中资源上传与下载 Nexus服务器安装与启动 私服 Nexus是Sonatype公司的一款maven私服产品下载地址: https://help.sonatype.com/repomanager3/download 解压到自己放置资源的地方 输入…

YOLOV8多类别训练时遇到的大坑

本篇文章帮大家避坑。。。 如果要训练六个类别的数据集&#xff0c;按照我以下做数据集文件夹 有test、train、valid、还有一个data.yaml的配置文件。 每个下面都有images和labels 我们拿train的imges来说&#xff0c;它里面存放着你六个类别的图片 labels也要跟上面的图片名…

AH8681锂电升压3.7升5V升12V 2A可支持QC2.0 3.0

135.3806.7573在探讨AH8681这款专为3.7V升压5V至12V&#xff0c;并具备2A输出能力&#xff0c;同时兼容QC2.0与QC3.0快充协议的升压芯片时&#xff0c;我们不得不深入其技术细节、应用场景、设计优势以及市场定位等多个维度&#xff0c;以全面理解其在现代电子设备中的重要作用…