2021-08-18

姓名:朱军伟               学号:19170100001           学院:电子工程学院            班级:1902015

原文转自:https://download.csdn.net/download/sun_jfly/4326176?utm_medium=distribute.pc_relevant_t0.none-task-download-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&depth_1-utm_source=distribute.pc_relevant_t0.none-task-download-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control

【嵌牛导读】任何行业的终极目标都是为了谋求发展,嵌入式作为一个前沿行业,我们有必要熟悉一下常见的面试题,我将此作为一个系列发布。

【嵌牛鼻子】嵌入式行业面试题

【嵌牛提问】如何轻松应对嵌入式行业面试?

【嵌牛正文】

分析下面的程序:

void GetMemory(char **p,int num)

{

*p=(char *)malloc(num);

}

int main()

{

char *str=NULL;

GetMemory(&str,100);

strcpy(str,"hello");

free(str);

if(str!=NULL)

{

strcpy(str,"world");

}

printf("\n str is %s",str);

getchar();

}

问输出结果是什么?希望大家能说说原因,先谢谢了

输出 str is world。

free 只是释放的 str 指向的内存空间,它本身的值还是存在的.

所以 free 之后,有一个好的习惯就是将 str=NULL.

此时 str 指向空间的内存已被回收,如果输出语句之前还存在分配空间的操作的话,这段存储

空间是可能被重新分配给其他变量的,

尽管这段程序确实是存在大大的问题(上面各位已经说得很清楚了),但是通常会打印出

world 来。

这是因为,进程中的内存管理一般不是由操作系统完成的,而是由库函数自己完成的。

当你 malloc 一块内存的时候,管理库向操作系统申请一块空间(可能会比你申请的大一些),

然后在这块空间中记录一些管理信息(一般是在你申请的内存前面一点),并将可用内存的

地址返回。但是释放内存的时候,管理库通常都不会将内存还给操作系统,因此你是可以继

续访问这块地址的,只不过。。。。。。。。楼上都说过了,最好别这么干。

char a[10],strlen(a)为什么等于 15?运行的结果

#include "stdio.h"

#include "string.h"

void main(){

char aa[10];

printf("%d",strlen(aa));

}

sizeof()和初不初始化,没有关系;

strlen()和初始化有关。

char (*str)[20];/*str 是一个数组指针,即指向数组的指针.*/

char *str[20];/*str 是一个指针数组,其元素为指针型数据.*/

long a=0x801010;

a+5=?

0x801010 用二进制表示为:“1000 0000 0001 0000 0001 0000”,十进制的值为 8392720,再

加上 5 就是 8392725 罗

1)给定结构 struct A

{

char t:4;

char k:4;

unsigned short i:8;

unsigned long m;

};问 sizeof(A) = ?

给定结构 struct A

{

char t:4; 4 位

char k:4; 4 位

unsigned short i:8; 8 位

unsigned long m; // 偏移 2 字节保证 4 字节对齐

}; // 共 8 字节

2)下面的函数实现在一个数上加一个数,有什么错误?请改正。

int add_n ( int n )

{

static int i = 100;

i += n;

return i;

}

当你第二次调用时得不到正确的结果,难道你写个函数就是为了调用一次?问题就出在

static 上?

// 帮忙分析一下#include

#include

#include

#include

#include

#include

typedef struct AA

{

int b1:5;

int b2:2;

}AA;

void main()

{

AA aa;

char cc[100];

strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");

memcpy(&aa,cc,sizeof(AA));

cout << aa.b1 <

cout << aa.b2 <

}

答案是 -16 和1

首先 sizeof(AA)的大小为 4,b1 和 b2 分别占 5bit 和 2bit.

经过 strcpy 和 memcpy 后,aa 的 4 个字节所存放的值是:

0,1,2,3 的 ASC 码,即 00110000,00110001,00110010,00110011

所以,最后一步:显示的是这4个字节的前5位,和之后的2位

分别为:10000,和 01

因为 int 是有正负之分 所以:答案是-16 和1

求函数返回值,输入 x=9999;

int func ( x )

{

int countx = 0;

while ( x )

{

countx ++;

x = x&(x-1);

}

return countx;

}

结果呢?

知道了这是统计 9999 的二进制数值中有多少个 1 的函数,且有

9999=9×1024+512+256+15

9×1024 中含有 1 的个数为 2;512 中含有 1 的个数为 1;

256 中含有 1 的个数为 1;

15 中含有 1 的个数为 4;

故共有 1 的个数为 8,结果为 8。

1000 - 1 = 0111,正好是原数取反。这就是原理。

用这种方法来求 1 的个数是很效率很高的。

不必去一个一个地移位。循环次数最少。

int a,b,c 请写函数实现 C=a+b ,不可以改变数据类型,如将 c 改为 long int,关键是如何处理溢出

问题

bool add (int a, int b,int *c)

{

*c=a+b;

return (a>0 && b>0 &&(*ca || *c>b)));

}

分析:

struct bit

{ int a:3;

int b:2;

int c:3;

};

int main()

{

bit s;

char *c=(char*)&s;

cout<

*c=0x99;

cout << s.a <

int a=-1;

printf("%x",a);

return 0;

}

输出为什么是

4

1

-1

-4

ffffffff

因为 0x99 在内存中表示为 100 11 001 , a = 001, b = 11, c = 100

当 c 为有符合数时, c = 100, 最高 1 为表示 c 为负数,负数在计算机用补码表示,所以 c = -4;

同理

b = -1;当 c 为有符合数时, c = 100,即 c = 4,同理 b = 3

位域 :

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如

在存放一个开关量时,只有 0 和 1 两种状态, 用一位二进位即可。为了节省存储空间,并

使处理简便,C语言又提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把

一个字节中的二进位划分为几个不同的区域,

并说明每个区域的位数。每个域有一个域名,

允许在程序中按域名进行操作。 这样就可以把几个不同的对象用一个字节的二进制位域来

表示。一、位域的定义和位域变量的说明位域定义与结构定义相仿,其形式为:

struct 位域结构名

{ 位域列表 };

其中位域列表的形式为: 类型说明符 位域名:位域长度

例如:

struct bs

{

int a:8;

int b:2;

int c:6;

};

位域变量的说明与结构变量说明的方式相同。 可采用先定义后说明,同时定义说明或者直

接说明这三种方式。例如:

struct bs

{

int a:8;

int b:2;

int c:6;

}data;

说明 data 为 bs 变量,共占两个字节。其中位域 a 占 8 位,位域 b 占 2 位,位域 c 占 6 位。

对于位域的定义尚有以下几点说明:

1. 一个位域必须存储在同一个字节中,不能跨两个字节。如一个字节所剩空间不够存放另

一位域时,应从下一单元起存放该位域。也可以有意使某位域从下一单元开始。例如:

struct bs

{

unsigned a:4

unsigned :0 /*空域*/

unsigned b:4 /*从下一单元开始存放*/

unsigned c:4

}

在这个位域定义中,a 占第一字节的 4 位,后 4 位填 0 表示不使用,b 从第二字节开始,占

用 4 位,c 占用 4 位。

2. 由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过 8 位二进位。

3. 位域可以无位域名,这时它只用来作填充或调整位置。无名的位域是不能使用的。例如:

struct k

{

int a:1

int :2 /*该 2 位不能使用*/

int b:3

int c:2

};

从以上分析可以看出,位域在本质上就是一种结构类型, 不过其成员是按二进位分配的。

二、位域的使用位域的使用和结构成员的使用相同,其一般形式为: 位域变量名•

位域名 位域允许用各种格式输出。

main(){

struct bs

{

unsigned a:1;

unsigned b:3;

unsigned c:4;

} bit,*pbit;

bit.a=1;

bit.b=7;

bit.c=15;

pri

改错:

#include

int main(void) {

int **p;

int arr[100];

p = &arr;

return 0;

}

解答:

搞错了,是指针类型不同,

int **p; //二级指针

&arr; //得到的是指向第一维为 100 的数组的指针

#include

int main(void) {int **p, *q;

int arr[100];

q = arr;

p = &q;

return 0;

}

下面这个程序执行后会有什么错误或者效果:

#define MAX 255

int main()

{

unsigned char A[MAX],i;//i 被定义为 unsigned char

for (i=0;i<=MAX;i++)

A[i]=i;

}

解答:死循环加数组越界访问(C/C++不进行数组越界检查)

MAX=255

数组 A 的下标范围为:0..MAX-1,这是其一..

其二.当 i 循环到 255 时,循环内执行:

A[255]=255;

这句本身没有问题..但是返回 for (i=0;i<=MAX;i++)语句时,

由于 unsigned char 的取值范围在(0..255),i++以后 i 又为 0 了..无限循环下去.

struct name1{

char str;

short x;

int num;

}

struct name2{

char str;

int num;

short x;

}

sizeof(struct name1)=8,sizeof(struct name2)=12

在第二个结构中,为保证 num 按四个字节对齐,char 后必须留出 3 字节的空间;同时为保

证整个结构的自然对齐(这里是 4 字节对齐),在 x 后还要补齐 2 个字节,这样就是 12 字节。

intel:

A.c 和 B.c 两个 c 文件中使用了两个相同名字的 static 变量,编译的时候会不会有问题?这两个

static 变量会保存到哪里(栈还是堆或者其他的)?

static 的全局变量,表明这个变量仅在本模块中有意义,不会影响其他模块。他们都放在数据区,但是编译器对他们的命名是不同的。

如果要使变量在其他模块也有意义的话,需要使用 extern 关键字。

struct s1

{

int i: 8;

int j: 4;

int a: 3;

double b;

};

struct s2

{

int i: 8;

int j: 4;

double b;

int a:3;

};

printf("sizeof(s1)= %d\n", sizeof(s1));

printf("sizeof(s2)= %d\n", sizeof(s2));

result: 16, 24

第一个 struct s1

{

int i: 8;

int j: 4;

int a: 3;

double b;

};

理论上是这样的,首先是 i 在相对 0 的位置,占 8 位一个字节,然后,j 就在相对一个字节

的位置,由于一个位置的字节数是 4 位的倍数,因此不用对齐,就放在那里了,然后是 a,

要在 3 位的倍数关系的位置上,因此要移一位,在 15 位的位置上放下,目前总共是 18 位,

折算过来是 2 字节 2 位的样子,由于 double 是 8 字节的,因此要在相对 0 要是 8 个字节的

位置上放下,因此从 18 位开始到 8 个字节之间的位置被忽略,直接放在 8 字节的位置了,

因此,总共是 16 字节。

第二个最后会对照是不是结构体内最大数据的倍数,不是的话,会补成是最大数据的倍数

上面是基本问题,接下来是编程问题:

本人很弱,这几个题也搞不定,特来求救:

1)读文件 file1.txt 的内容(例如):

1234

56

输出到 file2.txt:

56

34

12

(逆序)

2)输出和为一个给定整数的所有组合

例如 n=5

5=1+4;5=2+3(相加的数不能重复)

则输出

1,4;2,3。

望高手赐教!!

第一题,注意可增长数组的应用.

#include

#include

int main(void)

{

int MAX = 10;

int *a = (int *)malloc(MAX * sizeof(int));

int *b;

FILE *fp1;

FILE *fp2;

fp1 = fopen("a.txt","r");

if(fp1 == NULL)

{printf("error1");

exit(-1);

}

fp2 = fopen("b.txt","w");

if(fp2 == NULL)

{printf("error2");

exit(-1);

}

int i = 0;

int j = 0;

while(fscanf(fp1,"%d",&a[i]) != EOF)

{i++;

j++;

if(i >= MAX)

{

MAX = 2 * MAX;

b = (int*)realloc(a,MAX * sizeof(int));

if(b == NULL)

{

printf("error3");

exit(-1);

}

a = b;

}

}

for(;--j >= 0;)

fprintf(fp2,"%d\n",a[j]);

fclose(fp1);

fclose(fp2);

return 0;

}

第二题.

#include

int main(void)

{

unsigned long int i,j,k;

printf("please input the number\n");

scanf("%d",&i);

if( i % 2 == 0)

j = i / 2;

else

j = i / 2 + 1;

printf("The result is \n");

for(k = 0; k < j; k++)

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

return 0;

}#include

void main()

{

unsigned long int a,i=1;

scanf("%d",&a);

if(a%2==0)

{

for(i=1;i

printf("%d",a,a-i);

}

else

for(i=1;i<=a/2;i++)

printf(" %d, %d",i,a-i);

}

兄弟,这样的题目若是做不出来实在是有些不应该, 给你一个递规反向输出字符串的例子,可

谓是反序的经典例程.

void inverse(char *p)

{

if( *p = = '\0' )

return;

inverse( p+1 );

printf( "%c", *p );

}

int main(int argc, char *argv[])

{

inverse("abc\0");

return 0;

}

借签了楼上的“递规反向输出”

#include

void test(FILE *fread, FILE *fwrite)

{

char buf[1024] = {0};

if (!fgets(buf, sizeof(buf), fread))

return;

test( fread, fwrite );

fputs(buf, fwrite);

}

int main(int argc, char *argv[]){

FILE *fr = NULL;

FILE *fw = NULL;

fr = fopen("data", "rb");

fw = fopen("dataout", "wb");

test(fr, fw);

fclose(fr);

fclose(fw);

return 0;

}

在对齐为 4 的情况下

struct BBB

{

long num;

char *name;

short int data;

char ha;

short ba[5];

}*p;

p=0x1000000;

p+0x200=____;

(Ulong)p+0x200=____;

(char*)p+0x200=____;

希望各位达人给出答案和原因,谢谢拉

解答:假设在 32 位 CPU 上,

sizeof(long) = 4 bytes

sizeof(char *) = 4 bytes

sizeof(short int) = sizeof(short) = 2 bytes

sizeof(char) = 1 bytes

由于是 4 字节对齐,

sizeof(struct BBB) = sizeof(*p)

= 4 + 4 + 2 + 1 + 1/*补齐*/ + 2*5 + 2/*补齐*/ = 24 bytes (经 Dev-C++验证)

p=0x1000000;

p+0x200=____;

= 0x1000000 + 0x200*24

(Ulong)p+0x200=____;

= 0x1000000 + 0x200

(char*)p+0x200=____;

= 0x1000000 + 0x200*4你可以参考一下指针运算的细节

你可能感兴趣的:(2021-08-18)