第5次面试题目 嵌入式软件工程师 题目 (题目难度低 )

1.int a[3][4] = { {1,2},{0},{4,6,8,10}};

a[1,2]=?

a[2,1]=?

答案:   (数组自动补 0 )
a[1][2]=0;
a[2][1]=6;

 代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int a[3][4] = { {1,2},{0},{4,6,8,10}};
	cout<<"a[1][2] = "<<a[1][2]<<endl;
	cout<<"a[2][1] = "<<a[2][1]<<endl; 
}

2. int k=2;
    int m=4;
    int n=6;
    int *pk=&k;
    int *pm=&m;
    int *p;
    *(p=&n) = *pk*(*pm);

  n=?

答案: 
n=8;

代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int k=2;
	int m=4;
	int n=6;
	int *pk=&k;
	int *pm=&m;
	int *p;
	//*p =  pk * pm = 2* 4 =8 
	*(p=&n) = *pk  * (*pm);
	//*(p= &n)  等于  *p = &n; 
	// *pk  * (*pm)   等于  m  * n  
	//注意之间的间隔少, 不要看错了!   
	cout<<"n= "<<n<<endl;
}

 


3.int *var;
    int b;
    var=&b;
    b=100;
    b=*var+10;

*var= ?

答案:
* var=110

代码:

#include<bits/stdc++.h>
using namespace std;

int main()
{
	int *var;
	int b;
	var=&b;
	b=100;
	b=*var+10;//指针应用 
	cout<<"*var = "<<*var<<endl; 
}

 


4.int a[5]  ,*p=a  正确使用 

 选项:

1. *(p+5 )    //错的  数组超标

2. * (a+2)   //对的

3. *&a[5 ]  // 数组超标


5. int a[5]  , *p =5 , 对指针的 正确引用

1.   &a+1 // 错的  &(a +1)

2.  &a[0]   // 对的

3.  p+5    //错的 数组超标

4. *a+1  // 指针的引用  这是  *a =1   *a+1=2


6.int a[4][[6]  --->4行 6列   正确的表示 a[i][j]  的地址表达

1.  & a[0][0] + 4* i + j  ;   // 错的 这个是把二维数组看成一维数组, 4*i   +  j   这个是 x 行 4 列的 应用

2.  & a[0][0] + 6* j + i  ;  //错的  这个是 j, i 的位置错误, 主要是因为 不能看成数组

3.  & a[0][0] + 6*i + j;  // 对的

4. &  a[0][0] + 4*j + i;  // 错的  不能形成 数组


7.int i=-2  以十六进制数的形式结构 表达 i 在 内存的存储形式 

原码: i=  1 0010

反码: i= 1 1101

补码: i= 1 1110

知识自己查询!!!


8.volatile 与 static 的区别   c与 c++ 的区别

c: 

volatile int i=10; int a = i; ... //其他代码,并未明确告诉编译器,对i进行过操作 int b = i;

volatile 指出 i是随时可能发生变化的,每次使用它的时候必须从i的地址中读取,因而编译器生成的汇编代码会重新从i的地址读取数据放在b中。而优化做法是,由于编译器发现两次从i读数据的代码之间的代码没有对i进行过操作,它会自动把上次读的数据放在b中。而不是重新从i里面读。这样以来,如果i是一个寄存器变量或者表示一个端口数据就容易出错,所以说volatile可以保证对特殊地址的稳定访问。

static:

1. 局部变量
普通局部变量是再熟悉不过的变量了,在任何一个函数内部定义的变量(不加static修饰符)都属于这个范畴。编译器一般不对普通局部变量进行初始化,也就是说它的值在初始时是不确定的,除非对其显式赋值。

普通局部变量存储于进程栈空间,使用完毕会立即释放。

静态局部变量使用static修饰符定义,即使在声明时未赋初值,编译器也会把它初始化为0。且静态局部变量存储于进程的全局数据区,即使函数返回,它的值也会保持不变。

变量在全局数据区分配内存空间;编译器自动对其初始化
其作用域为局部作用域,当定义它的函数结束时,其作用域随之结束
 

全局变量
全局变量定义在函数体外部,在全局数据区分配存储空间,且编译器会自动对其初始化。

普通全局变量对整个工程可见,其他文件可以使用extern外部声明后直接使用。也就是说其他文件不能再定义一个与其相同名字的变量了(否则编译器会认为它们是同一个变量)。

静态全局变量仅对当前文件可见,其他文件不可访问,其他文件可以定义与其同名的变量,两者互不影响。

在定义不需要与其他文件共享的全局变量时,加上static关键字能够有效地降低程序模块之间的耦合,避免不同文件同名变量的冲突,且不会误使用。

函数
函数的使用方式与全局变量类似,在函数的返回类型前加上static,就是静态函数。其特性如下:

静态函数只能在声明它的文件中可见,其他文件不能引用该函数
不同的文件可以使用相同名字的静态函数,互不影响

 

c++:

volatile.,声明这个字段易变(可能被多个线程使用),Java内存模型负责各个线程的工作区与主存区的该字段的值保持同步,即一致性。


static,声明这个字段是静态的(可能被多个实例共享),在主存区上该类的所有实例的该字段为同一个变量,即唯一性。


volatile,声明变量值的—致性;

 static,声明变量的唯—性。


此外,volatile同步机制不同于synchronized,前者是内存同步,后者不仅包含内存同步(一致性),且保证线程互斥(互斥性)。
staic只是声明变量在主存上的唯一性,不能保证工作区与主存区变量值的一致性;除非变量的值是不可变的,即再加上final的修饰符,否则static声明的变量,不是线程安全的。
 


9.

struct INFO  

{

        int a;

char c[6];

float f;

double d;

} ; 

一个INFO 的变量的 内存大小 

内存大小: 24

 代码:

#include<bits/stdc++.h>
using namespace std;
struct INFO
{
 	int a;
	char c[6];
	float f;
	double d;

};
int main()
{
	INFO a;
	cout<<"内存大小: "<<sizeof(a)<<endl;
}

我的理解 

首先 定义一个结构体 : 他在数据区的内存分配 的图形是一个 矩形 ,

struct INFO
{
     int a;
    char c[6];  //这里可以 看成 6 个  char 
    float f;
    double d;

};

就这个结构体来说 : 

1.开始的地方  :  sizeof(int  ) = 4  ;

2.数据开辟  一个     一行 4 列      的数据区域      存储 int a

3.第二个来了一个  sizeof( char c[6] ) = 6  ;

4.这个时候   数据开辟 了 一个  1 行 6列  的数据区域 ,但是 因为结构的数据区域要在一起, 那么,就要合并, 1 行4 列  和1行  6 列  合并   ,  变成啥, 2行 6 列   因为数据区域 要是 矩形, 

5.第三个数据来了  sizeof( float )  = 4;

6. 这时候系统 发现之前的 数据区域,有空余的空间 (等于 2 ) , 看是否能挤一挤  ,发现区域小了,挤不进去,只好 再开辟一个 1行 6 列的空间   与 之前的 2 行 6 列的空间 合并成为 3行 6列。

7.第四个数据来了   sizeof(  double  ) =8 

8.系统看他比之前的数据 都大  直接开辟 一个 1行8列的数据空间存储它,, 之后与之前的是数据区域合并, 1行 8列, 与 3行 6 列  ,  变成一个矩形  ,, --》 4行8列。

9.这时候,系统又看 内存空得太多了,可以挤一挤吗 ?  

一下  int   4   与  float  4  挤到一行去了  。变成了  3行 8 列 

内存大小 = 3 *8 =24;

其他的案列:

 

 自己补充知识点 


 10.ARM  程序编译后的 可执行代码 分为哪几个阶段 ,作用

答:

text段是代码段。它用来放程序代码(code)。它通常是只读的。 
.data段是数据段。它用来存放初始化了的(initailized)全局变量(global)和初始化了的静态变量(static)。它是可读可写的。 
.bss段是全局变量数据段。它用来存放未初始化的(uninitailized)全局变量(global)和未初始化的静态变量(static)。它也是可读可写的。bss是英文Block Started by Symbol的缩写。之所以把bss跟data分开来,是因为系统会为这些bss段的变量的初值清零。 
.rodata段是常量数据段。它用来存放常量(const)。它也是只读的。 

在ARM的集成开发环境中, 
1、只读的代码段称为Code段,即上述的.text段。 
2、只读的常量数据段,被称作RO Data段,即上述的.constdata段。 
以上两个段统称为RO段(Read Only),放在ROM或FLASH等非易失性器件中。 
3、可读可写的初始化了的全局变量和静态变量段,被称作RW Data段(ReadWrite),即上述的.data段。 
4、可读可写的未初始化的全局变量和静态变量段,被称作ZI Data段(Zero Init),即上述的.bss段。因为这个段里的变量要被初始化为零,所以叫ZI段。 

三个段

1.RO

2.RW

3.ZI


11.已知函数模型  int fun(int a,float b)

声明一个函数指针

int (*p)(int a, float b);

12..使用宏定义 写一个 返回最大的函数 ,

#define max_1(a,b) (((a)>(b))?(a):(b))

 

代码:

#include<bits/stdc++.h>
using namespace std;
#define max_1(a,b) (((a)>(b))?(a):(b))

int main()
{
	int a=max_1(1,2);
	cout<<a<<endl;
}


程序题目:

1. 1.完成下面函数,对一个传入数组进行由小到大排序,传入参数为数组首地址和数组长度
void Sort(int*pArray, int nLen);

#include<bits/stdc++.h>
using namespace std;

void Sort(int* pArray, int nLen)//pArray 是数组,  nlen是数组长度 
{
	for(int i=0;i<nLen;i++)
	{
		for(int j=i+1;j<nLen;j++)
		{
			if(pArray[i]>pArray[j])	
			{
				int a=pArray[i];
				pArray[i]=pArray[j];
				pArray[j]=a;
			}
		}	
	} 
	

}

int main()
{
	int num[]={2,1,5,6,4,8,9};
	Sort(num,7);
	for(int i=0;i<7;i++)
	{
		cout<<num[i]<<"  "; 
	}
	
}

2.一个结构体  两个小题

某数据管理软件中采用链表来维护员工的信息,链表节点结构体类型声明如下所示,假定该链表已经存在,且已经按照员工工号从小到大排列各节点,其中链表首节点并不存储任何信息,只是用于占位以简化链表操作。要求实现下两个链表操作函数(C或C++):
typedef struct _WorkerInfo
char Name[20];/*员工姓名*/
unsigned int ID;/*员工工号,在整个链表中工号不会重复*/struct _Workerlnfo*pNext;
}WorkerInfo;


2.1 1)编写一个函数添加新的员工信息,即通过传入链表首节点地址、新员工的姓名和F
工号信息,动态生成一个节点插入到当前链表合适位置,成功返回0,出错返回-1,
函数原型声明如下:
int InsertNewNode(WorkerInfo *pListHead, const char*Name, unsigned int lD);

2.22)编写一个函数删除某员工信息,即通过入链表首节点地址和传入该员
工的工号,在链表中搜索相应节点,并予以删除,成功返回o,出错返回-1,函数原型声明如下
int DeleteNode(WorkerInfo *pListHead, unsigned int lD);
提示:可以用malloc和free函数进行动态内存分配和回收,亦可使用new和delete


代码:

#include<bits/stdc++.h>
using namespace std;

struct WorkerInfo
{
	char Name[20];/*员工姓名*/
	unsigned int ID;/*员工工号,在整个链表中工号不会重复*/
	struct WorkerInfo *pNext;//指针  
};

//函数功能: 添加工人到链表合适的位置   ID 不会重复  所以按照 ID 排序 
int InsertNewNode(WorkerInfo *pListHead, const char*Name, unsigned int ID)//pListHead 头节点   name  工人的名字   ID  工人的ID  
{
	if(pListHead==NULL)
	{
		return 0;
	 } 
	WorkerInfo * pp =pListHead;
	WorkerInfo * kk= (WorkerInfo*)malloc(sizeof(WorkerInfo));
	strcpy(kk->Name,Name);
	kk->ID=ID;
	while(pp!=NULL)
	{
		if(pp->pNext!=NULL)
		{
			if(pp->pNext->ID > ID)
			{
				kk->pNext=pp->pNext;
				pp->pNext=kk;
				return 1;
			}
		}
		pp=pp->pNext;
	}
	pp=pListHead;//
	while(pp->pNext!=NULL) ///找到最后一个单位 
	{
		pp=pp->pNext; 
	}
		kk->pNext=pp->pNext;
		pp->pNext=kk;
		return 1;
}
//程序功能: 删除工人的信息 
int DeleteNode(WorkerInfo *pListHead, unsigned int ID)//pListHead 头节点     ID  工人的ID  
{
	WorkerInfo * kk =pListHead; //方便删除  
	WorkerInfo * pp =pListHead;
	while(pp!=NULL)
	{
		if(pp->ID==ID)
		{
			kk->pNext=pp->pNext;
			delete pp;
			return 1;
		}
		else
		{
			kk=pp;
			pp=pp->pNext;
		 } 
	}
	return 0;//没有这个人  
	
	
}
//程序功能 打印链表信息  
void print(WorkerInfo *pListHead) 
{
	WorkerInfo *pp=pListHead;
	while(pp!=NULL)
	{
		cout<<pp->Name<<"    "<<pp->ID<<endl;
		pp=pp->pNext;
	}
}

int main()
{
	WorkerInfo * head=(WorkerInfo* )malloc(sizeof(WorkerInfo));
	head->pNext=NULL;
	head->ID=0;
	strcpy(head->Name,"0000");
	
	cout<<"第1次打印链表 : "<<endl;
	print(head);
	
	
	 InsertNewNode(head,"11111",1);
	 
	cout<<"第2次打印链表 : "<<endl;
	print(head);
	
	 InsertNewNode(head,"3333",3);
	 InsertNewNode(head,"2222",2);
	DeleteNode(head,2);
	cout<<"第3次打印链表 : "<<endl;
	print(head);
		
	
}

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值