嵌入式面试题(C/C++)

概念区分

  • 变量的声明和定义有什么区别
为变量分配地址和存储空间的称为定义,不分配地址的称为声明。一个变量可以在多个地方声明,但只能在一个地方定义。加入extern修饰的是变量的声明,说明此变量将在文件以外或在文件后面部分定义。
说明:很多时候一个变量,只是声明,不分配内存空间,知道具体使用时才初始化,分配内存空间,如外部变量。
  • sizeof和strlen的区别
sizeof是一个操作符(关键词),strlen是库函数。
sizeof的参数可以是数据的类型,也可以是变量,而strlen只能以结尾为‘\0‘的字符串作参数。
编译器在编译时就计算出了sizeof的结果。而strlen函数必须在运行时才能计算出来。
sizeof计算的是数据类型占内存的大小,而strlen计算的是字符串实际的长度。
  • 写一个“标准”宏MIN
#define min(a,b) ((a)<=(b)?(a):(b))  //加圆括号,保护数据
  • 一个指针可以是volatile吗?
可以,因为指针和普通变量一样,有时也有变化程序的不可控性。常见例:子中断服务子程序修改一个指向一个buffer的指针时,必须用volatile来修饰这个指针。
  • a 和 &a 有什么区别请写出以下代码的打印结果,主要目的是考察a和&a的区别。
#include<stdio.h>   
int main( void )   
{   
     int a[5]={1,2,3,4,5};  
     int *ptr=(int *)(&a+1);  
     int *ptr2 = (int *)(a + 1) ;
     printf("%d,%d,%d,%d\n",*(a+1),*(ptr-1),*ptr2,*(ptr2+1));   
     return 0;  
 }

输出结果:2,5。

(a+1)这个比较简单,很好理解,就是取数组a的首地址的下一个值;数组名a可以作数组的首地址,而&a是数组的指针,指针ptr指向整个数组地址的下一块空间 ,通过(ptr-1)就可获取数组的最后一个值。思考,将原式的int *ptr=(int *)(&a+1);改为int *ptr=(int *)(a+1);时输出结果将是什么呢?2,5,2,3
————————————————
版权声明:本文为CSDN博主「Bruceoxl」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/u013162035/article/details/78308140

  • 简述C、C++程序编译的内存分配情况
C、C++中内存分配方式可以分为三种:
(1)从静态存储区域分配:
内存在程序编译时就已经分配好,这块内存在程序的整个运行期间都存在。速度快、不容易出错,因为有系统会善后。例如全局变量,static变量等。
(2)在栈上分配:
在执行函数时,函数内局部变量的存储单元都在栈上创建,函数执行结束时这些存储单元自动被释放。栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。
(3)从堆上分配:
即动态内存分配。程序在运行的时候用malloc或new申请任意大小的内存,程序员自己负责在何时用free或delete释放内存。动态内存的生存期由程序员决定,使用非常灵活。如果在堆上分配了空间,就有责任回收它,否则运行的程序会出现内存泄漏,另外频繁地分配和释放不同大小的堆空间将会产生堆内碎块。

一个C、C++程序编译时内存分为5大存储区:堆区、栈区、全局区、文字常量区、程序代码区。
  • 链表与数组的区别
数组和链表有以下几点不同:
(1)存储形式:数组是一块连续的空间,声明时就要确定长度。链表是一块可不连续的动态空间,长度可变,每个结点要保存相邻结点指针。
(2)数据查找:数组的线性查找速度快,查找操作直接使用偏移地址。链表需要按顺序检索结点,效率低。
(3)数据插入或删除:链表可以快速插入和删除结点,而数组则可能需要大量数据移动。
(4)越界问题:链表不存在越界问题,数组有越界问题。

说明:在选择数组或链表数据结构时,一定要根据实际需要进行选择。数组便于查询,链表便于插入删除。数组节省空间但是长度固定,链表虽然变长但是占了更多的存储空间。
  • 简述队列和栈的异同
队列和栈都是线性存储结构,但是两者的插入和删除数据的操作不同,队列是“先进先出”,栈是“后进先出”。

注意:区别栈区和堆区。堆区的存取是“顺序随意”,而栈区是“后进先出”。栈由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。堆一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。分配方式类似于链表。
它与本题中的堆和栈是两回事。堆栈只是一种数据结构,而堆区和栈区是程序的不同内存存储区域。
  • typedef和define有什么区别
1)用法不同:typedef用来定义一种数据类型的别名,增强程序的可读性。define主要用来定义常量,以及书写复杂使用频繁的宏。
(2)执行时间不同:typedef是编译过程的一部分,有类型检查的功能。define是宏定义,是预编译的部分,其发生在编译之前,只是简单的进行字符串的替换,不进行类型的检查。
(3)作用域不同:typedef有作用域限定。define不受作用域约束,只要是在define声明后的引用都是正确的。
(4)对指针的操作不同:typedef和define定义的指针时有很大的区别。

注意:typedef定义是语句,因为句尾要加上分号。而define不是语句,千万不能在句尾加分号。
  • static有什么作用
static在C中主要用于定义全局静态变量、定义局部静态变量、定义静态函数。在C++中新增了两种作用:定义静态数据成员、静态函数成员。
注意:因为static定义的变量分配在静态区,所以其定义的变量的默认值为0,普通变量的默认值为随机数,在定义指针变量时要特别注意。
  • extern有什么作用
extern标识的变量或者函数声明其定义在别的文件中,提示编译器遇到此变量和函数时在其它模块中寻找其定义。
  • 简述指针常量与常量指针区别
int a = 20;
int * const p = &a;

指针常量本质上是一个常量,在指针常量中,指针自身的值是一个常量,不可改变,始终指向同一个地址。在定义的同时必须初始化

int a = 10, b = 20;
const int *p = &a;
p = &b; 

常量指针本质上是一个指针,常量表示指针指向的内容,说明该指针指向一个“常量”。在常量指针中,指针指向的内容是不可改变的,指针看起来好像指向了一个常量。指针可以指向其他地址,但是内容不可以改变

注意:无论是指针常量还是常量指针,其最大的用途就是作为函数的形式参数,保证实参在被调用函数中的不可改变特性。

  • 以下输出的答案是什么
char str1[] = "abc"; 
char str2[] = "abc"; 
const char str3[] = "abc"; 
const char str4[] = "abc"; 
const char* str5 = "abc"; 
const char* str6 = "abc"; 
cout << ( str1==str2 ) << endl; // 输出什么? 
cout << ( str3==str4 ) << endl; // 输出什么? 
cout << ( str5==str6 ) << endl; // 输出什么?

0,0,1

str1和str2是字符串数组,每个都有自己的存储器,数组名的值则是各存储器的首地址,所以不等,为0

str3和str4只是按const语义,他们所指向的数据区不能修改。

str5和str6不是数组而是字符指针,并没有分别存储器,"abc"以常量形式存于静态数据区,指针则指向该区的首地址,所以相等。

  • 以下代码什么问题
    cout << (true?1:"1") << endl;
    三目运算操作类型不一致
  • 结构体和共同体的区别
    结构体struct:把不同类型的数据组合成一个整体,自定义类型。
    共同体union:使几个不同类型的变量共同占用一段内存。
    structunion都有内存对齐,结构体的内存布局依赖于CPU、操作系统、编译器及编译时的对齐选项。

编程

  • 编码实现某一变量某位清0或置1
#define BIT3 (0x1 << 3 )
static int a;  
//设置a的bit 3:   
void set_bit3( void )   
{   
      a |= BIT3; //将a第3位置1   
}  
//清a的bit 3   
void set_bit3( void )   
{  
    a &= ~BIT3; //将a第3位清零   
} 

  • 编码实现直接选择排序
#include <stdio.h>  
  
int main()  
{  
    int i,j,t;  
    int array[10]={2,7,1,8,5,9,3,4,0,6};  
    printf("\nDisplay this array:\n");  
    for(i=0;i<10;i++)  
    {  
        printf("%d ",array[i]);  
    }  
    printf("\n");  
    for(i=1;i<=9;i++)  
    {  
        int t = i-1;  
        for(j=i;j<10;j++)  
        {  
            if(array[j]<array[t])  
            {  
                t=j;  
            }  
        }  
        if(t!=(i-1))  
        {  
            int temp = 0;  
            temp=array[i-1];  
            array[i-1]=array[t];  
            array[t]=temp;  
        }  
    }  
    printf("After sorting,this array is:\n");  
    for(i=0;i<10;i++)  
    {  
        printf("%d ",array[i]);  
    }  
    printf("\n");  
    return 0;  
}  

  • 编码实现冒泡排序
#include <stdio.h>  
#define LEN 10  
  
int main()  
{  
    int a,i,j;  
    int ARRAY[10]={23,1,4,9,6,17,24,56,98,72};  
    printf("\n");  
    printf("Display this array:\n");  
    for(a=0;a<10;a++)  
    {  
        printf("%d ",ARRAY[a]);  
    }  
    printf("\n");  
    for(j=0;j<10;j++)  
    {     
        for(i=0;i<LEN-j-1;i++)  
        {  
            int temp;  
            if(ARRAY[i]>ARRAY[i+1])  
            {  
                temp=ARRAY[i+1];  
                ARRAY[i+1]=ARRAY[i];  
                ARRAY[i]=temp;  
            }  
        }  
    }  
    printf("\nAfter sorting,the array is:\n");  
    for(a=0;a<LEN;a++)  
    {  
        printf("%d ",ARRAY[a]);  
    }  
    printf("\n");  
    return 0;     
}  

  • 编码实现直接插入排序
#include <stdio.h>  
  
int main()  
{  
    int i,temp,p;  
    int array[10] = {2,6,1,9,4,7,5,8,3,0};  
    printf("Display this array:\n");  
    for(i=0;i<10;i++)  
    {  
        printf("%d ",array[i]);  
    }  
      
    for(i=1;i<10;i++)  
    {  
        temp = array[i];  
        p = i-1;  
        while(p >= 0 && temp < array[p])  
        {  
            array[p+1] = array[p];  
            p--;  
        }  
        array[p+1] = temp;  
    }  
    printf("\n");  
    printf("After sorting,this array is:\n");  
    for(i=0;i<10;i++)  
    {  
        printf("%d ",array[i]);  
    }     
    printf("\n");  
    return 0;  
} 
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值