1、嵌入式软件工程师笔试题维数组空间的动态申请 a.简单的,已经有一维,如 char (*c)5;c=new charn5;维的int *p;p=new int*m_row;.题二:读程序,写出运行结果i nclude i nclude i nclude i nclude typedef struct int value; char type;head_t;这是什么东西啊?typedef struct head_t head; int para;message_t;void main(void) message_t *message=NULL; head_t *head=NULL; message
2、=(message_t *)malloc(sizeof(message_t);o assert(message); 目标文件,不进行连接(一般很少单独使用)。 o make clean 删除编译产生的目标文件和依赖文件。 o make cleanall 删除目标文件、依赖文件以及可执行文件。 o make rebuild 重新编译和连接程序。相当于 make clean & make all。 下面提供两个例子来具体说明上面 Makefile 的用法。 例一Hello World 程序 这个程序的功能是输出 Hello, world! 这样一行文字。由 、 三个文件组成。前两个文件是 C 程序
3、,后一个是 C+ 程序,因此这是一个 C 和 C+ 混编程序。 代码:/* File name: * C header file */ #ifndef HELLO_H #define HELLO_H #ifdef _cplusplus extern C #endif void print_hello(); #ifdef _cplusplus #endif #endif 代码:/* File name: * C source file. */ #include #include void print_hello() puts( Hello, world! ); 代码:/* File name:
4、* C+ source file. */ #include int main() print_hello(); return 0; 建立一个新的目录,然后把这三个文件拷贝到目录中,也把 Makefile 文件拷贝到目录中。之后,对 Makefile 的相关项目进行如下设置: 代码:PROGRAM := hello # 设置运行程序名 SRCDIRS := . # 源程序位于当前目录下 SRCEXTS := .c .cxx # 源程序文件有 .c 和 .cxx 两种类型 CFLAGS := -g # 为 C 目标程序包含 GDB 可用的调试信息 CXXFLAGS := -g # 为 C+ 目标程
5、序包含 GDB 可用的调试信息 由于这个简单的程序只使用了 C 标准库的函数(puts),所以对于 CFLAGS 和 CXXFLAGS 没有过多的要求,LDFLAGS 和 CPPFLAGS 选项也无需设置。 经过上面的设置之后,执行 make 命令就可以编译程序了。如果没有错误出现的话,./hello 就可以运行程序了。 如果修改了源程序的话,可以看到只有和修改有关的源文件被编译。也可以再为程序添加新的源文件,只要它们的扩展名是已经在 Makefile 中设置过的,那么就没有必要修改Makefile。 1.引言 本文的写作目的并不在于提供C/C+程序员求职面试指导,而旨在从技术上分析面试题的内
6、涵。文中的大多数面试题来自各大论坛,部分试题解答也参考了网友的意见。许多面试题看似简单,却需要深厚的基本功才能给出完美的解答。企业要求面试者写一个最简单的strcpy函数都可看出面试者在技术上究竟达到了怎样的程度,我们能真正写好一个strcpy函数吗?我们都觉得自己能,可是我们写出的strcpy很可能只能拿到10分中的2分。读者可从本文看到strcpy函数从2分到10分解答的例子,看看自己属于什么样的层次。此外,还有一些面试题考查面试者敏捷的思维能力。 分析这些面试题,本身包含很强的趣味性;而作为一名研发人员,通过对这些面试题的深入剖析则可进一步增强自身的内功。2.找错题试题1:void te
7、st1()char string10;char* str1 = 09;strcpy( string, str1 );试题2:void test2()char string10, str110;int i;for(i=0; i10; i+)str1i = a;strcpy( string, str1 );试题3:void test3(char* str1)char string10;if( strlen( str1 ) = 10 )strcpy( string, str1 );解答:试题1字符串str1需要11个字节才能存放下(包括末尾的0),而string只有10个字节的空间,strcpy会导
8、致数组越界;对试题2,如果面试者指出字符数组str1不能在数组内结束可以给3分;如果面试者指出strcpy(string, str1)调用使得从str1内存起复制到string内存起所复制的字节数具有不确定性可以给7分,在此基础上指出库函数strcpy工作方式的给10分;对试题3,if(strlen(str1) = 10)应改为if(strlen(str1) = - EPSINON) & (x =”或“=”形式。如果写成if (x = ,则判为错,得0分。试题2:以下为Windows NT下的32位C+程序,请计算sizeof的值void Func ( char str100 )sizeof(
9、 str ) = ?void *p = malloc( 100 );sizeof ( p ) = ?解答:sizeof( str ) = 4sizeof ( p ) = 4剖析:Func ( char str100 )函数中数组名作为函数形参时,在函数体内,数组名失去了本身的内涵,仅仅只是一个指针;在失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。数组名的本质如下:(1)数组名指代一种数据结构,这种数据结构就是数组;例如:char str10;cout sizeof(str) ;符号, 此时联合访问成员可表示成: 联合名-;成员名 另外, 联合既可以出现在结构内,
10、它的成员也可以是结构。 例如: struct int age; char *addr; union int i; char *ch; x; y10; 若要访问结构变量y1中联合x的成员i, 可以写成: y1.; 若要访问结构变量y2中联合x的字符串指针ch的第一个字符可写成: *y2.; 若写成y2.x.*ch;是错误的。 2. 结构和联合的区别 结构和联合有下列区别: 1. 结构和联合都是由多个不同的数据类型成员组成, 但在任何同一时刻, 联合转只存放了一个被选中的成员, 而结构的所有成员都存在。 2. 对于联合的不同成员赋值, 将会对其它成员重写, 原来成员的值就不存在了, 而对于结构的不
11、同成员赋值是互不影响的。 下面举一个例了来加对深联合的理解。 例4:main() union /*定义一个联合*/ int i; struct /*在联合中定义一个结构*/ char first; char second; half; number; =0x4241; /*联合成员赋值*/ printf(%c%cn, a; /*联合中结构成员赋值*/ b; printf(%xn, ; getch(); 输出结果为: AB 6261 从上例结果可以看出: 当给i赋值后, 其低八位也就是first和second的值;当给first和second赋字符后, 这两个字符的ASCII码也将作为i 的低八
12、位和高八位。Volatile 关键字告诉编译器不要持有变量的临时性拷贝。一般用在多线程程序中,以避免在其中一个线程操作该变量时,将其拷贝入寄存器。请看以下情形: A线程将变量复制入寄存器,然后进入循环,反复检测寄存器的值是否满足一定条件(它期待B线程改变变量的值。在此种情况下,当B线程改变了变量的值时,已改变的值对其在寄存器的值没有影响。所以A线程进入死循环。 volatile 就是在此种情况下使用。一、预备知识程序的内存分配 一个由c/C+编译的程序占用的内存分为以下几个部分 1、栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
13、2、堆区(heap) 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收 。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表,呵呵。 3、全局区(静态区)(static),全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后有系统释放 4、文字常量区常量字符串就是放在这里的。 程序结束后由系统释放 5、程序代码区存放函数体的二进制代码。例子程序这是一个前辈写的,非常详细另外,在WINDOWS下,最好的方式是用VirtualAlloc分配内存,他不是在堆,也不是在栈是直接在进程
14、的地址空间中保留一快内存,虽然用起来最不方便。但是速度快,也最灵活。堆和栈中的存储内容栈: 在函数调用时,第一个进栈的是主函数中后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数,在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。堆:一般是在堆的头部用一个字节存放堆的大小。堆中的具体内容有程序员安排。存取效率的比较char s1 = aaaaaaaaaaaaaaa;char *s2 = bbbbbb
15、bbbbbbbbbbb;aaaaaaaaaaa是在运行时刻赋值的;而bbbbbbbbbbb是在编译时就确定的;但是,在以后的存取中,在栈上的数组比指针所指向的字符串(例如堆)快。比如:i ncludevoid main()char a = 1;char c = 90;char *p =90;a = c1;a = p1;return;对应的汇编代码10: a = c1;00401067 8A 4D F1 mov cl,byte ptr ebp-0Fh0040106A 88 4D FC mov byte ptr ebp-4,cl11: a = p1;0040106D 8B 55 EC mov ed
16、x,dword ptr ebp-14h00401070 8A 42 01 mov al,byte ptr edx+100401073 88 45 FC mov byte ptr ebp-4,al第一种在读取时直接就把字符串中的元素读到寄存器cl中,而第二种则要先把指针值读到edx中,在根据edx读取字符,显然慢了。小结堆和栈的区别可以用如下的比喻来看出:使用栈就象我们去饭馆里吃饭,只管点菜(发出申请)、付钱、和吃(使用),吃饱了就走,不必理会切菜、洗菜等准备工作和洗碗、刷锅等扫尾工作,他的好处是快捷,但是自由度小。使用堆就象是自己动手做喜欢吃的菜肴,比较麻烦,但是比较符合自己的口味,而且自由度
17、大。windows进程中的内存结构在阅读本文之前,如果你连是什么多不知道的话,请先阅读文章后面的。接触过的人都知道,高级语言都能通过变量名来访问内存中的数据。那么这些变量在内存中是如何存放的呢?程序又是如何使用这些变量的呢?下面就会对此进行深入的讨论。下文中的C语言代码如没有特别声明,默认都使用VC编译的release版。首先,来了解一下 C 语言的变量是如何在内存分部的。C 语言有全局变量(Global)、本地变量(Local),静态变量(Static)、寄存器变量(Regeister)。每种变量都有不同的分配方式。先来看下面这段代码:i nclude int g1=0, g2=0, g3=0;int main()static int s1=0, s2=0, s3=0;int v1=0, v2=0, v3=0;7c7c6c3”2”1”0C0000000C4C0040100F894C83C43C0000003C00401078 C000C6A6A6A0000000C004068c
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1