1.C++ 中,下面描述正确的是( C)
int *p1 = new int[10];
int *p2 = new int[10]();
(A) p1和p2申请的空间里面的值都是随机值
(B) p1和p2申请的空间里的值都已经初始化
(C) p1申请的空间里的值是随机值,p2申请的空间里的值已经初始化
(D) p1申请的空间里的值已经初始化,p2申请的空间里的值是随机值
解:
默认初始化(变量被赋予的值取决于变量的数据类型和变量的定义位置)的规则:
(1)内置类型(int等)的默认初始化值取决于定义它的位置:
* 定义在任何函数之外的未初始化的内置类型变量(即全局变量)默认初始化为0;
* 定义在函数体内部的内置类型变量的默认初始化值是随机数,如果试图开呗或以其他方式访问该变量的值,会产生编译错误。
(2)未初始化的内置类型的全局变量的默认初始化值还取决于变量的数据类型:
* 数值数据类型的未初始化全局变量的默认初始化值为0;
* bool类型的未初始化全局变量的默认初始化值为false;
* char类型的未初始化的全局变量的默认初始化值为‘\0’(ASCII=0)
* string 类型的未初始化的全局变量的默认初始化值为“”
(3)静态变量无论是全局变量还是局部变量都会默认初始化,它的值取决于变量的数据类型;
(4)全局指针类型的未初始化的默认初始化值为NULL,而局部指针类型的默认初始化值是未定义的。
1.当new单个对象时,默认情况下,用new动态分配的对象是默认初始化的,也就是随机值,而类类型的对象会用默认构造函数进行初始化(默认构造函数如果没有自己写的话系统会自动生成的);
2.第一行代码可以看成是系统调用的自动生成的默认构造函数,也就是默认初始化,赋予的是随机值;第二行则是调用了自己写的构造函数,也就是给它初始化了,即初始化为0。
补充:对于内置类型而言,new仅仅是分配内存,除非后面显示加(),相当于调用它的构造函数,对于自
定义类型而言,只要一调用new, 那么编译器不仅仅给它分配内存,还调用它的默认构造函数初
始化,即使后面没有加()。
2.有关枚举:
第一个枚举成员的默认值为整型的 0,后续枚举成员的值在前一个成员上加 1。
(1)枚举变量的定义:
(2)用枚举类型定义的变量day,无论这个变量day内部的第一个枚举变量的值是多少,day的值都为0,如图:
函数内部定义下面枚举值,访问a,x2,x4值为( 0,98,101)
enum data{
x1='a',
x2,
x3 = 100,
x4,
x5,
} a;
如果使用 a=x4,则a的值就变成了x4的值。这也是枚举类型的用法之含义。
3.在函数中传入的形参函数名或指针的大小都是随系统大小。(因为在这里其实传入的是地址,这个形参看做指针)
如:void example(char ac[]){} 中,sizeof(ac)=4;
4.32位编译器,下面地址输出为(B )
float *X1;//sizeof(float)=4;
int *X2;//sizeof(int)=4;
long long *X3;//sizeof(long long)=8;
X1 = (float *)0x801000;
X2 = (int*)0x810000;
X3 = (long long*)0x820000;
X1+=5;X2+=6;X3+=7;//加上的数是根据他们各自的类型而来
(A)X1=0X801014 ;X2=0X810018;X3=0X82001C;
(B)X1=0X801014 ;X2=0X810018;X3=0X820038;
(C)X1=0X801020 ;X2=0X810024;X3=0X820056;
(D)X1=0X801020 ;X2=0X810024;X3=0X820038;
解:地址的表示用的十六进制,0X801014的尾部两位:14也就是16*1+4=20
5.以下有关C语言的说法中,错误的是(C)。
A.可以通过malloc(size_t)函数调用申请超过该机器物理内存大小的内存块。
B.无法通过内存释放函数free(void*)直接将某块已经使用完的物理内存直接还给操作系统。
C.可以通过内存分配函数malloc(size_t)直接申请物理内存。
D.内存泄露一般是指程序申请了一块内存,使用完后,没有及时将这块内存释放,从而导致程序占 用大量内存。
解:malloc和free申请和释放的虚拟内存。其他的选项都对,它申请的是虚拟内存,这块虚拟内存的大小可以很大,它所占据的的物理内存其实很小,A对;free释放的内存不一定直接还给操作系统,可能要到进程结束才释放,B对;D对。
6.以下为Linux下的32 位程序,下面输出结果:8
typedef struct name1{
char t;
char k;
unsigned short 7;//2bit
int m;
}Name1;
printf("Name1=%d\n",sizeof(Name1));
解:unsigned short 7;用到了位域,short是2bit,故1+1+1+2+4=8。
7.关于内存的思考题,你能看出有什么问题?
void GetMemory(char *p)
{
p = (char *)malloc(100);
}
void Test(void)
{
char *str = NULL;
GetMemory(str);//调用函数,但是是把str保存的NULL传给了函数GetMemory,在GetMemory代码块内有了一个局部指针被赋值为空,又给它开辟了100个空间,但是出了这个代码块就没人找得到这块内存了,因为这是局部指针,随代码块消亡了。没有真正给str开辟空间。
strcpy(str, "hello world");//给空指针指向的空写字符串,属于非法操作内存
printf(str);
}
解:GetMemory()函数中给malloc的空间一直存在,是随进程持续性的。
8.关于内存的思考题,你能看出有什么问题?
char *GetMemory(void)
{
char p[] = "hello world";//指针p是局部定义的,出了这个代码块就失效了
return p;//返回的是局部变量的地址
}
void Test(void)
{
char *str = NULL;
str = GetMemory();
printf(str);
}
以上两题的正确改写:
void GetMemory(char **p)
{
*p = (char *)malloc(100);
}
int main()
{
char *str = NULL;
GetMemory(&str);
strcpy(str, "hello world");
printf("%s",str);
return 0;
}
或者
char *GetMemory(void)
{
char *p = (char *)malloc(100);
return p;//这个是可以的,只是返回了这个地址,没有对局部变量p操作什么!(malloc的空间随进程持续性)
}
int main()
{
char *str = NULL;
str=GetMemory();
strcpy(str, "hello world");
printf("%s",str);
return 0;
}
注意一点:
在GetMemory();函数中如果是定义的局部指针,给指针malloc空间并返回指针就可以实现要求,虽然指针是局部的,会消亡,但是只是对它的地址返回是没有问题的,因为没有真的操作它。而在GetMemory();中以局部指针指向一串字符串却没有意义,因为无论是局部指针还是字符串都是随代码块持续性的,返回指向字符串的局部指针会出错。