您的位置:首页 > 编程语言 > C语言/C++

C++小题(四)

2015-12-27 15:13 435 查看
/*
int fseek(FILE *stream, long offset, int fromwhere);函数设置文件指针stream的位置。
如果执行成功,stream将指向以fromwhere为基准,偏移offset(指针偏移量)个字节的位置,函数返回0。
如果执行失败(比如offset超过文件自身大小),则不改变stream指向的位置,函数返回一个非0值。
实验得出,超出文件末尾位置,还是返回0。往回偏移超出首位置,返回-1,且指向一个-1的位置,请小心使用

void rewind(FILE *stream);
rewind函数作用等同于 (void)fseek(stream, 0L, SEEK_SET);

int fscanf(FILE*stream, constchar*format, [argument...]); 其功能为根据数据格式(format)从输入流(stream)中写入数据(argument);
与fgets的差别在于:fscanf遇到空格和换行时结束,注意空格时也结束,fgets遇到空格不结束。

int fprintf( FILE *stream, const char *format, [ argument ]...),
fprintf()函数根据指定的格式(format)向输出流(stream)写入数据(argument)。
*/
/////////////////////////////////////////////////////////////////////////////
/*
#include <stdio.h>
main( )
{
FILE * fp;
int i,a[6]={1,2,3,4,5,6},k;
fp = fopen("data.dat","w+");
for (i=0;i<6;i++)
{
fseek(fp,0L,0);
fprintf(fp,"%d\n",a[i]);
rewind (fp);
fscanf(fp,"%d",&k);
}
fclose(fp);
printf("%d\n",k);
}
则程序的输出结果是? 6
*/
////////////////////////////////////////////////////////////////////////////
/*
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(void) {
int i;
for (i=0; i<2; i++) {
fork();
printf("-\n");
}
return 0;
}
6个-
1.printf("-\n");对于行输出/n有清除缓存的作用;
2.fork()可以复制父进程的缓存,变量值等信息;
3.i=0时,父进程A产生一个子进程A1,此时输出两行“-”;
4.i=1时,fork使父进程A产生子进程A2,A1产生子进程A3,此时A-A3共产生4行“-”(因为现在A,A1的输出行缓冲均为空);
总数为6:2(A)+2(A1)+1(A2)+1(A3)=6;
注意printf("-\n");与printf("-");的不同,前者直接输出,后者存在缓冲区中
printf("-")由于A2,A3会继承A和A1的输出行缓冲区,所以会分别输出两个“-”,加起来为:2(A)+2(A1)+2(A2)+2(A3)=8;
*/
/////////////////////////////////////////////////////////////////////////////
/*
class A
{
int a;
short b;
int c;
char d;
};
class B
{
double a;
short b;
int c;
char d;
};

在32位机器上用gcc编译以上代码,求sizeof(A),sizeof(B)分别是多少。
16 24
1、  结构体的大小等于结构体内最大成员大小的整数倍
2、  结构体内的成员的首地址相对于结构体首地址的偏移量是其类型大小的整数倍,比如说double型成员相对于结构体的首地址的地址偏移量应该是8的倍数。
3、  为了满足规则1和2编译器会在结构体成员之后进行字节填充!
A中,a占4个字节,b本应占2个字节,但由于c占4个字节,为了满足条件2,b多占用2个字节,为了满足条件1,d占用4个字节,一共16个字节。
B中,a占8个字节,b占2个字节,但由于c占4个字节,为了满足条件2,b多占用2个字节,
即abc共占用8+4+4=16个字节,为了满足条件1,d将占用8个字节,一共24个字节。
*/
/////////////////////////////////////////////////////////////////////////////
/*
假定有类AB,有相应的构造函数定义,能正确执行
AB a(4),b(5),c[3],*p[2]={&a,&b};语句,请问执行完此语句后共调用该类的构造函数次数为 5次
a(4),一个对象a,调用1次构造函数;
b(5),一个对象b,调用1次构造函数;
c[3],三个对象c[0],c[1],c[2],调用3次构造函数;
*p[2],指针数组,其元素分别指向a和b,所以没有调用构造函数。
总共5次。
*/
/////////////////////////////////////////////////////////////////////////////
/*
写出下面程序的输出结果
class A
{
public:
void FuncA()
{
printf( "FuncA called\n" );
}
virtual void FuncB()
{
printf( "FuncB called\n" );
}
};
class B : public A
{
public:
void FuncA()
{
A::FuncA();
printf( "FuncAB called\n" );
}
virtual void FuncB()
{
printf( "FuncBB called\n" );
}
};
void main( void )
{
B  b;
A  *pa;
pa = &b;
A *pa2 = new A;
pa->FuncA();
pa->FuncB();
pa2->FuncA();
pa2->FuncB();
delete pa2;
}
答案
FuncA called
FuncBB called
FuncA called
FuncB called
pa->FuncA(); //pa=&b动态绑定但是FuncA不是虚函数,所以FuncA called
pa->FuncB(); //FuncB是虚函数所以调用B中FuncB,FuncBB called
pa2->FuncA(); //pa2是A类指针,不涉及虚函数,调用的都是A中函数,所以FuncA called
pa2->FuncB();//FuncB called
*/
/////////////////////////////////////////////////////////////////////////////
/*
下列关于数组与指针的区别描述正确的是?
正确答案: A B C

A数组要么在静态存储区被创建(如全局数组),要么在栈上被创建。
B用运算符sizeof 可以计算出数组的容量(字节数)
C指针可以随时指向任意类型的内存块。
D用运算符sizeof 可以计算出指针所指向内容的容量(字节数)

*/
/////////////////////////////////////////////////////////////////////////////
/*
若有定义int(*pt)[3];则下列说法正确的是:
正确答案: D

A定义了基类型为int的三个指针变量
B定义了基类型为int的具有三个元素的指针数组pt
C定义了一个名为*pt、具有三个元素的整型数组
D定义了一个名为pt的指针变量,它可以指向每行有三个整数元素的二维数组
*/
/////////////////////////////////////////////////////////////////////////////
/*
全局变量可不可以定义在可被多个.C文件包含的头文件中?
正确答案: A

A可以
B不可以
全局变量如果不加static放在.h文件中,会在链接的时候出错,但是加上static,它就相当于各自c文件的本地全局变量
*/
/////////////////////////////////////////////////////////////////////////////
/*
以下代码段有问题的是()
正确答案: A B C   答案是A 申请了空间没有释放,答案B 打开流没有关闭,答案C free了二次,但是其实指针都是一块内存空间

A void func1(char *e){
char *p1;
p1=malloc(100);
sprintf(p1,error:"%s'.",e);
local_log(p1);
}
B int func2(char *filename)
{
FILE *fp;
int key;
fp=fopen(filename,"r");
fscanf(fp,"%d",&key);
return key;
}
C void func3(char *info){
char *p,*pp;
p=malloc(100);
pp=p;
free(p);
sprintf(pp,*info:"%s'.",info);
free(pp);
}

int sprintf( char *buffer, const char *format, [ argument] … );把格式化的数据写入某个字符串缓冲区。
*/
/////////////////////////////////////////////////////////////////////////////
/*
下面程序段的运行结果是:ab
char C[5]={‘a’,’b’,’\0’,’c’,’\0’};
printf(“%s”,C);
字符数组以\0结尾,所以扫描到'\0'字符时就返回结果。
引申一下,
char c[5] = { 'a', 'b', 's', 'c', 'd' };
printf("%s", c);
//这样会数组溢出(over flow),因为C风格的字符串会默认加一个'\0'
*/
/////////////////////////////////////////////////////////////////////////////
/*
内存空间被分成不同区域,其中用函数
void* malloc(unsigned int size);
申请的内存在()
正确答案: C

A 程序区
B 静态存储区
C 动态存储区
D ROM区

栈区(stack)
堆区(heap)
全局区(静态区)(static)
文字常量区程
序代码区
*/
/////////////////////////////////////////////////////////////////////////////
/*
struct s
{
int x: 3;
int y: 4;
int z: 5;
double a;
}
求sizeof(s)  16
有些信息在存储时,并不需要占用一个完整的字节,而只需占用几个或一个二进制位。
例如在存放一个开关量时,只有0和1两种状态,用一位二进制即可。为了节省存储空间,并使处理简单,
C语言提供了一种数据结构,称为“位域”或“位段”。所谓“位域”是把一个字节中的二进制位划分为几个不同的区域,
并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。
题目中的x,y,z是一个int型的3个位域,因此以一个int来计算,a是一个double型,字符对齐,因此共占16个字节。
*/
/////////////////////////////////////////////////////////////////////////////
/*
下面有关c++内存分配堆栈说法错误的是?
正确答案: B

A对于栈来讲,是由编译器自动管理,无需我们手工控制;对于堆来说,释放工作由程序员控制
B对于栈来讲,生长方向是向上的,也就是向着内存地址增加的方向;对于堆来讲,它的生长方向是向下的,是向着内存地址减小的方向增长。
C对于堆来讲,频繁的 new/delete 势必会造成内存空间的不连续,从而造成大量的碎片,使程序效率降低。对于栈来讲,则不会存在这个问题
D一般来讲在 32 位系统下,堆内存可以达到4G的空间,但是对于栈来讲,一般都是有一定的空间大小的。

堆的生长方向,是向上的,也就是内存地址增加的方向;栈的生长方向是向下的,也就是内存地址减小的方向
*/
/////////////////////////////////////////////////////////////////////////////
/*
下列代码试图打印数字1-9的全排列组合。
#include "stdio.h"
#define N 9
int x
;
int count = 0;

void dump() {
int i = 0;
for (i = 0; i < N; i++) {
printf("%d", x[i]);
}
printf("\n");
}

void swap(int a, int b) {
int t = x[a];
x[a] = x[b];
x[b] = t;
}

void run(int n) {
int i;
if (N - 1 == n) {
dump();
count ++;
return;
}
for (i = ___; i < N; i++) {
swap(___, i);
run(n + 1);
swap(___, i);
}
}

int main() {
int i;
for (i = 0; i < N; i++) {
x[i] = i + 1;
}
run(0);
printf("* Total: %d\n", count);
}
其中run函数中缺失的部分应该依次为:n n n
*/
/////////////////////////////////////////////////////////////////////////////
/*
int main(){
int pid;
int num=1;
pid=fork();
if(pid>0){
num++;
printf("in parent:num:%d addr:%x\n",num,&num);
}
else if(pid==0){
printf("in child:num:%d addr:%x\n",num,&num);
}
}
父子进程中输出的num不同,num地址相同

这里打印的变量的地址都是逻辑空间(虚拟地址)因为在fork时整个虚拟地址空间被复制,
对于父子进程,它们的逻辑空间一样,但是物理空间还是不同的。
所以在多进程编程中,不要寄希望于通过地址来判断两个变量是否相同。
*/
///////////////////////////////////////////////////////////////////////////////////
/*
对以下数据结构中data的处理方式描述正确的是()
1
2
3
4
5
struct Node
{
int size;
char data[0];
};
正确答案: C   你的答案: C (正确)

A data将会被编译成一个char *类型指针
B 全部描述都不正确
C 编译器会认为这就是一个长度为0的数组,而且会支持对于数组data的越界访问
D 编译器会默认将数组data的长度设置为1

柔性数组,它只能放在结构体末尾,是
申明一个长度为0的数组,就可以使得这个结构体是可变长的。对于编译器来说,此时长度为0的数组并不占用空间,
因为数组名本身不占空间,它只是一个偏移量, 数组名这个符号本身代 表了一个不可修改的地址常量 (注意:数组名永远都不会是指针! ),
但对于这个数组的大小,我们可以进行动态分配 请仔细理解后半部分,
对于编译器而言,数组名仅仅是一个符号,它不会占用任何空间,它在结构体中,只是代表了一个偏移量,代表一个不可修改的地址常量!
对于0长数组的这个特点,很容易构造出变成结构体,如缓冲区,数据包等等:
注意:构造缓冲区就是方便管理内存缓冲区,减少内存碎片化,它的作用不是标志结构体结束,而是扩展
柔性数组是C99的扩展,简而言之就是一个在struct结构里的标识占位符(不占结构struct的空间)
*/
///////////////////////////////////////////////////////////////////////////////////////////////
/*
int func(unsigned int i) {
unsigned int temp = i;
temp = (temp & 0x55555555) + ((temp & 0xaaaaaaaa) >> 1);
temp = (temp & 0x33333333) + ((temp & 0xcccccccc) >> 2);
temp = (temp & 0x0f0f0f0f) + ((temp & 0xf0f0f0f0) >> 4);
temp = (temp & 0x00ff00ff) + ((temp & 0xff00ff00) >> 8);
temp = (temp & 0x0000ffff) + ((temp & 0xffff0000) >> 16);
return temp;
}
请问 func(0x11530828)的返回值是:9
将255的8个位置进行编号,1号位置到8号位置,首先对12、34、56、78进行相加,得到2、2、2、2,
分别存放于12、34、56、78位置,再将12、34、56、78看成一个整体,将12和34、56和78相加,
得到4、4存放于1234、5678位置,最后再将1234和5678相加,得到8。
算法也是利用了二分的思想,给定一个二进制数,将均分成两部分,分别求左边和右边的1的个数,然后相加,最后得到结果。
为了方便理解,我们把代码改成如下的形式:
int func(unsigned int i)
{
unsigned int temp = i;
temp = (temp & 0x55555555) + ((temp>> 1) & 0x55555555);  //temp相邻位相加
temp = (temp & 0x33333333) + ((temp >> 2) & 0x33333333);  //temp相邻(以2为单位)相加
temp = (temp & 0x0f0f0f0f) + ((temp>> 4) & 0x0f0f0f0f);    //temp相邻(以4为单位)相加
temp = (temp & 0xff00ff) + ((temp>> 8) & 0xff00ff);       //temp相邻(以8为单位)相加
temp = (temp & 0xffff) + ((temp>> 16) & 0xffff) ;          //temp相邻(以16为单位)相加
return temp;
}
temp相邻位相加:相加原理若相邻的两个数为00则结果为00, 相邻的两个数为01或10则结果为01,
相邻两个数为11则结果为10,也就是先小范围统计每两位中1的个数,后面的步骤在累计有多少个1.*/
//////////////////////////////////////////////////////////////////////////////////////////////////
/*
以下代码输出什么?
int a =1,b =32 ;
printf("%d,%d",a<<b,1<<32);
正确答案: B
执行a<<b时,编译器会先将b与31进行and操作,以限制左移的次数小于等于31。b&31=0,则a<<b=1
执行1<<32时,编译器直接执行算术左移的操作。
1,1
1,0
0,0
0,1
*/
///////////////////////////////////////////////////////////////
/*
typedef char T[10] ;
T * a ;
上述定义中a的类型与下面选项中完全相同的是?
正确答案: B   你的答案: B (正确)

A char a [ 10 ] ;
B char ( *a) [ 10 ] ;
C char * a ;
D char *a [ 10 ] ;
typedef char T[10] ;

T * a ;

这里T是什么类型呢,把名字抹去不就是类型了吗?char [10],T为一个char数组。
那么T * a中啊为什么类型呢,T * ,T为数组,是一个整体,a为指向这个数组的一个指针*/
///////////////////////////////////////////////////////////////////////////
/*
引用可以是void类型吗?
正确答案: A
A不可以
B可以
void类型没有分配内存,而引用必须是另一个固定内存变量的别名,所以不能指向void
*/
/////////////////////////////////////////////////////////////////////////////
/*
请补全下面的快速排序代码,答案中请不要包含空格。
void qsort(int *array, int len)
{
int value, start, end;
if (len <= 1)
return;
value = array[0];
start = 0;
end = len - 1;
while (start < end) {
for (; start < end; --end) {
if (array[end] < value) {
1
break;
}
}
for (; start < end; ++start) {
if (array[start] > value)
{
2
break;
}
}
}
3
qsort(array, 4 );
qsort( 5 , 6 );
}
1 array[start++] = array[end];
2 array[end--] = array[start];
3 array[start] = value;
4 start
5 array+start+1
6 len-start-1
*/
////////////////////////////////////////////////////////////////////////
/*
在32位机器上
设有以下说明和定义:
typedef union {
long i;
int k[5];
char c;
} DATE;
struct data {
int cat;
DATE cow;
double dog;
} too;
DATE max;
则语句 printf("%d",sizeof(struct data)+sizeof(max));的执行结果是:32+20=52

DATE是一个union, 变量公用空间. 里面最大的变量类型是int[5], 占用20个字节. 所以它的大小是20 。
但是到了结构体里面,其实它是这样的,首先一个int,然后后面5个int,再然后是一个double,所以最大的成员长度是8不是20,
然后6个int刚刚24,然后加上8是32,加上共用体是52,
如果你把第一个Int cat去掉,你仍然会发现,结构体大小还是32,
因为8个字节内存对齐,前面2个int一组,最后还单一个int也要占8个字节
*/
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: