}
简单描述Windows内存管理的方法。
内存管理是操作系统中的重要部分,两三句话恐怕谁也说不清楚吧~~
我先说个大概,希望能够抛砖引玉吧
当程序运行时需要从内存中读出这段程序的代码。
代码的位置必须在物理内存中才能被运行,由于现在的操作系统中有非常多的程序运行着,内存中不能够完全放下,所以引出了虚拟内存的概念。
把哪些不常用的程序片断就放入虚拟内存,当需要用到它的时候在load入主存(物理内存)中。
这个就是内存管理所要做的事。
内存管理还有另外一件事需要做:
计算程序片段在主存中的物理位置,以便CPU调度。
内存管理有块式管理,页式管理,段式和段页式管理。
现在常用段页式管理
块式管理:
把主存分为一大块、一大块的,当所需的程序片断不在主存时就分配一块主存空间,把程序片断load入主存,就算所需的程序片度只有几个字节也只能把这一块分配给它。
这样会造成很大的浪费,平均浪费了50%的内存空间,但时易于管理。
页式管理:
把主存分为一页一页的,每一页的空间要比一块一块的空间小很多,显然这种方法的空间利用率要比块式管理高很多。
段式管理:
把主存分为一段一段的,每一段的空间又要比一页一页的空间小很多,这种方法在空间利用率上又比页式管理高很多,但是也有另外一个缺点。
一个程序片断可能会被分为几十段,这样很多时间就会被浪费在计算每一段的物理地址上(计算机最耗时间的大家都知道是I/O吧)。
段页式管理:
结合了段式管理和页式管理的优点。
把主存分为若干页,每一页又分为若干段。
好处就很明显,不用我多说了吧。
各种内存管理都有它自己的方法来计算出程序片断在主存中的物理地址,其实都很相似。
这只是一个大概而已,不足以说明内存管理的皮毛。
无论哪一本操作系统书上都有详细的讲解
------------------------
4.
#include""
#defineSQR(X)X*X
intmain(intargc,char*argv[])
{
inta=10;
intk=2;
intm=1;
a/=SQR(k+m)/SQR(k+m);
printf("%d\n",a);
return0;
}
这道题目的结果是什么啊
define只是定义而已,在编择时只是简单代换X*X而已,并不经过算术法则的
a/=(k+m)*(k+m)/(k+m)*(k+m);
=>a/=(k+m)*1*(k+m);
=>a=a/9;
=>a=1;
5.
const符号常量;
(1)constchar*p
(2)charconst*p
(3)char*constp
说明上面三种描述的区别;
如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;
如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。
(1)constchar*p
一个指向char类型的const对象指针,p不是常量,我们可以修改p的值,使其指向不同的char,但是不能改变它指向非char对象,如:
constchar*p;
charc1=’a';
charc2=’b';
p=&c1;面是C语言中两种if语句判断方式。
请问哪种写法更好为什么
intn;
if(n==10)面的代码有什么问题
voidDoSomeThing(…)
{
char*p;
…
p=malloc(1024);面的代码有什么问题并请给出正确的写法。
voidDoSomeThing(char*p)
{
charstr[16];
intn;
assert(NULL!
=p);
sscanf(p,“%s%d”,str,n);
if(0==strcmp(str,“something”))
{
…
}
}
A:
sscanf(p,“%s%d”,str,n);这句该写成:
sscanf(p,“%s%d”,str,&n);
由于str有限,如果输入的字符串过大,会引发堆栈溢出!
!
!
9.下面代码有什么错误
Voidtest1()
{
charstring[10];
char*str1=”09″;
strcpy(string,str1);
}
数组越界
10.下面代码有什么问题
Voidtest2()
{
charstring[10],str1[10];
for(i=0;i<10;i++)
{
str1[i]='a';
}
strcpy(string,str1);
}
数组越界(以’/0’为拷贝界限)
------------------------
11.下面代码有什么问题
Voidtest3(char*str1)
{
charstring[10];
if(strlen(str1)<=10)
{
strcpy(string,str1);
}
}
==数组越界
==strcpy拷贝的结束标志是查找字符串中的\0因此如果字符串中没有遇到\0的话会一直复制,直到遇到\0,上面的123都因此产生越界的情况
建议使用strncpy和memcpy
------------------------
12.下面代码有什么问题
#defineMAX_SRM256
DSNget_SRM_no()
{
staticintSRM_no;出运行结果:
{出运行结果:
{C++写个程序,如何判断一个操作系统是16位还是32位的不能用sizeof()函数
A1:
16位的系统下,
inti=65536;
cout<
#include
voidmain()
{
inti=60;
intj=50;
i=i+j;
j=i-j;
i=i-j;
printf(“i=%d\n”,i);
printf(“j=%d\n”,j);
}
方法二:
i^=j;
j^=i;
i^=j;
方法三:
关位域的面试题(为什么输出的是一个奇怪的字符)
=‘b’;效果相当于=‘b’&0xf;
‘b’–>01100010
‘b’&0xf–>>00000010
所以输出Ascii码为2的特殊字符
chart:
4;就是4bit的字符变量,同样
unsignedshorti:
8;就是8bit的无符号短整形变量
尚未验证
i=10,j=10,k=3;k*=i+j;k最后的值是
60
20.进程间通信的方式有
进程间通信的方式有共享内存,管道,Socket,消息队列,DDE等
21.
structA
{
chart:
4;
chark:
4;
unsignedshorti:
8;
unsignedlongm;
}
sizeof(A)=(不考虑边界对齐)
7
structCELL位结构中的成员可以定义为unsigned,也可定义为signed,但当成员长
度为1时,会被认为是unsigned类型。
因为单个位不可能具有符号。
2.位结构中的成员不能使用数组和指针,但位结构变量可以是数组和指针,
如果是指针,其成员访问方式同结构指针。
3.位结构总长度(位数),是各个位成员定义的位数之和,可以超过两个字
节。
4.位结构成员可以与其它结构成员一起使用。
例如:
structinfo{
charname[8];
intage;
structaddraddress;
floatpay;
unsignedstate:
1;
unsignedpay:
1;
}workers;
上例的结构定义了关于一个工人的信息。
其中有两个位结构成员,每个位结
构成员只有一位,因此只占一个字节但保存了两个信息,该字节中第一位表示工
人的状态,第二位表示工资是否已发放。
由此可见使用位结构可以节省存贮空间。
和上面的那个差不多
22.下面的函数实现在一个固定的数上加上一个数,有什么错误,改正
intadd_n(intn)
{
staticinti=100;
i+=n;
returni;
}
答:
因为static使得i的值会保留上次的值。
去掉static就可了
23.下面的代码有什么问题
classA
{
public:
A(){p=this;}
~A(){if(p!
=NULL){deletep;p=NULL;}}
A*p;
};
答:
会引起无限递归
由于A对象析构会调用~A(),但是在deletep时又会调用~A();由于p!
=NULL,会引起无限递归。
24.
uniona{
inta_int1;
doublea_double;
inta_int2;
};
typedefstruct
{
aa1;
chary;
}b;
classc
{
doublec_double;
bb1;
aa2;
};
输出cout<答:
VC6环境下得出的结果是32
另:
在+win2k下做过试验:
short-2
int-4
float-4
double-8
指针-4
sizeof(union),以结构里面size最大的为union的size
关于union和struct在内存中的布局及长度增加的方式,MSDN里有详细的说明。
解析C语言中的sizeof
一、sizeof的概念
sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。
它并不是函数。
sizeof操作符以字节形式给出了其操作数的存储大小。
操作数可以是一个表达式或括在括号内的类型名。
操作数的存储大小由操作数的类型决定。
二、sizeof的使用方法
1、用于数据类型
sizeof使用形式:
sizeof(type)
数据类型必须用括号括住。
如sizeof(int)。
2、用于变量
sizeof使用形式:
sizeof(var_name)或sizeof var_name
变量名可以不用括号括住。
如sizeof (var_name),sizeof var_name等都是正确形式。
带括号的用法更普遍,大多数程序员采用这种形式。
注意:
sizeof操作符不能用于函数类型,不完全类型或位字段。
不完全类型指具有未知存储大小的数据类型,如未知存储大小的数组类型、未知内容的结构或联合类型、void类型等。
如sizeof(max)若此时变量max定义为int max();sizeof(char_v) 若此时char_v定义为char char_v [MAX]且MAX未知,sizeof(void)都不是正确形式。
三、sizeof的结果
sizeof操作符的结果类型是size_t,它在头文件
中typedef为unsigned int类型。
该类型保证能容纳实现所建立的最大对象的字节大小。
1、若操作数具有类型char、unsigned char或signed char,其结果等于1。
ANSI C正式规定字符类型为1字节。
2、int、unsigned int 、short int、unsigned short 、long int 、unsigned long 、float、double、long double类型的sizeof 在ANSI C中没有具体规定,大小依赖于实现,一般可能分别为2、2、2、2、4、4、4、8、10。
3、当操作数是指针时,sizeof依赖于编译器。
例如Microsoft C/C++中,near类指针字节数为2,far、huge类指针字节数为4。
一般Unix的指针字节数为4。
4、当操作数具有数组类型时,其结果是数组的总字节数。
5、联合类型操作数的sizeof是其最大字节成员的字节数。
结构类型操作数的sizeof是这种类型对象的总字节数,包括任何垫补在内。
让我们看如下结构:
struct {char b; double x;} a;
在某些机器上sizeof(a)=12,而一般sizeof(char)+ sizeof(double)=9。
这是因为编译器在考虑对齐问题时,在结构中插入空位以控制各成员对象的地址对齐。
如double类型的结构成员x要放在被4整除的地址。
6、如果操作数是函数中的数组形参或函数类型的形参,sizeof给出其指针的大小。
四、sizeof与其他操作符的关系
sizeof的优先级为2级,比/、%等3级运算符优先级高。
它可以与其他操作符一起组成表达式。
如i*sizeof(int);其中i为int类型变量。
五、sizeof的主要用途
1、sizeof操作符的一个主要用途是与存储分配和I/O系统那样的例程进行通信。
例如:
void *malloc(size_t size),
size_t fread(void * ptr,size_t size,size_t nmemb,FILE * stream)。
2、sizeof的另一个的主要用途是计算数组中元素的个数。
例如:
void * memset(void * s,int c,sizeof(s))。
六、建议
由于操作数的字节数在实现时可能出现变化,建议在涉及到操作数字节大小时用sizeof来代替常量计算。
=============================================================
本文主要包括二个部分,第一部分重点介绍在VC中,怎么样采用sizeof来求结构的大小,以及容易出现的问题,并给出解决问题的方法,第二部分总结出VC中sizeof的主要用法。
1、sizeof应用在结构上的情况
请看下面的结构:
structMyStruct
{
doubledda1;
chardda;
inttype
};
对结构MyStruct采用sizeof会出现什么结果呢sizeof(MyStruct)为多少呢也许你会这样求:
sizeof(MyStruct)=sizeof(double)+sizeof(char)+sizeof(int)=13
但是当在VC中测试上面结构的大小时,你会发现sizeof(MyStruct)为16。
你知道为什么在VC中会得出这样一个结果吗
其实,这是VC对变量存储的一个特殊处理。
为了提高CPU的存储速度,VC对一些变量的起始地址做了"对齐"处理。
在默认情况下,VC规定各成员变量存放的起始地址相对于结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。
下面列出常用类型的对齐方式,32位系统)。
类型
对齐方式(变量存放的起始地址相对于结构的起始地址的偏移量)
Char
偏移量必须为sizeof(char)即1的倍数
int
偏移量必须为sizeof(int)即4的倍数
float
偏移量必须为sizeof(float)即4的倍数
double
偏移量必须为sizeof(double)即8的倍数
Short
偏移量必须为sizeof(short)即2的倍数
各成员变量在存放的时候根据在结构中出现的顺序依次申请空间,同时按照上面的对齐方式调整位置,空缺的字节VC会自动填充。
同时VC为了确保结构的大小为结构的字节边界数(即该结构中占用最大空间的类型所占用的字节数)的倍数,所以在为最后一个成员变量申请空间后,还会根据需要自动填充空缺的字节。
下面用前面的例子来说明VC到底怎么样来存放结构的。
structMyStruct
{
doubledda1;
chardda;
inttype
};
为上面的结构分配空间的时候,VC根据成员变量出现的顺序和对齐方式,先为第一个成员dda1分配空间,其起始地址跟结构的起始地址相同(刚好偏移量0刚好为sizeof(double)的倍数),该成员变量占用sizeof(double)=8个字节;接下来为第二个成员dda分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为8,是sizeof(char)的倍数,所以把dda存放在偏移量为8的地方满足对齐方式,该成员变量占用sizeof(char)=1个字节;接下来为第三个成员type分配空间,这时下一个可以分配的地址对于结构的起始地址的偏移量为9,不是sizeof(int)=4的倍数,为了满足对齐方式对偏移量的约束问题,VC自动填充3个字节(这三个字节没有放什么东西),这时下一个可以分配的地址对于结构的起始地址的偏移量为12,刚好是sizeof(int)=4的倍数,所以把type存放在偏移量为12的地方,该成员变量占用sizeof(int)=4个字节;这时整个结构的成员变量已经都分配了空间,总的占用的空间大小为:
8+1+3+4=16,刚好为结构的字节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以没有空缺的字节需要填充。
所以整个结构的大小为:
sizeof(MyStruct)=8+1+3+4=16,其中有3个字节是VC自动填充的,没有放任何有意义的东西。
下面再举个例子,交换一下上面的MyStruct的成员变量的位置,使它变成下面的情况:
structMyStruct
{
chardda;
doubledda1;
inttype
};
这个结构占用的空间为多大呢在环境下,可以得到sizeof(MyStruc)为24。
结合上面提到的分配空间的一些原则,分析下VC怎么样为上面的结构分配空间的。
(简单说明)
structMyStruct
{
chardda;inta[50];Test*s;
以上为sizeof的基本用法,在实际的使用中要注意分析VC的分配变量的分配策略,这样的话可以避免一些错误。
最后等于多少
inti=1;
intj=i++;
if((i>j++)&&(i++==j))i+=j;
答:
i=5
未验证,本人认为这种题目没有任何实际意义!
26.
unsignedshortarray[]={1,2,3,4,5,6,7};
inti=3;
*(array+i)=
答:
4
27.
classA
{
virtualvoidfunc1();
voidfunc2();
}
ClassB:
classA
{
voidfunc1(){cout<<"fun1inclassB"<virtualvoidfunc2(){cout<<"fun2inclassB"<}
A,A中的func1和B中的func2都是虚函数.
B,A中的func1和B中的func2都不是虚函数.
C,A中的func2是虚函数.,B中的func1不是虚函数.
D,A中的func2不是虚函数,B中的func1是虚函数.
答:
A
28.
数据库:
抽出部门,平均工资,要求按部门的字符串顺序排序,不能含有"humanresource"部门,
employee结构如下:
employee_id,employee_name,depart_id,depart_name,wage
答:
selectdepart_name,avg(wage)
fromemployee
wheredepart_name<>‘humanresource’
groupbydepart_name
orderbydepart_name
29.
给定如下SQL数据库:
Test(numINT(4))请用一条SQL语句返回num的最小值,但不许使用统计功能,如MIN,MAX等
答:
selecttop1num
fromTest
orderbynumdesc
30.
输出下面程序结果。
#include
classA
{
public:
virtualvoidprint(void)
{
cout<<"A:
:
print()"<}
};
classB:
publicA
{
public:
virtualvoidprint(void)
{
cout<<"B:
:
print()"<};
};
classC:
publicB
{
public:
virtualvoidprint(void)
{
cout<<"C:
:
print()"<}
};
voidprint(Aa)
{
();
}
voidmain(void)
{
Aa,*pa,*pb,*pc;
Bb;
Cc;
pa=&a;
pb=&b;
pc=&c;
();
();
();
pa->print();
pb->print();
pc->print();
print(a);
print(b);
print(c);
}
A:
:
print()
B:
:
print()
C:
:
print()
A:
:
print()
B:
:
print()
C:
:
print()
A:
:
print()
A:
:
print()
A:
:
print()
C++是根据内存中的具体类对象模型来判断使用哪个虚函数的,记住这个就行了!
31.
试编写函数判断计算机的字节存储顺序是升序(littleendian)还是降序(bigendian)
答:
boolIsBigendian()
{
unsignedshort