姓名:朱军伟 学号: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<iostream.h>
#include <string.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
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 <<endl;
cout << aa.b2 <<endl;
}
答案是 -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 &&(*c<a || *c<b) || (a<0 && b<0 &&(*c>a || *c>b)));
}
分析:
struct bit
{ int a:3;
int b:2;
int c:3;
};
int main()
{
bit s;
char *c=(char*)&s;
cout<<sizeof(bit)<<endl;
*c=0x99;
cout << s.a <<endl <<s.b<<endl<<s.c<<endl;
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 <stdio.h>
int main(void) {
int **p;
int arr[100];
p = &arr;
return 0;
}
解答:
搞错了,是指针类型不同,
int **p; //二级指针
&arr; //得到的是指向第一维为 100 的数组的指针
#include <stdio.h>
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 <stdio.h>
#include <stdlib.h>
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 <stdio.h>
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 <stdio.h>
void main()
{
unsigned long int a,i=1;
scanf("%d",&a);
if(a%2==0)
{
for(i=1;i<a/2;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 <stdio.h>
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你可以参考一下指针运算的细节