嵌入式C/C++语言笔试题(01)

注明:本笔记的题目来源于B站的 UP主:嵌入式技术公开课,观看地址为:

C语言笔试题,C++笔试题,嵌入式笔试题,面试题,难点疑点解析(持续更新)_哔哩哔哩_bilibili

(笔记是理解题目后自行编写的,希望对读者有帮助~~~~,当然,推荐各位去观看b站的视频,up主讲得很好,我只是在这里记录我对题目的理解,若有不对的地方,请多见谅~~~)

1、下面程序输出的结果是?   (视频中的 第 81 集)

int main(void)

{

        char x = 0xFF;

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

        return 0;

}

解析:

        我们先解读一下这道题,char x=0xff,这一个16进制数,二进制表示为 1111 1111,十进制为255,然后在printf里以%d的格式输入,x--。
这道题答案是 -1。printf中的 %d 输出是10进制输出,而且是有符号的十进制,又因为 x 内存中存储的形式为 1111 1111,最高位是1,以 %d 的形式输出,那就说明x一定是负数,有符号数在内存中是以补码的形式存储的。将其转化为 10 进制就相当于求他的原码,就是 1 000 00001 (不熟的就去看看补码、反码、原码的转换哈),也就是 -1 。
总结一下这道题所包含的知识点。总的来说,这道题所包含的知识点有,第一 :x-- 是先用了 x,再进行 -- 操作,第二:printf中的 %d 输出是10进制输出,而且是有符号的十进制。第三:补码、反码、原码的转换。

2、假如有如下代码:(视频中的 第 66 集)

float a=1.0; 则 cout <<  (int &)a  << endl; 的输出结果为?

解析:

        这道题很多人可能就会认为是强制类型转换,就输出 1了。但这是错的。因为 a 是 float 类型, 所以应该是 a 在内存中存储的数,然后将存储的数用整形数表示出来。置于float 类型在内存中是如何存储的,这里不过多解释,请自行查资料学习。最终的结果为:1065353216
(int &)a   ----> 给变量 a 声明了一个匿名引用,cout 输出的是这个匿名引用的值。
这道题的知识点为 float 类型在内存中是如何存储的,然后将存储的数用整形数表示出来。

3、请说明下面代码的运行结果:        (视频中的 第 30 集)

int main(void)

{

        int i;

        i=10;

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

        printf("%d\n",sizeof(i++));

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

        return 0;

}

解析:

        这道题输出的是(不考虑换行符):10   4   10
        为什么呢?不是执行++操作了吗?首先,我们得先知道sizeof是一个运算符,他不是一个函数,sizeof(i++) 是不会执行 i++操作的。(在C++11 的标准中有写到,i++是不会被解析,被运算的,理解记住就好了)

4、阅读下面代码,看这段代码是否有问题,如果有问题请指出问题。        (视频中的 第 14 集)

#include<stdio.h>

#include<string.h>


struct std

{
        unsigned int id;

        char *name;

        unsigned int age;
}per;



int main(void)

{

        per.id = 0001;

        strcpy(per.name,"Micheal Jackson");

        per.age = 20;

        printf("%s\n", per.name);

        return 0:

}

解析:

        这道题运行起来其实是会报经典的段错误的(编译没问题),这就说明是我们的指针有问题,用法不恰当,所以才会报错的。那问题出现在哪呢?
这道题其实是考察我们,结构体中使用字符数组还是字符指针?在上面,struct std 的 name 成员使用了 char *类型的指针,那么在这个结构体里面,char * 类型的这个指针就只能存放四个字节,用这四个直接去拷贝 "Micheal Jackson" ,这显然是不对的。第二个有问题的地方就是,我们通常在申请指针变量的时候(暂时不用),是要将指针初始化为 NULL的,但是 per.name 没有指向任何东西,是个野指针(有可能会指向不可访问的地址),这就有可能会引发一系列的问题。所以,我们在结构体中要使用字符数组。
        要是我就想用   char *name 呢? 我们可以 直接 per.name = "Micheal Jackson" ;把字符串的地址直接赋值给 per.name 。但是不推荐,因为 name 指向的 字符串并不存在于我们的结构体内存中, per.name只是指向了我们赋值的字符串的地址。我们申请结构体,希望的是字符串在我们的内存中,而不是在别的内存。

5、请描述一下下面语句的含义:        (视频中的 第 2 集)

char *(*c[10]) (int **p);

解析:

(1)char *pt[10];       pt是数组,数组是由10个char*指针所组成。
(2)char (*pt)[10];    pt是指针,pt指针指向了由10个char元素构成的数组,即pt是数组指针
(3)c[10]        ----》c是数组
(4)*c[10]    ---- 》c是一个指针数组
(5)char *(*c[10])(int **p)    ------》     c数组中每一个元素都是函数指针,其所指向的函数返回值是char*类型,且函数带一个指向指针的指针。

6、下面代码的运行结果是什么?假设在32位系统中        (视频中的 第 7 集)

int main(void)

{

        unsigned int a = 6;

        int b= -20;

        (a+b > 6) ? puts(">6") : puts("<=6");

        return 0;

}

解析:

        题目就不解读了。该题打印出的结果为 >6 。该题是考察了两个知识点一个是有符号数与无符号数相加,会自动的进行强制类型转换;第二个是数字在内存中是如何存储的正数原码存储,负数补码存储。
有符号数与无符号数相加,自动的进行强制类型转换的原则:将有符号数自动转化为无符号数据,也就是说 会将 -20 的原码为 1000 0000 0000 0000 0000 0000 0001 0100,则在内存中存储以补码的形式存储,即 1111 1111 1111 1111 1111 1111 1110 1100,与6相加后则为1111 1111 1111 1111 1111 1111 1111 0010 ,这个数转为无符号数很大(可以理解为在前面加个0,即求 0 1111 1111 1111 1111 1111 1111 1111 0010十进制的大小了),肯定比 6 大呀。
但这里我们还要了解一个知识点,如下:
printf(" a + b = %d\n",a+b); 这有输出什么呢?答案是 -14 。为什么呢?难道上面讲错了嘛?不是的,这是因为 printf中的 %d 输出是10进制输出,而且是有符号的十进制,输入的形式还是以负数在内存中存储的形式一样。要是想输出无符号的结果,则可以这样输出 printf(" a + b = %ud\n",a+b); 这样a+b的值就变得很大了(至于多少,可以自行操作一遍)

7、阅读下面代码,看这段代码是否有问题,如果有问题请指出问题        (视频中的 第 81 集)

char*p1 ="ABCABC";

char *p2=(char *) malloc(strlen(p1));

strcpy(p2, pl);

解析:

        这段代码是有问题的,我们要知道,strlen 统计字符串长度的时候是不包含 '\0' 的,也就是说上面的 p2 长度为 6 ,而 strcpy 拷贝字符串的时候是包含 '\0' 的,也就是拷贝字符串的长度为 7 ,这显然是不对的。正确的做法是: (char *) malloc(strlen(p1+1)) 申请内存的时候在后面 + 1

8、请说明下面代码的运行结果:                (视频中的 第 31 集)

unsigned char *pl;
unsigned long *p2;

p1 = (unsigned char *)0x801000;
p2 = (unsigned long *)0x801000;


请问:

p1 + 5 = ?
p2 + 5 = ?

解析:

       要做出这道题,首先我们得知道指针+1 到底是什么。指针+1不是地址加1,所增加的地址值为这个指针指向的类型所占用的内存大小。也就是,指针+1 == 地址 + sizeof(指向数据的类型)。
所以,
p1 + 5 = 0x801000+ sizeof ( unsigned char ) * 5 = 0x801000 + 5 = 0x801005
p2+ 5 = 0x801000 + sizeof ( unsigned long ) * 5 = 0x801000 + 20=0x801014

9、下面的函数有什么错误:        (视频中的 第 32 集)

int square(volatile int * pt)
{
    
    return (*pt) * (*pt);

}

解析:

        首先,我们得了解C语言中 volatile  关键字的作用,它的作用就是使得 pt 指针每次取值的时候,都要从指定的内存寄存器中取值,这就会出现一个问题。假定第一次 (*pt) 取值的时候 pt 指向内存的值为 3 ,而在第二次 (*pt)  取值的时候,内存中的值就有可能发生变化了,取出来的就不是 3 了。这显然和我们要实现的功能不符合。
        那怎么改呢?要么就不加  volatile ,要是加上,就:
int square(volatile int * pt)
{
    int a =  *pt;

    return a * a;

}

10、指出下面代码的输出,并解释为什么?   假定在 32 位系统中  (视频中的 第 34 集)

#include <stdio.h〉
int main(void)
{

    int a[5]= {1,2,3,4,5};

    int *pt =(int *)(&a + 1);

    printf("%d, %d\n",*(a + 1),*(pt - 1));

    return 0;
}

解析:

        对于这道题,我们首先得知道 a 与 &a 分别代表什么。
a:数组名,表示数组中第一个元素的地址,指向的是数组中元素的地址
&a:整个数组在内存中的起始地址,指向的是整个数组作为一个单元的起始地址
二者的所指向的地址一样,但所表达的含义却不一样。
所以说,a+1 表示的是,a 指向了第二个元素,其向后移动了 sizeof(int)= 4 个字节。
而 &a + 1  表示的是 a 指向了第二个元素,其向后移动了 5 * sizeof(int)= 20个字节。
所以,*(a + 1) =2, *(pt - 1) = 5

嵌入式C/C++语言笔试题(01)就先告一段落了,我打算的是以 10 道题为一篇,这样读者看起来也不用太累,每天学一点。

期待一下我的嵌入式C/C++语言笔试题(02)吧!

https://blog.csdn.net/Breezekyu/article/details/138282621

  • 27
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值