void main()
{
a.x[0] = 10;
a.x[1] = 1;
printf("%d",a.i);
}
答案:266 (低位低地址,高位高地址,内存占用情况是Ox010A)
2:(微软笔试题)
int func(x)
{
int countx = 0;
while(x)
{
countx ++;
x = x&(x-1);
}
return countx;
}
假定x = 9999。 答案:8
思路:将x转化为2进制,看含有的1的个数。
3:不用比较算符,不用if,得出int a, b的较大者。
解决方案1:
这个貌似是终极方案了:
#define MyMax(a, b) (((a)-(b))&0x80000000 ? (b) : (a) )
cout<
解决方案2:(爽哥提供的方案)
char* str_vec[2];
str_vec[0] = "a>=b";
str_vec[1] = "a
int a = 10;
int b = 11;
int idx = (unsigned int)(a-b)>>31; // 要转化为无符号数
cout<
4:
C++中不能重载的算符有:“.”、“::”和“sizeof” 3个.
另外“?:”算符由于重载的话没有意义,一般也不让重载。
5:
再给出常用的C变量的定义方式:
a) 一个整型数(An integer)
b) 一个指向整型数的指针(A pointer to an integer)
c) 一个指向指针的的指针,它指向的指针是指向一个整型数(A pointer to a pointer to an integer)
d) 一个有10个整型数的数组(An array of 10 integers)
e) 一个有10个指针的数组,该指针是指向一个整型数的(An array of 10 pointers to integers)
f) 一个指向有10个整型数数组的指针(A pointer to an array of 10 integers)
g) 一个指向函数的指针,该函数有一个整型参数并返回一个整型数(A pointer to a function that takes an integer as an argument and returns an integer)
h) 一个有10个指针的数组,该指针指向一个函数,该函数有一个整型参数并返回一个整型数( An array of ten pointers to functions that take an integer argument and return an integer )
答案是:
a) int a; // An integer
b) int *a; // A pointer to an integer
c) int **a; // A pointer to a pointer to an integer
d) int a[10]; // An array of 10 integers
e) int *a[10]; // An array of 10 pointers to integers
f) int (*a)[10]; // A pointer to an array of 10 integers
g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
// 扩展1 函数指针数组
定义一个10个元素的数组,元素是函数指针,函数的参数为(int,int),返回值为int
方法1:int (*p[10])(int,int);
方法2:typedef int (*PFUN)(int,int)
PFUN p[10];
// 使用方法
p[0](1,1);
p[1](1,1);
函数指针数组的应用:
// 扩展2 指向函数指针数组的指针
方法1:int (*(*ppfun)[2])(int,int);
ps:将方法2中的3)式代入1)式中即可得到
方法2:typedef int (*PFUN)(int,int) // ----------------------------------------------1)
PFUN p[10]; // 函数指针数组--------------------------------2)
PFUN (*pp)[10] = &p; // 指向函数指针数组的指针--------------------3)
// 使用方法
(*pp)[0](1,1);
(*pp)[1](1,1);
参考资料:
如果你觉得你懂了,那么做下面的题:
(1) float(**def)[10] def是什么?
(2) double*(*gh)[10] gh是什么?
(3) double(*f[10])() f是什么?
(4) int*((*b)[10]) b是什么?
(5) int(*(*f)(int,int))(int) f是什么?
答案:
(1) def是一个指针, 指向的对象也是一个指针, 指向的指针最终指向的是10个float构成的数组.
(2) gh是指针, 指向的是10个元素构成的数组, 数组的元素是double*类型的指针.
(3) f是10个元素构成的数组, 每个元素是指针, 指针指向的是函数, 函数类型为无参数且返回值为double. 下面要讲的窍门的例子跟这个很类似.
(4) b是指针,指向的是10个元素构成的数组, 数组元素为int*类型的指针.
(5)f是一个函数指针,指向的函数是具有两个int型参数并返回一个函数指针的函数,返回的函数指针指向一个有一个int参数并返回int的函数
呵呵,做这样的题是不是有点崩溃???下面介绍一个好方法。
窍门如下:
如果我们碰到复杂的类型声明,该如何解析它?例如:
char (*a[3])(int);
a到底被声明为什么东东?指针?数组?还是函数?
分析时,从a 最接近(按运算符优先级)处开始。我们看到a最接近符号是[ ]——注意:*比[ ]的优先级低。a后既然有[ ],那么a是数组,而且是包含3个元素的数组。
那这个数组的每个元素是什么类型呢?虽然数组a只含有a[0]、a[1]、a[2]三个元素,a[3]实际上已经越界,但在分析数组a的元素的类型时,我们正好需要形式上的元素a[3]。知道了a[3]的类型,就知道了a的元素的类型。 a[3]是什么类型?是指针,因为它的前面有*. 由此可知,数组a的元素是指针。
光说是指针还不够。对于指针,必须说出它指向的东东是什么类型。它指向的东东是什么,就看*a[3]是什么(a[3]是指针,它指向的东东当然是*a[3])了。继续按优先级观察,我们看到*a[3]后面有小括号,所以可以肯定*a[3]是函数。即数组a的元素是指向函数的指针。
指向的是什么类型的函数?这很明显,是入参为int、返回值为char的类型的函数。
至此解析完毕。
按上述方法,再复杂的也可以一步步解析出来。
就像习武不是为了打人而是为了防身一样,我们了解上述方法是为了看懂别人写的复杂声明,而不是为了在实践中自己去构造这种复杂的东东。实在需要复杂声明时,可以用typedef替代一部分。例如上面语句可改成两句:
typedef char (*FUN_PTR)(int);
FUN_PTR a[3];
这样就清晰多了。
此外,上面的分析方法还让我们对某些东西的本质更加清楚。比如,n维数组的本质都是一维数组。看个具体的例子:
int a[3][5];
这句声明的是一个包含3个元素的一维数组,其每个元素又是一个由5个int数构成的数组。我们不能理解为:a是一个包含5个元素的一维数组,其每个元素又是一个由3个int数构成的数组。为什么?还是按上面的方法分析,这里从略。
有的书上或网上提供"向右看,向左看"的方法, 其实缺乏通用性, 比如它不适用于对多维数组本质的分析. 而且这种方法掩盖了本质. 本质应该是按上面所讲的,根据运算符优先级逐层剥开.
参考:
// 扩展3 指向成员函数的函数指针
三)在C++类中使用函数指针。
//形式3:typedef 返回类型(类名::*新类型)(参数表)
class CA
{
public:
char lcFun(int a){ return; }
};
CA ca;
typedef char (CA::*PTRFUN)(int);
PTRFUN pFun;
void main()
{
pFun = CA::lcFun;
ca.(*pFun)(2);
}
在这里,指针的定义与使用都加上了“类限制”或“对象”,用来指明指针指向的函数是哪个类的,这里的类对象也可以是使用new得到的。比如:
CA *pca = new CA;
pca->(*pFun)(2);
delete pca;
而且这个类对象指针可以是类内部成员变量,你甚至可以使用this指针。比如:
类CA有成员变量PTRFUN m_pfun;
void CA::lcFun2()
{
(this->*m_pFun)(2);
}
一句话,使用类成员函数指针必须有“->*”或“.*”的调用。
6:
struct foo
{
foo(){};
void fun(){};
};
下列语句对不对
foo f;
f.fun();
foo f2(); // --------------->错误! 无参数的构造函数 不可以使用()号 直接 写变量名字即可!
f2.fun();
7:关于字节对齐
(强调!!!结构体自身也要对其,默认按照其对大元素的对齐值对齐!!!)
假设vc默认8字节对齐
#pragma pack(8)
typedef struct C{
double a;
short c;
int d;
char b;
};
sizeof(C) = 24;
分析:按照数据类型自身的对齐,应该是20。 然后结构体本身也要有自己的对齐,按照结构体内成员最大的对齐方式对其,也就是double的8字节对齐,所以就是24
同样结构体,如果加上
#pragma pack(4)
....
#pragma pack() // 取消指定对齐
那么sizeof(C) = 20; 因为指定了4字节对齐,结构体也按照4字节对齐。
再来个例子,做对了,就理解了
#pragma pack(8)
typedef struct C{
double* c;
int a;
char d;
};
sizeof(C) = 12; 结构体内最大的字节对齐为4,所以,结构体本身也按4字节对齐。
理论在于:
1)数据类型自身的对齐值:就是上面交代的基本数据类型的自身对齐值。
2)指定对齐值:#pragma pack (value)时的指定对齐值value。
3)结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值。
4)数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小的那个值。
char型数据,其自身对齐值为1,对于short型为2,对于int,float,为4, 对于double类型,为8,单位字节
7(腾讯笔试题): 关于 += 和 ++
int i=1;
i+=++i+(i++);
cout< 分析, 从右向左, 表达式右侧为 3 + 1; 此时 i=3, 所以 3+=4 =》 7
8:(深信服笔试题)
下列算符的优先级 % & . && <= =
优先级顺序为(由高到底):. & % <= && =
9:^ 是与或符! 不是指数运算符!搞matlab搞多了 就会把当成指数算符了。 :(
10:fun((exp1, exp2), (exp3, exp4, exp4)) 问该函数共几个参数?
答案,2个,分别是 exp2和exp4, exp1,exp3,exp4也并非无用,是先执行exp1,才执行exp2.
‘,’号是个运算符,自左向右运算。常用语循环语句。eg:
for( i=1, j=1; ....; .... )
10:分析如下输出
struct C180 {
C180() {
foo();
this->foo();
}
void virtual foo() {
cout << "<< C180.foo this: " << this
<< " vtadr: " << *(void**)this
<< endl;
}
};
struct C190 : public C180 {
C190() {}
void virtual foo() {
cout << "<< C190.foo this: " << this
<< " vtadr: " << *(void**)this
<< endl;
}
};
main()
{
C190 c190;
}
// 输出为
C180.foo this: ***** vtadr:*****
C180.foo this: ***** vtadr:*****
11下面的代码有什么问题?(百度2010)
cin>>num;
int *pInt = int[num];
答案:
cin没有检查返回值。应该:
cin>>num;
if(!cin.fail())
{ int *pInt = int[num]; }
通常来说,以下情况,会导致failbit置位,从而使得cin.fail()返回值为真
1。未能读取到预期的字符,例如int a; cin >> a; 的时候输入了字符
2。I/O失败,例如试图访问不可访问的文件或写入受保护的磁盘、文件。
3。读取到文件尾,即读取文件结尾标志EOF,这时cin.fail()和cin.eof()的返回值都将为真。
12 关于大小端
在小端机器上(eg:x86),下面代码的输出:
view plaincopy to clipboardprint?
01.void print_px( unsigned char* px )
02.{
03. int a = (int)(*px);
04. cout<< a <05.}
06.void main()
07.{
08. int x = 0x04030201;
09. unsigned char* px = (unsigned char*)&x;
10. print_px(px++);
11. print_px(px++);
12. print_px(px++);
13. print_px(px++);
14.}
void print_px( unsigned char* px )
{
int a = (int)(*px);
cout<< a <}
void main()
{
int x = 0x04030201;
unsigned char* px = (unsigned char*)&x;
print_px(px++);
print_px(px++);
print_px(px++);
print_px(px++);
}
答案:在小端机器(eg:pc机x86)上输出 1 2 3 4
在大端机器(eg:keil c) 上输出 4 3 2 1
这里给出一个将一个buff数据转换大小端转换的例子。注意,是4个字节作为一块转换的,分别把每4个字节全部逆序。
view plaincopy to clipboardprint?
01.inline void McuManager::_ReverseDword(u8 *pucHex, u16 usLen)
02.{
03. //字节序转换
04. u8 ucTmp;
05. for (int i=0; i06. {
07. //byte3 & 0
08. ucTmp = pucHex[i + 0];
09. pucHex[i + 0] = pucHex[i + 3];
10. pucHex[i + 3] = ucTmp;
11.
12. //byte2 & 1
13. ucTmp = pucHex[i + 1];
14. pucHex[i + 1] = pucHex[i + 2];
15. pucHex[i + 2] = ucTmp;
16. }
17.}