IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 2021-09-04 -> 正文阅读

[嵌入式]2021-09-04

嵌入式C语言面试题(二)

1.评价下面的代码

unsigned int zero = 0;
unsigned int compzero = 0xFFFF; 

unsigned int zero = 0; //OK
unsigned int compzero = 0xFFFF;//unsigned int 在16位OS中可以这样表示,在32位OS中表示错误.
应该是:
unsigned int compzero = ~0;

2.求c=a+++b;

int a = 5, b = 7, c;
c = a+++b;
c = a+++b = 12;
c = a+++b被编译器理解为a+++b

3.求值

typedef union {long i; int k[5]; char c;} DATE;
struct data { int cat; DATE cow; double dog;} too;
DATE max;

则语句 printf("%d",sizeof(struct data)+sizeof(max));的执行结果是?
sizeof(struct date) 分析如下:DATE是一个union,long i可能是4 byte,也可能是8 byte,int k[5]=20 byte,char c1个字节,因此,如果long i是4 byte,则sizeof(DATE)=20.此时struct data的大小为:cat(4byte),cow(20byte),dog(8 byte)合计32个字节.So,总长度为52个字节;

如果long i是8个字节,则DATE是24个字节,则4,24,8=36,合计60个字节.

4.下出下面的输出

char str1[] = "abc";
char str2[] = "abc";

const char str3[] = "abc";
const char str4[] = "abc";

const char *str5 = "abc";
const char *str6 = "abc";

char *str7 = "abc";
char *str8 = "abc";


cout << ( str1 == str2 ) << endl;//str1!=str2,因为是两个不同的数组
cout << ( str3 == str4 ) << endl;//str3!=str4,因为i是两个不同的常量数组
cout << ( str5 == str6 ) << endl;//一样,同样的指针
cout << ( str7 == str8 ) << endl;//一样,同样的指针

5.写出输出结果

main()
{
	int a[5]={1,2,3,4,5};
	int *ptr=(int *)(&a+1);
	printf("%d,%d",*(a+1),*(ptr-1));
}
*(a+1)=a[1],因此,第一个输出是int数据2.
ptr = (int*)(&a+1);首先,a是数组的首地址,那么&a+1到底是表示a的地址加1还是其他意思?
我们必须记住一点:指针加减的数字是以指针指向的数据类型为量度的,由于&a是指向a[5]这个整型数组首地址的地址,也就说&a的数据类型为数组指针(int (*)[5]).这个数组指针指向的数据类型是int a[5],长度为20个字节.因此,&a+1(ptr)表示数组首地址+20int *ptr =&a+1. 因此,ptr-1其实就是指向数组a的第5个元素,也就是5.

6.请问以下代码有什么问题

int  main()
{
  char a='a';
  char *str=&a;//str的地址空间只有1个字符
  strcpy(str,"hello");//指针越界,segment fault.
  printf(str); 
  char* s="AAA";//字符串数组
  printf("%s",s);//.
  s[0]='B';//字符串常量,不能修改.
  printf("%s",s);//.
  return 0;
}

7.请问下列表达式哪些会被编译器禁止?为什么?

int a=248; //OK
b=4;//b没有定义类型,error!
int const c=21;//int常量OK
const int *d=&a;//常量指针,指针指向的数值不能修改,这里做初始化,OK
int *const e=&b;//指针常量,其值为指向b的地址,OK.后面不能修改此指针值.
int const *f =&a;//常量指针,指针指向的值不能修改,这里做初始化,OK
*c=32;//c不是指针,不能有取值运算.error!
d=&b;//常量指针,指针的值可以修改,但原来的地址对应的数值不会修改.OK
*d=43;//常量指针,指针指向的值不能修改,error!
e=34;//指针不能直接赋值,error!
e=&a;//指针常量,指针的值不能修改.error!
f=0x321f;//常量指针,指针指向的值不能修改,但建议指针不要直接赋值

8.交换两个变量的值,不使用第三个变量

1.a = a^b;
  a = a^b;
  b = a^b;
2.a = a+b
  b = a-b
  a = a-b

9.下面的程序会出现什么结果?

#include <stdio.h>
#include <stdlib.h>
void getmemory(char *p)    //
{
    p=(char *) malloc(100);
    strcpy(p,"hello world");
}

int main( )
{
    char *str=NULL;
    getmemory(str);
    //str=NULL,在getmemory函数里面,char*p ,p(指针值)作了修改,但是str(实参)没有修改,因此,调用后,str还是=NULL
    printf("%s/n",str);
    free(str);
    return 0;
}

10.分析以下代码的输出是什么?

int _tmain(int argc, _TCHAR* argv[])  
{  
    unsigned short A=10;  
    printf("~A=%u\n",~A);  
    printf("~A=%d\n",~A);  
    printf("~A=%x\n",~A);
    char c=128;
    printf("c=%d\n",c);  
    return 0;  
}  

第一个,将A作为%u,无符号整数,A=0x0A,则~A = 0xFF FF FF F5 ,则其值为2的32次方-11.
第二个,将A作为有符号整数,~A=0xFF FF FF F5,为负数,由于负数在计算机中用补码表示,其补码为0x0B=-11.
第三个,将A作为16进制数,~A = 0xFF FF FF F5, 故其值就是0xFFFFFFF5.
第四个,c=128=0b 1000 0000,如果解析为有符号整数,则输出为负数,其补码=-128.so 输出为-128.

11.绝对地址0x100000赋值且想让程序跳转到绝对地址是0x100000去执行,如何写代码?

void (* p)() =(unsigned int*)0x100000;
//一个函数指针,返回值为空,参数为空.
p();

12.求下面结构的sizeof(A)大小.

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

分析:假定编译器设置的对齐参数为#pragma pack(4);(4字节对齐),则:
若为32位OS,
t,k共占据1个字节,unsigned short 2 byte,unsigned long m 4 byte,则对齐单位为4 byte,故t和k占据1个字节,i偏移量从2开始,占据2个字节,m偏移量从4开始,占据4个字节,合计8个字节.
若为64位OS,
t,k共占据1个字节,unsigned short 2 byte, unsigned long m 8个字节,则对齐单位为4 byte,故t和k占据1个字节,i偏移量从2开始,长度为2,m偏移量从4开始,长度为8,共计12个字节.

13.给出下面程序的答案.

typedef struct  AA
{
        int b1:5;
        int b2:2;
}AA;

void main()
{
        AA aa;
        char cc[100];
        strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");//strcpy在最后补0了.
        memcpy(&aa,cc,sizeof(AA));
        cout << aa.b1 <<endl;
        cout << aa.b2 <<endl;
}   

//sizeof(AA)=4;拷贝4个字符“0123”其16进制内容为0x30,0x31,0x32,0x33即:00110000 00110001 00110010 00110011.
//b1和b2占据了这四个字节的前面字节的7位,即b1:0b10000,b2=0b01;int是有符号整数,b1=-16,b2=1

14.给出下面程序的输出.

struct bit
{   
    int a:3;
    int  b:2;
    int c:3;
};

int main()
{
  bit s;
  char *c=(char*)&s;
  cout<<sizeof(bit)<<endl;//sizeof(bit)=4
  *c=0x99;
  cout << s.a <<endl <<s.b<<endl<<s.c<<endl;
  int a=-1;
  printf("%x",a);
  return 0;
}

分析:
sizeof(struct bit)=4.
*c = 0x99= 0b1001 1001,a是前3位,故a是001,b是11,c是100,由于均为int型,故s.a=1,s.b=-1,s.c=-4
a=-1, 1的原码是-0x00000001,-1的补码是0xFFFFFFFF.故a打印出来0xFFFFFFFF.

15.求以下几个结构的长度

struct name1{
   char  str; //1个字节;
   short x;//2个字节;
   int  num;//4个字节
}

struct name2{
   char str;//1个字节
   int num;//4个字节;
   short x;//2个字节
}

假设编译器对齐参数设置为# pragma pack(4),则:
struct name1:
此结构中长度最大的值为num(4),两者之间的较小值为4,第一个char str从0开始,第二个short的偏移量为其长度与4的较小值,故为2,第三个int num 长度为4,故其偏移量为4,因此,合计长度为8.
struct name2:
首先,其单位对齐长度为num的长度与pack(4)两者的最小值(4).
char str 1个字节,占据1个字节,num 占据4个字节,偏移量为4的倍数,故从4开始,占据4-7四个 byte,short x是两个字节,故偏移量为2的倍数,偏移量为8,占据2个字节,但总长度应该是4的整数倍,故最终的占据长度为4+4+4=12.

从上面可以看出,为了节约空间,数据类型占据字节长的结构成员,应该放在结构的后面.

struct s1
{
  int i: 8;//8位bit  
  int j: 4;//4位bit
  int a: 3;//3位bit
  double b;
};


struct s2
{
  int i: 8;//
  int j: 4;//两个int,共需要2个字节,//
  double b;//第三个,需要8,其偏移量从8开始,长度为8.
  int a:3;//第四个,偏移量从16开始,长度为4.因此,且总长度需要8的倍数,因此,此结构的总长度为8+8+8=24.
};

假设为#pragma pack(4),则:
struct s1:
i,j,a均为int型,合计占据15个字节,由于单位对齐长度为4,故这三个bit位共占据2个字节,double b始终占据8 byte,则其偏移量为4的倍数,本身占据8个字节,故struct s1的长度为12.

struct s2:
i,j,为int型,共占据2个字节;double b占据8个字节,故为4-11 8个字节,int a:3占据4个字节,故合计为4+8+4=16个字节.(关于结构体长度的判断,请参见笔者在csdn的相关其他文章)

16.填空

struct BBB
{
   long num;//4个字节  offset 0+4
   char *name;//4个字节 offset 4+4
   short int data;//2个字节 offset 8+2
   char ha;//1个字节      offset 10+2
   short ba[5];
}*p;
p=0x1000000;
p+0x200=____;
(unsigned long*)p+0x200=____;
(char*)p+0x200=____;

分析如下:

struct BBB
{  
   //单位对齐长度为4.
   long num;//4个字节  0+4(offset+占据字节,下同)
   char *name;//4个字节 4+4
   short int data;//2个字节 8+2
   char ha;//1个字节      10+2
   short ba[5];          12+10(12)
}*p;
p=0x1000000;
p+0x200=____;
(unsigned long*)p+0x200=____;
(char*)p+0x200=____;

由于long在32位OS和64位OS下面有不同的长度,故分开讨论:
假设为32位OS:根据笔者C语言结构体所占空间分析(https://blog.csdn.net/cdma_zte_c/article/details/119943850)可知,struct BBB占据22个字节,但应该为4的倍数,故占据空间为24 Byte.
所以p+0x200 = p+0x20024 = p + 0x2000x18
(unsigned long*)p+0x200= p + 0x200sizeof(unsigned long)=p+ 0x200 * 4
(char
)p + 0x200 = p + 0x200*sizeof(char)=p+0x200

假设为64位OS,则分析如下:
struct BBB
{
//单位对齐长度为4
long num;//8个字节 0+8(offset+占据字节,下同)
char *name;//8个字节 8+8
short int data;//2个字节 16+2
char ha;//1个字节 18+2
short ba[5]; 20+10(12)
}*p;
故合计占据长度为32 byte.
则后面就好计算了.

17.写出程序输出结果

void g(int**);
int main()
{
	int line[10],i;
	int *p=line; //p是一个指向int数据的指针,然后赋值给它line,
	//这样,p就指向了line的首地址.指针p的类型是 (int *)[10];
	for (i=0;i<10;i++)
	{
	    *p=i;// *p = i,将i赋值给line的第i个元素。
	    g(&p);//因为p是一个指针,把指针地址当作参数传递到函数.
	}

	for(i=0;i<10;i++)
	    printf("%d\n",line[i]);

       return 0;
} 

void g(int**p)
{
    (**p)++;//根据上面的分析,(**p)就是line数组当前位值的数值,后++,由于(**p)++操作的是实际的内存中的数值,故调用g函数的line数组中的值会相应修改.
    (*p)++;//*p是指针,指向line数组的相应位置,现在(*p)++,相当于指向line数组相关元素位置的指针的值++(指针的值是保存在指针p对应的内存中,指针的值++,就是p指向的内存中的值++),因此,就是line数组的当前元素位置后移.然后再次赋值,再次+1.故输出是1,2,3,4,5,6,7,8,9,10
}

分析情况参见源码部分.

18.写出程序输出结果

int arr[] = {6,7,8,9,10};
int *ptr = arr;//ptr指向数组头部
*(ptr++)+=123; // 首先*ptr = 123,然后ptr++.
printf(%d %d ”, *ptr, *(++ptr));//首先计算右边的*(++ptr),ptr+2 ,指向数据8,*ptr=8.故两者输出都是8.
typedef struct
{
  int a:2;
  int b:2;
  int c:1;
}test;

test t;
t.a = 1;//a=0x01,正数,因此,打印为1.
t.b = 3;//a=0x11,负数,求补码,因此,打印为-1
t.c = 1;//c=0x1,负数,求补码,打印为-1
printf("%d",t.a);
printf("%d",t.b);
printf("%d",t.c);

解答参见原文代码.

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-09-07 10:59:11  更:2021-09-07 11:00:18 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/29 8:56:34-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计