iOS笔试面试iOS面试题iOS Dev

可能碰到的iOS笔试面试题(4)--C语言

2016-04-25  本文已影响1165人  b485c88ab697

C语言,开发的基础功底,iOS很多高级应用都要和C语言打交道,所以,C语言在iOS开发中的重要性,你懂的。里面的一些问题可能并不是C语言问题,但是属于计算机的一些原理性的知识点,所以我就不再另外写一篇文章了,直接写在这里。

当你写下面的代码时会发生什么事?

用预处理指令#define声明一个常数,用以表明1年中有多少秒(忽略闰年问题)

define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL(UL无符号长整形)

写一个"标准"宏MIN ,这个宏输入两个参数并返回较小的一个。

define MIN(A,B) ((A) <= (B) ? (A) : (B))

写一个标准宏Max,并给出以下代码的输出

int array[5] = {1, 2, 3, 4, 5};
int *p = &array[0];
int max = Max(*p++, 1);
printf("%d %d", max, *p);
参考答案: 1,2
#define Max(X, Y) ((X) > (Y) ? (X) : (Y))
当看到宏时,就会想到宏定义所带来的副作用。对于++、–,在宏当中使用是最容易产生副作用的,因此要慎用。
分析:
p指针指向了数组array的首地址,也就是第一个元素对应的地址,其值为1.
宏定义时一定要注意每个地方要加上圆括号
*p++相当于*p, p++,所以Max(*p++, 1)相当于:
(*p++) > (1) ? (*p++) : (1)
=>
(1) > (1) ? (*p++) : (1)
=>
第一个*p++的结果是,p所指向的值变成了2,但是1 > 1为値,所以最终max的值就是1。而后面的(*p++)也就不会执行,因此p所指向的地址对应的值就是2,而不是3.
扩展:如果上面的*p++改成*(++p)如何?
(*++p) > (1) ? (*++p) : (1)
=>
(2) > (1) ? (*++p) : (1)
=> 
max = *++p;
=> 
*p = 3,max = 3;
 

define定义的宏和const定义的常量有什么区别?

λ   #define定义宏的指令,程序在预处理阶段将用#define所定义的内容只是进行了替换。因此程序运行时,常量表中并没有用#define所定义的宏,系统并不为它分配内存,而且在编译时不会检查数据类型,出错的概率要大一些。
λ   const定义的常量,在程序运行时是存放在常量表中,系统会为它分配内存,而且在编译时会进行类型检查。
#define定义表达式时要注意“边缘效应”,例如如下定义:
#define N 2 + 3 // 我们预想的N值是5,我们这样使用N
int a = N / 2;  // 我们预想的a的值是2.5,可实际上a的值是3.5

关键字volatile有什么含意?并给出三个不同的例子

完成字符串拷贝可以使用sprintf、strcpy、以及memcpy函数,请问这些函数有什么区别?你喜欢哪一个?为什么?

这些函数的区别在于实现功能以及操作对象不同。
- strcpy:函数操作的对象是字符串,完成从源字符串到目的字符串的拷贝功能。
- sprintf:这个函数主要用来实现(字符串或基本数据类型)向字符串的转换功能。如果源对象是字符串,并且指定%s格式符,也可实现字符串拷贝功能。
- memcpy:函数顾名思义就是内存拷贝,实现将一个内存块的内容复制到另一个内存块这一功能。内存块由其首地址以及长度确定。因此,memcpy 的操作对象适用于任意数据类型,只要能给出对象的起始地址和内存长度信息、并且对象具有可操作性即可。鉴于memcpy函数等长拷贝的特点以及数据类型代表的物理意义,memcpy函数通常限于同种类型数据或对象之间的拷贝,其中当然也包括字符串拷贝以及基本数据类型的拷贝。
- 对于字符串拷贝来说,用上述三个函数都可以实现,但是其实现的效率和使用的方便程度不同:
- strcpy 无疑是最合适的选择:效率高且调用方便。
- snprintf 要额外指定格式符并且进行格式转化,麻烦且效率不高。
- memcpy 虽然高效,但是需要额外提供拷贝的内存长度这一参数,易错且使用不便;并且如果长度指定过大的话(最优长度是源字符串长度 + 1),还会带来性能的下降。其实 strcpy 函数一般是在内部调用 memcpy函数或者用汇编直接实现的,以达到高效的目的。因此,使用 memcpy 和 strcpy 拷贝字符串在性能上应该没有什么大的差别。
- 对于非字符串类型的数据的复制来说,strcpy和snprintf一般就无能为力了,可是对memcpy却没有什么影响。但是,对于基本数据类型来说,尽管可以用 memcpy 进行拷贝,由于有赋值运算符可以方便且高效地进行同种或兼容类型的数据之间的拷贝,所以这种情况下memcpy几乎不被使用。memcpy的长处是用来实现(通常是内部实现居多)对结构或者数组的拷贝,其目的是或者高效,或者使用方便,甚或两者兼有。

sprintf,strcpy,memcpy使用上有什么要注意的地方

static关键字的作用

static关键字区别:

关键字const

堆栈

数组和指针的区别

引用和指针的区别

用变量a给出下面的定义

请写出以下代码输出

int a[5] = {1, 2, 3, 4, 5};
int *ptr = (int *)(&a + 1);
printf("%d, %d", *(a + 1), *(ptr + 1));
参考答案: 2, 随机值
这种类型题好像挺常见的。考的就是C语言上的指针的理解和数组的理解。
分析:
a代表有5个元素的数组的首地址,a[5]的元素分别是1,2,3,4,5。接下来,a + 1表示数据首地址加1,那么就是a[1],也就是对应于值为2.但是,这里是&a + 1,因为a代表的是整个数组,它的空间大小为5 * sizeof(int),因此&a + 1就是a+5。a是个常量指针,指向当前数组的首地址,指针+1就是移动sizeof(int)个字节。
因此,ptr是指向int *类型的指针,而ptr指向的就是a + 5,那么ptr + 1也相当于a + 6,所以最后的*(ptr + 1)就是一个随机值了。而*(ptr – 1)就相当于a + 4,对应的值就是5。

简述内存分区情况

用NSLog函数输出一个浮点类型,结果四舍五入,并保留一位小数

float money = 1.011;
NSLog(@"%.1f", money);

文章如有问题,请留言,我将及时更正。

满地打滚卖萌求赞,如果本文帮助到你,轻点下方的红心,给作者君增加更新的动力。

上一篇 下一篇

猜你喜欢

热点阅读