c语言面试题总结.doc



Similar documents
Microsoft PowerPoint - 5. 指针Pointers.ppt [兼容模式]

chap07.key

没有幻灯片标题

《C语言程序设计》第2版教材习题参考答案

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.06.doc

《C语言程序设计》教材习题参考答案

C++ 程序设计 告别 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

新版 明解C++入門編

CC213

新版 明解C言語入門編

新・解きながら学ぶC言語

Microsoft PowerPoint - 4. 数组和字符串Arrays and Strings.ppt [兼容模式]

untitled

新・明解C言語入門編『索引』

Generated by Unregistered Batch DOC TO PDF Converter , please register! 浙江大学 C 程序设计及实验 试题卷 学年春季学期考试时间 : 2003 年 6 月 20 日上午 8:3

OOP with Java 通知 Project 2 提交时间 : 3 月 14 日晚 9 点 另一名助教 : 王桢 学习使用文本编辑器 学习使用 cmd: Power shell 阅读参考资料

C/C++ - 文件IO

untitled

c_cpp

C C C The Most Beautiful Language and Most Dangerous Language in the Programming World! C 2 C C C 4 C Project 30 C Project 3 60 Project 40

NOWOER.OM m/n m/=n m/n m%=n m%n m%=n m%n m/=n 4. enum string x1, x2, x3=10, x4, x5, x; 函数外部问 x 等于什么? 随机值 5. unsigned char *p1; unsigned long *p

C/C++ - 函数

int *p int a 0x00C7 0x00C7 0x00C int I[2], *pi = &I[0]; pi++; char C[2], *pc = &C[0]; pc++; float F[2], *pf = &F[0]; pf++;

FY.DOC

2013 C 1 # include <stdio.h> 2 int main ( void ) 3 { 4 int cases, a, b, i; 5 scanf ("%d", & cases ); 6 for (i = 0;i < cases ;i ++) 7 { 8 scanf ("%d %d

C/C++程序设计 - 字符串与格式化输入/输出

《计算概论》课程 第十九讲 C 程序设计语言应用

_汪_文前新ok[3.1].doc

一 关于内存 数据存储 变量分类 局部变量 全局变量 静态变量 请看下面代码, 分析变量类型? int pi = 3; int Area(int r, int *sum) { int b; static int c =0; b = pi * r * r; c += b; *sum = c; retu

C++ 程序设计 告别 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1

C 1

untitled

试卷代号 ~1075 座位号 E 口 国家开放大学 ( 中央广播电视大学 )20]5 年秋季学期 " 开放本科 " 期末考试 C 十十语言程序设计 试题 同二二十斗 2016 年 1 月 巴叫一 1. 下面的保留字 ( ) 不能作为函数的返回类型 A. void B. int C. new D. l

试卷代号 :1075 座位号 rn 国家开放大学 ( 中央广播电视大学 )2015 年秋季学期 " 开放本科 " 期末考试 c+ 十语言程序设计试题 2016 年 1 月 t 问一 Urr-f 斗 士 1 1. 下面的保留字 ( ) 不能作为函数的返回类型 A. void B. int C. new

Microsoft Word - 《C语言开发入门》课程教学大纲-2.doc

C/C++语言 - C/C++数据

C/C++ - 字符串与字符串函数

untitled

OOP with Java 通知 Project 4: 4 月 18 日晚 9 点 关于抄袭 没有分数

C 1 # include <stdio.h> 2 int main ( void ) { 4 int cases, i; 5 long long a, b; 6 scanf ("%d", & cases ); 7 for (i = 0;i < cases ;i ++) 8 { 9

毛泽西 | C/C++ 程序设计员应聘常见面试试题深入剖析

Microsoft PowerPoint - 8. 运算符重载 Operator Overloading.pptx

Microsoft PowerPoint - string_kruse [兼容模式]

( CIP) /. :, ( ) ISBN TP CIP ( 2005) : : : : * : : 174 ( A ) : : ( 023) : ( 023)

1 Project New Project 1 2 Windows 1 3 N C test Windows uv2 KEIL uvision2 1 2 New Project Ateml AT89C AT89C51 3 KEIL Demo C C File

Microsoft PowerPoint - C语言课件-9-结构体.pptx

Microsoft PowerPoint - 3. 函数Functionl.ppt [兼容模式]

C++ 程式設計

为提高我们的程序品质特将林博士的资料作为我公司程序员的学习教材,请各位读读,我把我的看法用红字表出,供大家探讨

C/C++语言 - 运算符、表达式和语句

,,,,,,,,,, ( http: \ \ www. ncre. cn,, ) 30,,,,,,,, C : C : : 19 : : : /16 : : 96 : : : ISBN 7

C++ 程序设计 实验 3 - 参考答案 MASTER 2017 年 5 月 21 日 1

Microsoft Word - 把时间当作朋友(2011第3版)3.0.b.07.doc

北京大学

2015年计算机二级(C语言)模拟试题及答案(三)

文件

Ps22Pdf

download.kaoyan.com_2006ÄêÌì½ò¹¤Òµ´óѧ¸ß¼¶ÓïÑÔ³ÌÐòÉè¼Æ£¨409£©¿¼ÑÐÊÔÌâ

nooog

获取 Access Token access_token 是接口的全局唯一票据, 接入方调用各接口时都需使用 access_token 开发者需要进行妥善保存 access_token 的存储至少要保留 512 个字符空间 access_token 的有效期目前为 2 个小时, 需定时刷新, 重复

C/C++ 语言 - 循环

/ V 0.9 V V Page 2 of 101

OOP with Java 通知 Project 4: 4 月 19 日晚 9 点

untitled

第3章.doc

C

试卷代号 :1253 座位号 E 口 国家开放大学 ( 中央广播电视大学 )2014 年秋季学期 " 开放本科 " 期末考试 C 语言程序设计 A 试题 2015 年 1 月 E 四! 五 总分! 一 单选题 ( 每小题 2 分, 共 20 分 ) 1. 由 C 语言源程序文件编译而成的目标文件的默

C++ 程序设计 OJ2 - 参考答案 MASTER 2019 年 5 月 3 日 1

Guava学习之Resources

华恒家庭网关方案

C C

Guava学习之CharSequenceReader

untitled

第4章 栈和队列

C/C++ - 结构体、共用体、枚举体

Microsoft PowerPoint - 01_Introduction.ppt

エスポラージュ株式会社 住所 : 東京都江東区大島 東急ドエルアルス大島 HP: ******************* * 关于 Java 测试试题 ******

C

untitled

新・解きながら学ぶJava

プログラムの設計と実現II

Chapter12 Derived Classes

Microsoft PowerPoint - 6. 用户定义类型User-defined Datatypes.ppt [兼容模式]

Microsoft PowerPoint - 0 C复习.ppt [兼容模式]

帝国CMS下在PHP文件中调用数据库类执行SQL语句实例

格式化字符串 Weifeng Sun School of Software, DLUT

C PICC C++ C++ C C #include<pic.h> C static volatile unsigned char 0x01; static volatile unsigned char 0x02; static volatile unsigned cha

Microsoft PowerPoint - 10 模板 Template.pptx

1 LINUX IDE Emacs gcc gdb Emacs + gcc + gdb IDE Emacs IDE C Emacs Emacs IDE ICE Integrated Computing Environment Emacs Unix Linux Emacs Emacs Emacs Un

PowerPoint 演示文稿

Static Enforcement of Security with Types

《C语言程序设计》教材习题参考答案

OOP with Java 通知 Project 2 提交时间 : 3 月 21 日晚 9 点 作业提交格式 学习使用 文本编辑器 cmd, PowerShell (Windows), terminal(linux, Mac)

PowerPoint 演示文稿

网C试题(08上).doc

移动平台应用软件开发 C/C++/JAVA 基础 C 中的预处理指令 主讲 : 张齐勋 移动平台应用软件开发 课程建设小组北京大学二零一五年

C++ 程序设计 OJ1 - 参考答案 MASTER 2019 年 5 月 3 日 1

2015年计算机二级(C语言)模拟试题及答案(四)

内 容 提 要 指 针 持 久 动 态 内 存 分 配 字 符 串 ( 字 符 数 组 ) 2

PowerPoint 演示文稿

Transcription:

参考 : C/C++ 程序员面试指南 杨国祥等编著电子工业出版社 编程规范 1 头文件内有时会定义一些类, 结构体等, 如果被包含多次, 将会出现类型重定义的错误, 所以通常使用预处理指令来解决这个问题 #ifndef 标识 #define 标识. #endif 标识在理论上是可以自由命名的, 但每个头文件的这个标识都应该是唯一的, 标识的命名的规则一般是头文件名全大写, 前后加下划线, 并把头文件中的. 也变成下划线, 如 myprogram.h: #ifndef _MYPROGRAM_H_ #define _MYPROGRAM_H_.. #endif 2 全局变量加前缀 g_( 代表 global) 3 常量全用大写字母 4 指针变量命名 :p+ 变量类型 + 命名函数指针 1 请解析 (*(void (*)())0)() 的含义 解答 : 从后向前逐步分析 : a 当有如下函数声明时:void fun(param); 这个函数的调用方式为 :fun(param); 所以对比知原题的函数没有参数, 可简化 fun(); b 指针函数声明为:void (*pfun) (param); 调用形式为 :(*pfun) (param); 所以对比原题知本题函数的调用方式为 :(*0)(); 即 :(*(void (*)())0)() 把阴影部分去掉 ; 但是函数指针变量不能是个常数, 所以还要把 0 强制转换为函数指针, 根据本题, 可知用 void (*)() 将 0 转化为了一个返回值为 void, 参数为空的函数指针 c 所以*(void (*)())0 表示一个返回值为 void, 没有参数, 并且起始地址为 0 的函数的名字 d 所以(*(void (*)())0)() 就是对 c 中的函数名所对应的函数的调用 e 可以用 typedef 来加深对本句的理解 : typedef void(*pfun)(); (*(pfun)0)(); 这两句和 (*(void (*)())0)() 是等价的 注 : 这样做可以使微处理器从 0 地址启动, 可以模拟开机时候的情形 野指针野指针, 不是 NULL 指针, 而是指向垃圾内存即不可用内存的指针 产生原因 : 1 指针变量声明时没有初始化 任何指针变量刚被创建时都不会自动初始化为 NULL, 而是指向一个随机地址 要养成在声明指针变量的时候将其初始化为 NULL, 如果暂时不知道它的值, 应将其赋值为 NULL char *p1 = NULL; char *p2 = (char *)malloc(100); 2 指针 p 被 free 之后, 没有置为 NULL, 让人误以为 p 是个合法的指针

char *p = (char *)malloc(100); strcpy(p, before ); free(p); //p 所指向的内存被释放, 但是 p 的值不变 if(p!= NULL) // 检测不到错误 strcpy(p, after ); 为了避免这种情况, 指针在 free 之后应赋值为 NULL 3 指针超越了变量的作用范围, 这种情况让人防不胜防 #include<iostream.h> class A public: void Func(void) value = 3; cout<< in fun of A <<endl; public: void f(a *p) A a; p = &a; p->func(); void main(void) A *p; f(p); //a 的作用域结束 int value; p->func(); // p 成了野指针 ; 函数 f 结束时, 变量 a 被释放,p 指向了垃圾内存, 但是在 main 函数中又用 p 调用了 Fun, 而此时 p 所指向的内存不可用 (a 释放后 p 就成了野指针 ), 将导致内存操作错误 常见的一道题 : void GetMemory(char *p) p = (char *)malloc(100); char *str = NULL; getmemory(str); // 执行完这句之后,str 的值仍为 NULL, 如果想改变指针的值 strcpy(str, hello world );//GetMemory 的参数要为二级指针 printf(str); ############################################################################### void *GetMemory(void) char p[] = hello world ; return p; char *str = NULL; str = getmemory()();

printf(str); GetMemory 中 p[] 是局部变量, 函数返回时,p 就被释放掉了,str 便指向了一段无用的内存区域, 输出的 str 将是乱码 ############################################################################### void GetMemory(char **p, int num) *p = (char *)malloc(num); char *str = NULL; getmemory(&str, 100); strcpy(str, hello ); printf(str); *p = (char *)malloc(num); 之后没有判断动态申请内存是否成功而直接使用, 应首先判断 If(NULL == *p)..// 申请失败处理 另外, 没有释放动态申请的内存空间 ############################################################################### char *str = (char *)malloc(100); strcpy(str, hello ); free(str); 在申请了动态内存后没有检查是否申请成功就直接使用, 并且在 free 之后没有将指针置空, str 就成了野指针 一定要记得每次释放动态申请的内存空间后要将指针置空 free(str); str = NULL; 嵌入式编程 1 编码实现某一变量某位清 0 或置 1, 比如清除或置位整型变量 a 的第 3 位 #define BIT3 (0x1 << 3) static int a; void set_bit3(void) a = BIT3; void set_bit3(void) a &= ~BIT3;

2 死循环 a while(1) b for(; ;) // 这两种区别 for 不用比较, 效率稍微高点 c Loop:. goto Loop; 3 用变量 a 给出下面的定义 A 一个整形数 :int a; B 一个指向整形数据的指针 :int *a; C 一个指向指针的指针, 它指向的指针是指向一个整形数 :int **a; D 一个有 10 个整形数据的数组 :int a[10]; E 一个有 10 个指针的数组, 该指针是指向整形数据 :int *a[10]; 总结一下 : 变量声明为 int *a[10] 时, 定义的是指针数组 a; 变量声明为 int (*a)[10] 时, 定义了数组指针 a; 变量声明为 int *a() 时, 定义的是返回值为整型指针的函数 a; 变量声明为 int(*a)() 时, 定义了返回值为整形数据的函数指针 a 接着来 : F 一个指向有 10 个整型数据数组的指针 :int(*a)[10]; G 一个指向函数的指针, 该函数有一个整型参数并返回一个整形数 :int (*a)(int); H 一个有 10 个指针的数组, 该指针指向一个函数, 该函数有一个整形参数并返回一个整形数 : H 是 F 和 G 的联合, 可以用 typedef 来实现, 定义一个函数的别名 : typedef int (*pfun)(int); 再定义这个指针的数组 : pfun a[10]; 即 :int (*a[10])(int); 4 设置地址为 0x67a9 的整型变量的值为 0xaa66 int *ptr; ptr = (int *)0x67a9; *ptr = 0xaa66; 或者 :*(int * const)(0x67a9) = 0xaa66;// 最好不要为了方便采用这种写法 主要考察了是否知道为了访问一个绝对地址, 把一个整形数强制转换为一个指针是合法的, 为什么是合法的呢? 因为无论在什么平台上, 地址长度和整型数据的长度都是一样的, 即一个整型数据可以强制转换成地址指针类型, 只要有意义即可 a 和 &a 的区别写出一下代码的打印结果 #include <stdio.h> void main(void) int a[5] = 1,2,3,4,5; int *ptr = (int *)(&a+1);

printf( %d,%d, *(a+1),*(ptr-1)); return; *(a+1) 就是 a[1], 但 *(ptr-1) 并不是 a[0], 因为 &a+1 并不是数组 a 的首地址加 1, 系统会认为是数组 a 的首地址加上一个数组 a 的偏移, 即偏移了一个数组的大小 (5 个 int 的地址 ), 原式中 int *ptr = (int *)(&a+1); 的结果是,ptr 指向了数组的第六个元素 a[5] 所以输出结果是 2, 5 自己编写一个 strcpy 函数 char *strcpy(char *str1, const char *str2) // 加 const 的目的 assert((str1!= NULL)&&(str2!= NULL)); // 判断指针的合法性 char *address = str1; // 记录目标指针所指向的地址 while((*str1++ = *str2++)!= \0 ); // 拷贝直到 str2 结束 return address; // 返回目标地址 加 const 的目的 : 因为 str2 传入的指针所指向的内容应该是只读型的, 不应该在 strcpy 内被改变 5 char x[] = abcd 和 char y[] = a, b, c, d 有什么不同? 答 : 用单引号引起来的一个字符代表一个整数, 而用双引号引起来的字符, 代表的一个字符串 所以 char x[] = abcd 意思是将字符串 abcd 以及结束符 \0 存到 x 而 char y[] = a, b, c, d 是将 4 个字符存到数组 y 6 == 和!= 的运算符优先级要高于 &,,~,&&, 运算符 7 & 和 &&, 和 有什么区别? 答 :(1)& 和 对操作数进行求值运算 ( 按位与 ),&& 和 只是判断逻辑关系 ;(2)&& 和 在判断左侧操作数就能确定结果的情况下就不再对右侧操作数求值 8 字符型数据占一个字节, 整型数据在 32 位机上占 4 个字节, 指针保存的是一个内存地址, 其长度是和整型数据一致的 9 sizeof 和 strlen 的区别 答 :a sizeof 是一个运算符, 用来返回一个数据类型的长度, 而 strlen 是一个库函数, 用来返回一个字符串的长度 ; b sizeof 的参数可以数数据类型, 也可以是变量 ( 此时 sizeof 后面的括号可以不加 ), 而 strlen 只能以 char * 并且结尾为 \0 的字符串做参数 例 :void main(void) int a = 3; printf ( %d, %d, sizeof(int), sizeof(a)); char *p = hello 123! ; printf( %d, strlen(p)); printf( %d, sizeof(p)); 结果为 4,4,10,4 c 数组做 sizeof 的参数不退化, 传递给 strlen 就会退化为指针 void main(void)

char str[10] = abcd ; int x = strlen(str); int y = sizeof(str); printf( %d,%d,x,y); 结果为 4,10 因为数组作为参数传给函数时, 传递的是指向数组首地址的指针而不是数组数据结构 10 结构体内存对齐问题首先介绍位域的概念 : 所谓位域就是把一个字节中的位按照实际的需求分成不同的区域, 表明每个区域位数, 区域的域名, 并允许程序按照域名进行操作 定义 : struct 位域的结构名 位域列表 ; 位域列表的形式为 : 类型说明符 位域名 : 位域的长度 如 :struct bs int a:8; int b:2; int c:6; ; 对于位域的定义, 有一下几点说明 : a 一个位域必须存储在同一个字节中, 不能跨接两个字节 如果一个字节所剩空间不够存放另一个位域时, 应从下一单元起存放该位域 也可以有意使某位域从下一单元开始 例如 : struct wy unsigned a:6; unsigned :0; unsigned b:4; unsigned c:4; ; 在这个位域定义中,a 占第一字节的 6 位, 后两位填 0 表示不使用,b 从第二字节开始, 占用 4 位,c 占用 4 位 b 由于位域不允许跨两个字节, 因此位域的长度不能大于一个字节的长度, 也就是不能超过 8 位二进制位 c 位域可以无位域名, 这时它只用来填充或调整位置 无名的位域是不能使用的 好了, 做题 : 写出下面代码的输出结果 : struct s1 struct s2 int i:8; int i:8; char j:4; int j:4; int a:4; double b; double b; int a:4; ; ;

struct s3 int i; char j; double b; int a; ; printf( sizeof(s1) = %d\n,sizeof(s1)); printf( sizeof(s2) = %d\n,sizeof(s2)); printf( sizeof(s3) = %d\n,sizeof(s3)); 结果 :sizeof(s1) = 16 sizeof(s2) = 24 sizeof(s3) = 32 每个数据都要对照结构体内最大数据的最小公倍数对齐 S1 按 8 字节对齐,double 是 8 字节类型数据 11 宏在使用过程中由于直接替代会导致副作用即使小心地使用括号括起了宏的参数 表达式, 但是有些问题还是避免不了的 如写一个标准宏 MIN #define min(a,b) ((a) <= (b)? (a) : (b)) 在调用时如果出现下面情况 : ((++*p) <= (x)? (++*p) : (x)), 这样 p 指针就自加了两次, 违背了程序员的本意 12 typedef 为复杂的声明定义一个新的简单的别名使用方法 : 在原来的声明中逐步用别名替换一部分复杂声明, 把带变量名的部分留到最后替换, 得到的就是原声明的最简化版 例 1: char *(*a[7])(char, int *) 这条语句定义了一个包含 7 个指针元素的数组 a, 指针指向的函数有两个参数, 一个是字符型, 一个是整型指针 函数的返回值是字符指针型数据, 但是这条语句的书写形式不利于阅读, 此时可用 typedef 做如下简化 : typedef char *(*pfun)(char, int *); pfun a[7]; 例 2: void (*a[7]) (void (*) ()); 这条语句定义了 7 个函数指针元素的数组 a, 这个函数有一个函数指针参数 ( 这个函数无参数, 无返回值 ), 可以将 void (*)() 先简化为 :typedef void (*pfunparam)(), 带入原式, typedef void (*a[7])(pfunparam); 接下来的步骤和例 1 相同, 接着进行替换 : typedef void (* pfun)(pfunparam); 最后原式可以简化为 : pfun a[7]; 13 一个参数可以既是 const 又是 volatile 的吗? 分析 :volatile 修饰的变量的值是程序不可控的, 可以不被程序明确指明的方式改变, 如外部端口 它的变化不用程序内部赋值语句就可实现 const 修饰的变量在程序中是只读的, 不能被改变的 但这仅限于程序内部, 它可以被程序外的东西改变 例如用 const 修饰外部端口, 程序内部不可以修改它的值, 但是外部却可以 另外一种情况是只读的状态寄存器, 它受 volatile 修饰, 但他却可能被意想不到的改变 综上, 可以用 const 和 volatile 同时修饰变量, 表示这个变量在程序内部是只读的, 不能被改变的, 只在程序外部条件变化下改变 2011/2/17 笑寒