嵌入式面试刷题(day1)

news2024/11/24 18:25:24

文章目录

  • 前言
  • 一、由for( ; ;)引出的一系列问题
  • 二、sizeof和strlen的误区
  • 三、字符串转义字符带来的问题
  • 四、结构体概念模糊
  • 五、!和~概念分不清
  • 六、switch case误区
  • 七、短路运算
  • 八、复合赋值运算符带来的问题
  • 九、什么是左值什么是右值
  • 十、struct和union
  • 总结


前言

最近我打算出一套笔试刷题的总结,帮助大家解决一些笔试的经典和容易出错的题目,并且将这些知识点讲解明白。
我将会在牛客网上刷题,节省大家的时间将最值得关注的题目呈现给大家。

一、由for( ; ;)引出的一系列问题

在C/C++的for循环中,我们可以省略循环语句的各个参数,包括初始化语句、循环条件和增量表达式。当省略这些参数时,编译器会按照一定的规则进行默认处理。

下面是省略循环参数时的默认处理规则:

1.省略初始化语句:如果省略初始化语句,那么循环开始之前的初始化操作就会被忽略。通常情况下,我们会在循环外部或者在循环之前对循环变量进行初始化。

2.省略循环条件:如果省略循环条件,那么循环将会一直执行,直到遇到 break 或 return 等跳出循环的语句。

3.省略增量表达式:如果省略增量表达式,需要确保循环体内部有适当的语句改变循环变量的值,以避免出现无限循环。否则,循环可能会无限执行,造成程序异常。

下面是一个例子来说明for循环省略参数的情况:

for (;;) {
  // 无限循环,没有显式的初始化、条件和增量表达式
  // 需要在循环体内部通过其他方式改变循环变量的值或者使用跳出循环的语句来终止循环
}

值得注意的是,虽然可以省略for循环的各个参数,但是在实际编码中,建议根据具体情况选择合适的方式来书写循环语句,以增加代码的可读性和易于维护性。

涉及到的题目:

int i = 0;

for(i = 0; ; i++)
{
	printf("Hello\n");
}

根据上面我们讲解到的规则,这里是省略了for循环中的条件,那么代码执行的次数就是无数次,这将是一个死循环。

二、sizeof和strlen的误区

这一道题目其实是没有什么难度的,主要就是要搞清楚sizeof和strlen的原理。
sizeof是计算字符串占内存的大小,而strlen是计算字符串的长度,并且只计算\0前字符串的个数。
根据这个原理我们可以轻松解决这个题目。
在这里插入图片描述

三、字符串转义字符带来的问题

要得到下面这道题目的答案我们得先了解字符串转义字符的概念。
在这里插入图片描述
在C语言中,转义字符是一种特殊的字符序列,用于表示在普通字符中无法直接表示的特殊字符或者控制字符。转义字符以反斜杠(\)作为前缀,后面跟着一个或多个字符。

下面是一些常见的字符串转义字符及其含义:

':单引号。用于表示普通的单引号字符。
":双引号。用于表示普通的双引号字符。
\:反斜杠。用于表示普通的反斜杠字符。
\n:换行符。用于表示换行操作,在字符串中添加一个换行符。
\t:制表符。用于表示水平制表操作,在字符串中添加一个制表符。
\r:回车符。用于表示回车操作,在字符串中添加一个回车符。
\b:退格符。用于表示退格操作,在字符串中添加一个退格符。
\f:换页符。用于表示换页操作,在字符串中添加一个换页符。
\0:空字符。用于表示空字符,常用于字符串的结尾,表示字符串的结束。
\xhh:十六进制转义字符。用于表示一个字符的十六进制值,hh为两个十六进制数字。

那么现在我们来分析一下答案为什么是9吧。

\:这是转义字符\的转义表示,表示一个反斜杠字符\。

141:普通字符串

\141:同样是八进制转义字符,也表示ASCII码为141的字符。

abc:这是普通的字符序列,包含字符a、b和c。

\t:这是转义字符,表示一个水平制表符。

1 + 3 + 1 + 3 + 1 = 9。

四、结构体概念模糊

在这里插入图片描述
这里需要注意的点就是定义结构体类型是不会分配内存的。只有当定义结构体变量时才会分配内存。

结构体类型定义:

typedef struct {
    int x;
    int y;
} Point;

定义一个结构体变量,这里才会分配内存空间。

Point p;

五、!和~概念分不清

在这里插入图片描述
在C语言中,~和!是两个不同的运算符,分别表示按位取反和逻辑取反。
这里很容易将他们混淆。

1.~按位取反:
~是一个一元位运算符,用于对操作数的每个位执行逻辑取反操作。它适用于整数类型(如int、char等)和无符号整数类型(如unsigned int、unsigned char等)。当对一个二进制数进行按位取反运算时,每个位的0会变为1,1会变为0。

示例:

unsigned int x = 10; // 二进制为 0000 1010
unsigned int result = ~x; // 结果为 1111 0101,即4294967285

在进行按位取反运算时需要注意,结果的位数与操作数的位数相同,因此它不会改变操作数的类型。

2.!逻辑取反:
!是一个一元逻辑运算符,用于对操作数执行逻辑取反操作。它适用于任何可以转化为布尔值的表达式,返回值为int类型,结果为1(真)或0(假)。!运算符会将其操作数的值为0(假)时返回1(真),非0值为(真)时返回0(假)。

示例:

int x = 10;
int result = !x; // 结果为0,因为x的值为非0,逻辑取反结果为0(假)

在使用!进行逻辑取反时,非零值会被视为真,而0会被视为假。

总结:

~按位取反运算符用于对整数类型进行按位取反操作,逐位翻转0和1。
!逻辑取反运算符用于对表达式求逻辑反,将非0值取反为0,将0取反为1。

六、switch case误区

现在我们看到下面这个题目,很多同学都会犯错认为输出的结果就是1,其实这是错误的。
当没有遇到break时,无论case中的条件是否符合都会执行,只有当遇到break时才会退出。
所以这题输出的结果是3。

#include <stdio.h>

int main(void)
{
    int x = 1;
    int i = 0;

    switch (x)
    {
    case 1:
        i++;
    case 2:
        i++;        
    case 3:
        i++;       
        break;
    }

    printf("i = %d\n",i);

}

七、短路运算

我们来看到下面的一道题目:
看起来这一题是非常简单的,但是却又是非常容易出问题的。有的同学可能是会认为结果为3,但是最后的结果却是2,这是为什么呢?

根据短路规则,在逻辑或运算符||中,如果左侧表达式为真,那么整个表达式的结果就是真,并且不会再计算右侧的表达式。只有当左侧表达式为假时,才会计算右侧表达式。

在这个代码中,首先判断i > 4的结果是否为真,即比较i是否大于4。由于i的值为5,条件成立,即左侧表达式为真。因此,右侧的表达式j++ > 1不会被计算,也就是不会执行j++的操作。

因此,即使j的初始值为2,右侧的自增操作j++也不会执行。所以,j的值保持为2,并且程序会打印出j的值,即输出结果为j : 2。

#include <stdio.h>
#include <string.h>

int main(void)
{
    int i = 5;
    int j = 2;

    if((i > 4) || (j++ > 1))
    {
        printf("j : %d\n", j);
    }

    return 0;
}

那么下面我们再来看一个&&的短路运算:

根据短路规则,在逻辑与运算符 && 中,如果左侧的表达式为假,整个表达式的结果就是假,并且不再计算右侧的表达式。只有当左侧表达式为真时,才会计算右侧的表达式。

#include <stdio.h>

int main(void)
{
    int i = 1;
    int j = 2;

    if ((i == 1) && (j++ > 1))
    {
        printf("j: %d\n", j);
    }

    return 0;
}

在这个代码中,首先判断 i == 1 的结果是否为真,即比较 i 是否等于 1。由于 i 的值为 1,条件成立,即左侧表达式为真。因此,接下来会计算右侧的表达式 j++ > 1。

在右侧的表达式中,会先判断 j++ 是否大于 1。由于 j 的初始值是 2,所以 j++ 的结果为 2,不大于 1。因此,该表达式的结果为假。

根据短路规则,因为左侧表达式为真但右侧表达式为假,整个逻辑与的结果也为假。所以,printf 语句不会被执行。

因此,在该代码中,j 的值仍然是初始值 2,而不是 3。

八、复合赋值运算符带来的问题

这一题有很多同学可能会将x *= i + 3等价为 x =x * i + 3,这就会导致错误的结果,实际上x = i + 3是等价为x = x(i+3)的。

#include <stdio.h>
#include <string.h>

int main(void)
{
    int x = 5;
    int i = 3;
    x *= i + 3;

    printf("%d\n", x);

    return 0;
}

九、什么是左值什么是右值

下面这个表达式是正确的吗?很多小伙伴可能都会犯错,其实这是一个错误的表达式。

++(a++);

在一个表达式中,将同一个变量作为左值(左侧操作数)和右值(右侧操作数)进行修改,会导致未定义行为。

在 C 语言中,左值(lvalue)和右值(rvalue)是用于描述表达式中的值的属性。

左值(lvalue):

左值是指可以出现在赋值运算符左侧的表达式。
左值可以是变量、数组元素、结构体成员等,它们在内存中有对应的存储位置。
左值可以被修改(赋值)。
左值可以出现在引用和取址操作符(如*和&)的操作数中。
例如:

int x = 10;       // x 是左值,可以被赋值
int arr[5];       // arr 是左值,数组名可以作为左值
arr[0] = 5;       // arr[0] 是左值,数组元素可以作为左值
struct Point { int x; int y; } p;
p.x = 1;          // p.x 是左值,结构体成员可以作为左值

右值(rvalue):

右值是指可以出现在赋值运算符右侧的表达式。
右值可以是常量、字面值、表达式的结果等。
右值没有对应的存储位置。
右值不能被直接修改。
右值不能出现在引用和取址操作符的操作数中。
例如:

int a = 5;        // 5 是右值,常量可以作为右值
int b = a + 3;    // a + 3 是右值,表达式的结果可以作为右值
int c = func();   // func() 是右值,函数调用表达式的结果可以作为右值

需要注意的是,有一些表达式既可以作为左值又可以作为右值,例如变量自身的标识符。根据上下文,同一个表达式可以被视为左值或右值。

例如:

int x = 10;      // x 是左值,在赋值语句中作为左操作数
int y = x;       // x 是右值,在赋值语句中作为右操作数
int *ptr = &x;   // &x 是右值,取址运算符的操作数

总结一下,左值表示可被赋值和具有存储位置的表达式,而右值则表示不可被直接赋值和没有存储位置的表达式。

十、struct和union

在这里插入图片描述
结构体 (struct) 和联合体 (union) 都要遵循字节对齐规则。字节对齐是指在内存中分配存储空间时,按照一定的规则将数据对齐到特定的内存地址。

对于结构体和联合体中的成员,编译器通常会根据其类型和对齐规则要求进行对齐。对齐要求通常取决于平台和编译器的设置,可以通过编译器选项或预处理指令进行配置。

常见的对齐规则包括按字节对齐、按类型对齐以及按照默认对齐规则对齐。例如,对于 int 类型的成员,通常要求按照 4 字节对齐,而 double 类型的成员通常要求按照 8 字节对齐。

结构体的大小必须是成员中最大对齐要求的倍数。

所以这题的结果为16 + 8 = 24。

总结

下篇文章继续为大家讲解笔试好题。

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

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

相关文章

cuda sample-asyncAPI(01)

C:\ProgramData\NVIDIA Corporation\CUDA Samples\v11.0\0_Simple\asyncAPI 这个例子说明了CUDA事件在GPU计时和CPU与GPU重叠执行方面的应用。 事件被插入到CUDA的调用流中。 由于CUDA流调用是异步的&#xff0c;CPU可以在GPU执行时进行计算&#xff08;包括主机和设备之间的DM…

【前端系列】前端如何使用websocket发送消息

序言 今天来学习一下前端如何使用websocket发送消息 1 基础介绍 1.1 什么是WebSocket WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议&#xff0c;它可以让客户端和服务器之间进行实时的双向通信。与传统的 HTTP 请求不同&#xff0c;WebSocket 使用了一个长连接&…

Django实现简单的音乐播放器 1

使用django框架开发一个简单的音乐播放器。 效果&#xff1a; 目录 环境准备 安装django 创建项目 创建应用 注册应用 配置数据库 设置数据库配置 设置pymysql库引用 创建数据库 创建数据表 生成表迁移文件 执行表迁移 配置时区 配置语言 配置子应用路由 在pla…

外部中断实验(stm32)

目录 EXIT的相关代码exit.cexit.h LED的相关代码KEY的相关代码BEEP的相关代码main.cGPIO 跟中断线的映射关系图 说明&#xff1a;以下内容参考正点原子资料 EXIT的相关代码 exit.c void EXTIX_Init(void) { EXTI_InitTypeDef EXTI_InitStructure;NVIC_InitTypeDef NVIC_InitS…

el-dialog中,el-form中表单信息未收集齐全时禁用提交按钮,动态控制按钮是否禁用

需求 在el-dialog中放置了一个表单&#xff0c;打开el-dialog时&#xff0c;表单没有收集内容&#xff0c;各项为空&#xff0c;此时表单的提交按钮被禁用&#xff0c;只有每个表单项都收集到内容时&#xff0c;才会将提交按钮设置为可用 预期效果 解决方案 <el-button c…

多线程进阶学习(高并发、线程池、使用场景)

文章目录 1、线程基础知识1.1、线程和进程线程和进程的区别&#xff1f; 1.2、并行与并发并行与并发有什么区别&#xff1f; 1.3、线程的创建方式创建线程的方式有哪些&#xff1f;刚才你说过&#xff0c;使用runnable和callable都可以创建线程&#xff0c;它们有什么区别呢&am…

OpenCV读取一张8位无符号三通道图像并显示

#include <iostream> #include <opencv2/imgcodecs.hpp> #include <opencv2/opencv.hpp> #include

Kafka生产者概述

【Kafka】Kafka生产者概述 文章目录 【Kafka】Kafka生产者概述1. 生产者1.1 生产者消息发送流程1.1.1 发送原理1.1.2 生产者重要参数列表 1.2 异步发送 API1.2.1 普通异步发送1.2.2 带回调函数的异步发送 1. 生产者 1.1 生产者消息发送流程 1.1.1 发送原理 在消息发送过程中…

企业数字化转型成功的标准是什么?

​近几年来&#xff0c;数字化转型一直是企业管理者的热议话题&#xff0c;那么&#xff0c;到底该以什么标准来衡量转型成效&#xff0c;又如何向管理者交出一份满意的答卷呢&#xff1f; 为了确保转型效果与目标的一致性&#xff0c;在规划数字化转型之初&#xff0c;选择正…

JVM — JDK11垃圾回收器 ZGC

1. ZGC介绍 ZGC&#xff08;The Z Garbage Collector&#xff09;是 JDK 11 中推出的一款低延迟垃圾回收器&#xff0c;为实现以下几个目标而诞生的垃圾回收器&#xff0c;停顿时间不超过 10ms&#xff0c;停顿时间不会因堆变大而变长&#xff0c;支持 8MB~4TB 级别的堆&#…

【专题速递】MD-VQA、AB实验、音视频质量建设以及在手机上的应用

// 怎样才能更好地进行QoE优化&#xff1f;音视频技术在用户侧的挑战又是什么&#xff1f;7月29日LiveVideoStackCon上海站QoE与数据驱动专场&#xff0c;为您解答。 QoE与数据驱动 在音视频应用里&#xff0c;获得了大量的用户上报数据&#xff0c;包括但不限于音视频质量数…

ASM汇编语言环境安装

以前是学习过8位单片机的&#xff0c;忘记的差不多了。现在需要使用64位的汇编语言&#xff0c;准备重新学习。 64位的编程环境使用ebe&#xff0c;sf上有的下载&#xff1a; 这个软件不错&#xff0c;可以调试64位的汇编语言&#xff0c;寄存器也可以实时查看。 32位的编程开…

pcl经典算法60例——(1)打开并显示点云,窗口PCLVisualizer嵌入MFC的picture control

一、搭建MFC框架 1、环境说明 本教程为vs2022&#xff0c;pcl1.12.1版本&#xff0c;其他版本自己进行适当修改&#xff0c;仅供参考。 2、方法步骤 (1)新建项目&#xff0c;选择“基于对话框”&#xff0c;然后点击“下一步” 二、配置pcl环境 关于配置环境&#xff0c;网…

centos安装常见软件

安装git # 方式一&#xff1a;yum install git -y# 方式二&#xff1a;&#xff08;开发会用的软件&#xff09;yum -y groupinstall "Development tools"# 执行下面这条yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel…

点云实战及Python路径实验

点云实战 文章目录 点云实战python 有关路径实验下一级目录上一级目录 学习PointNet论文&#xff08;https://arxiv.org/abs/1612.00593&#xff09;并实践 python .\show_seg.py --dataset ../data/shapenet --model .\seg\seg_model_Chair_2.pth python 有关路径实验 下一级…

kotlin Flow系列之 - 冷流SafefFlow源码解析之 - Safe在那里?

本文涉及源码基于kotlinx-coroutines-core-jvm:1.7.1 kotlin 协成系列文章: 你真的了解kotlin中协程的suspendCoroutine原理吗? Kotlin Channel系列&#xff08;一&#xff09;之读懂Channel每一行源码 kotlin Flow系列之-SharedFlow源码解析 kotlin Flow系列之-StateFlow源码…

【java】隐藏手机号中间四位

String phone "12334543437";phone phone.replaceAll("(\\d{3})\\d{4}(\\d{4})", "$1****$2");System.out.println(phone);

Mycat【什么是Mycat、Mycat与其他中间件区别、Mycat应用场景、核心概念详解、Mycat原理】(一)-全面详解(学习总结---从入门到深化)

目录 Mycat概述_什么是Mycat Mycat概述_Mycat与其他中间件区别 Mycat概述_Mycat应用场景 Mycat概念_核心概念详解 Mycat概述_Mycat原理 Mycat部署安装_MySQL主从复制概述 Mycat概述_什么是Mycat 什么是Mycat Mycat是数据库中间件&#xff0c;所谓中间件数据库中间件是连…

CentOS详细安装教程

文章目录 前言一、下载所需版本的 CentOS二、创建虚拟机三、安装 CentOS 前言 本文在虚拟机上安装 CentOS Linux release 7.6.1810 版本的操作系统&#xff0c;仅作为安装记录。 一、下载所需版本的 CentOS 1、进入 CentOS 官网&#xff1a;https://www.centos.org/download/…

React类组件

1. React组件 将页面按照界面功能进行拆分&#xff0c;每一块界面都拥有自己的独立逻辑&#xff0c;这样可以提高项目代码的可维护性。其中React组件分为两种&#xff0c;一种是类式组件&#xff0c;一种是函数式组件。这里我们将的是比较常用的类式组件&#xff0c;但是在后续…