程序员面试宝典题目

5.6 a,b交换比较

#include 
#include using namespace std;int main(){int a = 10, b = 5;int large1 = ((a + b) + abs(a - b)) / 2;int large2 = (a*(a/b) + b*(b/a)) / (a/b + b/a);/* b < 0时, b>>31是b的符号位1,b & 1 为b, a -= b就是a = a - (a - b) = b* b > 0时, b>>31是b的符号位0,b & 0为0, a -= b就是a = a - 0 = a*  */b = a - b; a -= b & (b >> 31);int large3 = a;int c[a] = {a, b};int z = a - b;z = (z>>31) & 1;int large4 = c[z];int pair[2] = {a, b};int large5 = pair[a < b];return 0;
}

交换两个数的宏 

#define swap1(a, b) (a=a+b;b=a-b;a=a-b;)/* a+b可能会溢出 */
/* swap2 虽然不会溢出,a b只能是整型* b=a^b=a^b^b=a^(b^b)=a* a=a^b^a=a^a^b=b* */
#define swap2(a, b) (a=a^b;b=a^b;a=a^b;)
#define swap3(a, b) {int size = sizeof(a); char* temp = (char*)malloc(size);memcpy(temp, &a, size);\memcpy(&a, &b, size); memcpy(&b, temp, size); free(temp);}//C++
#define swap4(a, b) {char tempBuf[10];memcpy(temp, &a, sizeof(a)); memcpy(&b, &a, sizeof(a));\memcpy(&b, tempBuf, sizeof(b));}//C

5.7 C和C++的关系

在C++中调用C编译器编译后的函数为什么要加extern "C"?

#include 
#define SUB(x,y) x-y
#define ACCESS_BEFORE(element,offset,value) *SUB(&element, offset) = value
int main() {int array[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };int i;ACCESS_BEFORE(array[5], 4, 6);printf("array: ");for (i = 0; i < 10; ++i) {printf("%d", array[i]);}printf("\n");return (0);
}

此处程序最后是*&array[5]-4=6.。根据优先级,算术运算优先级高于赋值运算符优先级,最后是6-4=2,因为减号返回一个数而不是合法的左值,所以编译报错

2.声明一个#define宏定义用以表示1年终有多少秒?

#define SECONDS_PER_YEAR (60*60*24*365)UL

后缀UL表示SECONDS_PER_YEAR是一个长整形,C语言中默认宏中数字是int

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

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

U表示该常数用无符号整型方式存储,相当于 unsigned int ,整形默认int
L表示该常数用长整型方式存储,相当于 long 
F表示该常数用浮点方式存储,相当于单精度 float,浮点数默认double

在C++中,函数重载中通常用在函数参数匹配上,尤其是重载的时候,比如说void fun(int), void fun(float),调用fun(0.5)时,可能会觉得应该调用void fun(float),因为0.5是浮点数,但实际上这个调用在语法标准上是有歧义的。因为0.5是默认的double类型,double转换为int和float的优先级是一样,所以加上后缀f,像fun(0.5F),这样就指明调用第二个函数。避免导致歧义。

数值常数的后缀不区分大小写

整形常数的表示形式有:十进制形式,以0开头的八进制形式,以0x开头的十六进制形式,无二进制形式

6.2 const

定义局部变量
const int n = 5;
int const n = 5;//这两种写法没有区别在定义指针变量时
int b = 500;
const int *a = 500;
*a = 600;//情况1:错误,不能通过常量指针(*a)修改指针指向的值int b = 500;
int const *a = &b;
b = 600;
cout<< *a <

const和#define相比有什么不同?

const和#define都可以定义常量;const常量有数据类型,编译器可以进行类型安全检查,但是宏常量只是进行字符替换没有安全检查,可能会产生意想不到的错误;有些集成化的调试工具可以对const常量进行调试,但是不能对宏常量进行调试;在C++程序只使用const常量而不使用宏常量。

在C语言中,const总是占用内存,名字是全局符,C编译器不能把const看成编译器件的常量,因此const bufsize = 100;char buf[bufsize];会编译错误,编译期间找不到bufsize的值。在C++中不能写const bufsize声明,但在C中可以,const在C中是外部链接的,在C++中是内部链接的,因此在C++中需要使用extern 关键字,extern const bufsize才可以。

有类如下:const修饰的函数f()怎么才能修饰成员变量?

class A_class
{void f() const{    ……}
}

数据成员加上mutable后可以放在const修饰的成员函数中 

#include 
#include 
using namespace std;class C
{
public:C(int i):m_Count(i){}//C(int i):m_Count(i){} //冒号后面m_Count(i)表示对成员变量初始化int  incr() const{return ++m_Count;}int decr() const{return --m_Count;}
private:mutable int m_Count;
};int main()
{C c1(0), c2(10);for(int tmp, i = 0; i < 10; i++){tmp = c1.incr();cout<

冒号的用法

https://segmentfault.com/a/1190000000345680

//位段,bit field
typedef struct_XXX{unsigned char a:4;//结构体内域的定义unsigned char c;
}XXX;
//初始化结构体成员列表
class myClass
{
public:myClass();~myClass();int a;const int b;
}myClass::myClass():a(1),b(1)//初始化结构体成员列表
{}
/*
初始化列表与在构造函数内对结构成员赋值作用相同,都是初始化结构体成员,但还是有些区别的。初始化列表
是对变量初始化,而在构造函数内是进行赋值操作,两种操作在const类型的数据上不一样。const类型数据必须
初始化,不能对const类型应用赋值运算符,因此const类型的数据只能进行列表初始化
*/
//这样代码就会出错
myClass::myClass()
{a = 1;//没错,效果相当于在初始化列表中初始化b = 1;//出错,const类型不能进行赋值操作
}
//列表初始化的顺序要与变量声明的顺序一致
myClass::myClass():b(1),a(b)
{
}
//这样执行的结果b=1,a是随机数;而不是b=1,a=1。
//对于继承的类来说,在初始化列表也可以进行基类的初始化,初始化的顺序是先基类初始化,再按子类的变
//量声明顺序初始化。
//条件运算符 ? :,需要注意的是条件运算符优先级很低
int i = 3, j = 2;
cout<< i>j?i:j;//出错,?:优先级低于<<,执行顺序为(cout<j?i:j,cout<j)?i:j;//输出1或0,相当于(cout<<(i>j))作为?:的判决条件,i>j时输出1,否则0
cout<<(i>j?i:j);//i>j输出i,否则输出j
//域操作符
void A::f() //f()函数是类A的成员函数

6.3 sizeof 

结构体对齐,结构体长度一定是最长的数据元素的整数倍,如果结构体内存在长度大于处理器位数的元素,那么就以处理器的位数为对齐单位。但是结构体内类型相同的连续元素和数组一样将在连续的空间,不会被直接对齐。

struct
{short a1;short a2;short a3;
}A;
sizeof(A);//6,相同的元素像数组一样存储在连续的空间,所以是6struct
{long a1;short a2;
}B;
sizeof(B);//8,a1四字节,a2 两字节,4+2=6不是4的整数倍,补空字节,8字节class A
{
private:short a1;short a2;short a3;
};//sizeof(A),6字节class B
{
private:bool m_bTemp;int m_nTemp;bool m_bTemp2;
};
|bool|--|--|--|
|-----int-----|
|bool|--|--|--|
//12字节,不连续,都按最长的四字节对齐
class C
{
private:int m_nTemp;bool m_bTemp;bool m_bTemp2;
};//8字节,4+2=6,补空到4的整数倍8字节

数据对齐是,是指数据所在的内存地址必须是该数据长度的整数倍。在访问内存时,如果地址按4字节对齐访问效率会高很多,原因在于访问内存的硬件电路。一般情况下,地址总线总是按照对齐后的地址来访问。例如当需要从0x00000001开始访问4字节内容,系统首先需要以0x00000000开始读4字节,从中取得3字节,然后再用0x00000004作为开始地址获取下一个4字节,再从中得到第一个字节,两次组合得到想要的内容,但是如果地址一开始就是对齐到0x00000000,则系统只需要一次读写即可。

#include 
using namespace std;class A1
{
public:int a;static int b;A1();~A1();
}int main()
{count<
char* ss = "0123456789";
//sizeof(ss); 4字节,任意指针大小是4字节
//sizeof(*ss); 1字节,*ss表示第一个字符0char ss[] = "0123456789";
//sizeof(ss); 11字节,sizeof计算到数组的‘\0’的位置
//sizeof(*ss); 1字节,*ss是第一个字符char ss[100] = "0123456789";
//sizeof(ss); 100字节,ss表示内存中分配的大小
//strlen(ss); 10字节,strlen计算到'\0'位置int ss[100] = "0123456789";
//sizeof(ss); 400字节,内存中分配100*4
//strlen(ss); strlen参数只能是char*, 且必须有'\0'结尾
//sizeof是运算符,可以用类型做参数,strlen是函数

数组做sizeof的参数不退化,传递给strlen就退化为指针;sizeof在编译时就计算,是类型或变量的长度,这就是sizeof(x)可以用来定义数组维度的原因;strlen是在运行时计算字符串长度的,而不是计算内存的大小;sizeof后面是类型必须有括号,变量名不用加括号,因为sizeof是操作符,不是函数。

char str[20] = "0123456789";
int a = strlen(str); //a = 10;
int b = sizeof(str); //b = 20;

数组作为参数传递给函数时传递的是指针而不是数组,传递的是数组的首地址,如func(char  [])等价于func(char*).C++里传递数组永远都是传递指向数组首元素的指针;如果要在函数内使用数组,需要

void fun(usigned char* p1, int len)
{usigned char* buf = new usigned char[len+1];memcpy(buf, p1, len);return;
}
#include 
#include 
using namespace std;int main(int argc, char* argv[])
{//To output "TrendMicroSoftUSCN"string strArr1[] = {"Trend", "Micro", "Soft"};string *pStrArr1 = new string[2];pStrArr1[0] = "US";pStrArr1[1] = "CN";for(int i = 0;i < sizeof(strArr1)/sizeof(string); i++){cout<
(1) unsiged 影响的是最高位bit的意义(正/负),数据长度是不会改变的
//sizeof(unsigned int) = sizeof(int)
(2) typedef short WORD ,sizeof(short) = sizeof(WORD)
(3) 对函数使用sizeof, 在编译阶段会被函数返回值的类型取代。如:int f1() {return 0;}count<

7.1 指针基本问题

指针与应用的区别?非空区别:不存在指向空值的引用,函数入参声明为引用可以利用这点省去入参非空检查,而指针可以指向空;可修改性:指针可以被重新复制以指向另一个不同的对象,而引用总是指向初始化时指定的对象,但对象的内容可以修改;应用区别:

#include using namespace std;
int main()
{int* pi;*pi = 5;//错误,整数指针pi并没有指向具体的地址,给其复制因不知道该往什么地址放值而错误const double di;//const 常量一定要初始化return 0;
}
void swap(int* p, int* q)
{int* temp;*temp = *p;*p = *q;*q = *temp;
}
//int* temp,*temp = *p是不符合逻辑的,因为int* temp并没有为temp分配内存,*temp = *int不是指向
//而是复制;系统临时随机地为*temp分配内存,使其存储*p的值,且函数结束后不收回,会造成内存泄露;在某
//些编译器下可以编译过,但是在vs2008等严格的编译器会报错

12.位运算与嵌入式

7.要求设置一绝对地址0x67a9的整形变量的值为0xaa66。编译器是ANSI编译器。
//把整形数强制转换成为指针是合法的
int *ptr;
ptr = (int*)0x67a9;
*ptr = 0xaa66;
8.找出下面代码的错误
unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
//不严谨,没有考虑处理器字长;对于unsigned int 不是16位的机器来说,上述代码是错误的,改为
unsigned int compzero = ~0;
//static分配在内存的全局变量区,在函数体内时,函数退出时并不释放, 下次执行函数时仍会使用上次退出时
的值。
#include
#include
#include "train/train.h"
using namespace std;int sum(int a)
{int c = 0;static int b = 3;c += 1;b += 2;b += 3;printf("Init b:%d\t", b);return (a+b+c);
}int main()
{int I;int a = 2;for(I=0;I<5;I++){printf("%d.\n", sum(a));}return 0;
}
/* 
Init b:8	11.
Init b:13	16.
Init b:18	21.
Init b:23	26.
Init b:28	31.*/
//大小端描述字节顺序
//大端:从地地址开始先存储高位字节,符合人的书写习惯
#include
#include
#include "train/train.h"
using namespace std;typedef struct bitStruct
{int b1:5;int :2;int b2:2;
}bitStruct;int main()
{bitStruct b;printf("%d.\n", sizeof(bitStruct));memcpy(&b, "EMC", sizeof(b));printf("%d, %d.\n", b.b1, b.b2);return 0;
}
/* 
高<----------------------------------------低
ASCII:               1M(0x4D)          E(0x45)01001101      01000101--=====b2   b1
b1 00101 有符号数扩展高位都是0,结果为5
b2 10    有符号数扩展高位1后得到原码,计算补码得到结果-2*/

13.数据结构基础


#include 
#include 
#include 
#include 
#include typedef struct student
{int data;struct student *next;
}node;node* creat(void)
{node* head, *p, *s;int x, cycle = 1;head = (node*)malloc(sizeof(node));p = head;while(cycle){printf("\nplease input data");scanf("%d", &x);if(x != 0){s = (node*)malloc(sizeof(node));s->data = x;printf("\n%d", s->data);p->next = s;p = s;}else{cycle = 0;}}head = head->next;p->next = NULL;printf("\n%d", head->data);return head;
}int length(node *head)
{int n = 0;node *p;p = head;while(p != NULL){p = p->next;n++;}return n;
}void print(node* head)
{node* p;int n;n = length(head);printf("\nNow, These %d records are: \n", n);p = head;if(head != NULL){while(p != NULL){printf("\n %d", p->data);p = p->next;}}return;
}node* del(node* head, int target_num)
{node *p1, *p2;p1 = head;//p1为要删除的节点,p2为p1前面的节点while(p1->data != target_num && p1->next != NULL){p2 = p1;p1 = p1->next;}if(target_num == p1->data){if(p1 == head){head = p1->next;free(p1);}else{p2->next = p1->next;}}else{printf("\n %c could not not been found", target_num);}return head;
}node* insert(node* head, int num)
{node* p0;node* p1;node* p2;p1 = head;p0 = (node*)malloc(sizeof(node));p0->data = num;//p0为待插入的节点,数据从小到大顺序插入节点while(p0->data > p1->data && p1->next != NULL){p2 = p1;p1 = p1->next;}if(p0->data <= p1->data){if(head == p1){p0->next = p1;head = p0;}else{p2->next = p0;p0->next = p1;}}else{p1->next = p0;p0->next = NULL;}return head;
}node* sort(node* head)
{node *p;int n; int temp;n = length(head);if(head == NULL || n == 1){return head;}p = head;for(int j = 1;j < n;j++){p = head;for(int i = 0; i < n - j; ++i){if(p->data > p->next->data){temp = p->data;p->data = p->next->data;p->next->data = temp;}p = p->next;}}return head;
}/* 逆置单链表 */
node* reverse(node* head)
{node *p1, *p2, *p3;if(head == NULL || head->next == NULL){return head;}p1 = head;p2 = p1->next;while(p2){p3 = p2->next;p2->next = p1;p1 = p2;p2 = p3;}return head;
}/* 找到单链表中间节点 */
node* searchmid(node* head)
{node *temp = head;node *p = head;while(head->next->next != NULL){p = p->next->next;temp = temp->next;}return temp;
}

13.5 栈

// 用两个栈实现队列功能
//入队列:入栈A
//出队列: 如果栈B不为空,直接弹出栈B的数据;如果栈B为空,则依次弹出A的数据放入栈B中,再弹出栈B的数据
#include 
#include 
using namespace std;
template
struct MyQueue
{void push(T &t){s1.push(t);}T front(){if(s2.empty()){if(s1.size() == 0) throw;while(!s1.empty()){s2.push(s1.top());s1.pop();}}return s2.top();}void pop(){if(s2.empty()){if(s1.size() == 0) throw;while(!s1.empty()){s2.push(s1.top());s1.pop();}}if(!s2.empty())s2.pop();}stack s1;stack s2;
};int main()
{MyQueue mq;int i;for(i=0;i<10;++i){mq.push(i);}for(i=0;i<10;i++){cout<

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章