c++面试题

来源:互联网 发布:mac系统如何安装sass 编辑:程序博客网 时间:2024/06/08 03:03

2015.1.14

预处理  const 和 sizeof


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
某32位系统下, C++程序,计算sizeof 的值
char str[] = “http://www.ibegroup.com/”
char *p = str ;
int n = 10;
 
sizeof (str ) = ?  //--(1)
sizeof ( p ) = ?   //--(2)
sizeof ( n ) = ?   //--(3)
 
void Foo ( char str[100])
{
    sizeof( str ) = ?  //--(4)
}
 
void *p = malloc( 100 );
sizeof ( p ) = ?   //--(5)
1、sizeof(str)
   str是个数组,sizeof数组得到的值=单个数组元素的字节大小*数组元素个数=1*25=25,不要漏了字符串结尾的0

2、sizeof(p)
   p是个指针,32位系统上指针就是个32位的值,所以等于4(4字节=32位)

3、sizeof(n)
   同2,32位系统上int占4个字节,所以等于4

4、数组做函数参数时,其实是按指针来传递的,所以同2,sizeof(指针)=4

5、同2,p是个指针,sizeof(p) = 4

数据类型    LP64     ILP64     LLP64     ILP32     LP32
 char         8        8         8         8         8
 short        16       16        16        16        16
 _int32      N/A       32       N/A       N/A       N/A
 int          32       64        32        32        16
 long         64       64        32        32        32
 long long   N/A      N/A        64       N/A       N/A
 pointer      64       64        64        32        32
 
LP64,ILP64,LLP64是64位平台上的字长模型,ILP32和LP32是32位平台上的字长模型。

64位Windows采用的是LLP64数据模型。
64位UNIX/Linux/MacOS X采用的是LP64数据模型。

对于支持SIMD指令集的CPU,比如MMX、SSE2/3/4等的,或者PowerPC指令的CPU,int显然不是最快的。因为那些CPU一个时钟周期能处理64位甚至128位整数。


#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
struct{
 short a1;
 short a2;
 short a3;
}A;
struct{
 long a1;
 short a2;
}B;

int main()
{
 char* ss1="0123456789";
 char ss2[]="0123456789";
 char ss3[100]="0123456789";
 int ss4[100];
 char q1[]="abc";
 char q2[]="a/n";
 char* q3="a/n";
 char* str1=(char*)malloc(100);
 void *str2=(void*)malloc(100);

 cout<<sizeof(ss1)<<" ";
 cout<<sizeof(ss2)<<" ";
 cout<<sizeof(ss3)<<" ";
 cout<<sizeof(ss4)<<" ";
 cout<<sizeof(q1)<<" ";
 cout<<sizeof(q2)<<" ";
 cout<<sizeof(q3)<<" ";
 cout<<sizeof(A)<<" ";
 cout<<sizeof(B)<<" ";
 cout<<sizeof(str1)<<" ";
 cout<<sizeof(str2)<<" ";

 return 0;
}


//解析:
//ss1是一个字符指针,指针的大小是一个定植,就是4。
//q2里面有一个"/n","/n"算做一位,所以它的空间大小是3。
//A 和B是两个结构体。在默认情况下,为了方便对结构体内元素的访问和管理,当结构体内的元素的长度都
//小于处理器的位数的时候,便以结构体里面最长的数据元素为对齐单位,也就是说,结构体的长度一定是
//最长的数据元素的整数倍。如果结构体内存在长度大于处理器位数的元素,那么就以处理器的位数为对齐
//单位。但是结构体内类型相同的连续元素将在连续的空间内,和数组一样。
//
//结构体A中有3个short类型变量,各自以2字节对齐,结构体对齐参数按默认的8字节对齐,则a1、a2、a3都
//取2字节对齐,sizeof(A)为6,其也是2的整数倍。B中a1为4字节对齐,a2 为2字节对齐,结构体默认对齐参数
//为8,则a1取2字节对齐;结构体大小6字节,6不为4的整数倍,增加到8时,符合所有条件,则sizeof(B)为8。
=======================================================================================================

//sizeof面试题3.cpp
//求解下面程序的结果。
//[中国某著名通信企业H面试题]
#include<iostream>
using namespace std;

class A1{
public:
 int a;
 static int b;
 A1();
 ~A1();
};

class A2{
public:
 int a;
 char c;
 A2();
 ~A2();
};

class A3{
public:
 float a;
 char c;
 A3();
 ~A3();
};

class A4{
public:
 float a;
 int b;
 char c;
 A4();
 ~A4();
};

class A5{
public:
 double d;
 float a;
 int b;
 char c,e;
 A5();
 ~A5();
};


int main()
{
 cout<<sizeof(A1)<<endl;
 cout<<sizeof(A2)<<endl;
    cout<<sizeof(A3)<<endl;
 cout<<sizeof(A4)<<endl; 
 cout<<sizeof(A5)<<endl;
 return 0;
}

//解析:
//因为静态变量是存放在全局数据区的,而sizeof计算栈中分配的大小,是不会计算在内的,所以sizeof(A1)
//是4。
//为了照顾数据对齐,int大小为4,char大小为1,所以sizeof(A2)是8。
// 为了照顾数据对齐,float大小为4,char大小为1,所以sizeof(A3)是8。
// 为了照顾数据对齐,float大小为4,int大小为4,char大小为1,所以sizeof(A4)是12。
// 为了照顾数据对齐,double大小是8,float大小为4,int大小为4,char大小为1,所以sizeof(A5)是24。

==================================================================================

含位域结构体的sizeof:
前面已经说过,位域成员不能单独被取sizeof值,我们这里要讨论的是含有位域的结构体的sizeof,只是考虑到其特殊性而将其专门列了出来。
C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,允许其它类型类型的存在。
使用位域的主要目的是压缩存储,其大致规则为:
1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++和GCC采取压缩方式;
4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
还是让我们来看看例子。

示例1
struct BF1
{
    char f1 : 3;
    char f2 : 4;
    char f3 : 5;
};
其内存布局为:
 |__f1___|____f2___ |__|____f3______|______|
 |__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|__|

位域类型为char,第1个字节仅能容纳下f1f2,所以f2被压缩到第1个字节中,而f3
能从下一个字节开始。因此sizeof(BF1)的结果为2
示例2
struct BF2
{
    char f1 : 3;
    short f2 : 4;
    char f3 : 5;
};
由于相邻位域类型不同,在VC6中其sizeof6,在Dev-C++中为2
示例3
struct BF3
{
    char f1 : 3;
    char f2;
    char f3 : 5;
};
非位域字段穿插在其中,不会产生压缩,在VC6Dev-C++中得到的大小均为3



在结构体和类中,可以使用位域来规定某个成员所能占用的空间,所以使用位域能在一定程度上节省结构体占用的空间。不过考虑下面的代码: 

struct s1 

 int i: 8; 
 int j: 4; 
 double b; 
 int a:3; 
}; 

struct s2 

 int i; 
 int j; 
 double b; 
 int a; 
}; 

struct s3 

 int i; 
 int j; 
 int a; 
 double b; 
}; 

struct s4 

 int i: 8; 
 int j: 4; 
 int a:3; 
 double b; 
}; 

cout<<sizeof(s1)<<endl; // 24 
cout<<sizeof(s2)<<endl; // 24 
cout<<sizeof(s3)<<endl; // 24 
cout<<sizeof(s4)<<endl; // 16 
  可以看到,有double存在会干涉到位域(sizeof的算法参考上一节),所以使用位域的的时候,最好把float类型和double类型放在程序的开始或者最后。
 
===================================================================================================================

const的用法:


求统计数组里重复元素个数,以及位置:


#include <iostream> 
#include <map>
#include <vector>
using namespace std;
void main(void) 

int data[]={20,20,12,8,8,6,6,10,20,15};
map<int, vector<int>> m_data;
map<int, vector<int>>::iterator r;



for(int i=0; i<sizeof(data)/sizeof(*data); ++i)
{
vector<int> pos;
r = m_data.find(data[i]);
if(r != m_data.end())
{ r->second.push_back(i);
m_data[data[i]] = r->second;
}
else
{
pos.push_back(i);
m_data[data[i]] = pos;
}
}


for(map<int, vector<int>>::iterator e=m_data.begin(); e!=m_data.end(); ++e)
{
cout << "数字:" << e->first << " 在数组中的个数:" << e->second.size() << " 在数组中的位置:";
   for(vector<int>::iterator r= (e->second).begin(); r!=(e->second).end(); ++r)
cout << *r << " ";
cout << endl;
}





0 0
原创粉丝点击