1,栈内存与堆内存
所有的局部变量在栈区,栈区是动态存储区,自动分配内存、自动回收。
而堆区,是人工分配和释放的,所以new出来的堆上。
对于问题:
对于函数中以下代码:
char* p=new char[100];
则:
- p在栈上,new出来的在堆上
2,!
与++
对于题目:
void main()
{
int a, x;
for(a = 0, x = 0; a<=1 && !x++; a++)
{
a++;
}
cout<< a << x << endl;
}
最后的输出结果应该是多少?
这个问题的关键在于第二个条件的判断。
- !与后置++同时出现时,后置++优先级高于!,所以!x++相当于!(x++),但是后置自增运算符是等语句执行完成之后再自增,也就是先把x的值取出来,做完“!”运算之后再自增。
- 因此,a=0,x=0时满足判断条件,执行循环体。此时,a = 2,x = 1,在进行条件判断你是,首先a <= 1的条件就是不成立。而&&运算符,左侧不成立就直接判断为false,不会继续进行。因此,x的值也不会再做自加操作。
因此,这道题的输出为21
3,字符串长度与大小问题
对于问题:
以下程序的输出结果是什么?
void main()
{
char st[20]="hello\0\t\\\";
printf (%d %d \n",strlen (st),sizeof (st));
}
strlen
是计算字符串的长度,从第一个字符开始一直计数到第一个’\0’为止(不包含‘\0’)。
因此,对于这个问题,第6个元素就是’\0’,所以字符串长度为5。
sizeof
则是计算字符串所占用的空间。数组st的大
小与赋值的字符串无关,是其定义时的大小20。
其中,sizeof
来返回类型以及静态分配的对象、结构或数组所占的空间,返回值跟对象、结构、数组所存储的内容没有关系;
具体而言,当参数分别如下时,sizeof返回的值表示的含义如下:
- 数组——编译时分配的数组空间大小;
- 指针——存储该指针所用的空间大小(存储该指针的地址的长度,是长整型,应该为4);
- 类型——该类型所占的空间大小;
- 对象——对象的实际占用空间大小;
- 函数——函数的返回类型所占的空间大小。函数的返回类型不能是void
4,宏定义相关
对于问题:
#define A(x) x+x
int i=5*A(4)*A(6);
cout<<i;
上述程序的输出应该为?
对于宏定义,在使用时是直接替换的,而且不需要自己加括号。
对于这个题,我们直接把A(x)替换为x+x,则:
5*4 + 4*6 + 6 = 50
5,calloc相关
对于问题:
假定有语句为“int *p=calloc(10+20,sizeof(int));”
,则p所指向的动态数组中所包含的元素个数为为多少?
对于calloc:
void *calloc(size_t n, size_t size)
在内存的动态存储区中分配n个长度为size的连续空间,函数返回一个指向分配起始地址的指针;如果分配不成功,返回NULL。
calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不初始化,里边数据是随机的垃圾数据。
对于这道题,p所指向的动态数组中所包含的元素个数为30,开辟30x4个字节的临时分配域,把起始地址赋给指针变量p。
6,指针函数问题
int *p[4]
:指针数组,是个有4个元素的数组,每个元素是指向整形的指针。即,数组的元素都是指针。int (*p)[4]
:数组指针,是一个指针,指向有四个整型元素的数组。即,一个指针指向4个整型元素的数组。int *func(void)
:指针函数,无参函数,返回整型指针。即,函数的返回值为int*。int (*func)(void)
:函数指针,可以指向无参,且返回值为整型指针的函数。即,函数的返回值为int。
对于问题:
下列定义语句中,错误的是:
A. int px*;
B. char *acp[10];
C. char(*pac)[10];
D. int(*p)();
答案为A。
其中,D是一个函数指针。
7,数组的动态实现等相关
1,数组的大小并不是必须在编译时确定,数组也可以动态实现,比如:
int n;
cin>>n;
int *p = new int[n];
2,数组的名字就是指向该数组第一个元素的指针。
3,在C++中,“数组可以通过值参数和引用参数两种方法传递给”函数的说法是错误的。
- int、char或者自定义的类可以通过值参数和引用参数两种方式传递给函数,但是数组不行。
- 数组是两种指针传递:
void sort(int *a; //对于指针a来说是值传递,对于数组来说是指针传递
void sort(int a[100]; //这种方法类似于引用,但是实质上还是指针传递
8,大小端问题
对于问题:
在80X86架构下,下面的代码输出为:
union Test
{
char a[4];
short b;
};
Test test;
test.a[0]=256;
test.a[1]=255;
test.a[2]=254;
test.a[3]=253;
printf("%d\n",test.b);
首先,对于这道题,我们应该知道:
- 80X86下是小端模式
char类型的取值范围为-128 ~ 127
unsigned char的取值范围为0 ~ 255
在这个问题上,a[0]发生了正溢出,将其转换到取值范围内就是0,即a[0] = 0,同理,a[1] = -1,a[2] = -2,a[3] = -3。
因为用补码表示符号数,则:
- a[0]=0, 0000 0000
- a[1]=-1, 1111 1111
- a[2]=-2, 1111 1110
- a[3]=-3, 1111 1101
而此时我们可以看到,Test是一个联合体,因此,a和b共用一个内存空间。
因为short占有2个字节,设置左边为高地址、右边为低地址,可以有:
a[1] | a[0] |
---|---|
1111 1111 | 0000 0000 |
short所占用的就是这两个字节,最高位1是一个负数,在计算机中用补码表示,按照取反加一的方法,可以得二进制的表示结果为:
1000 0001 0000 0000
转化为十进制,就是-256。
9,重载(overload)和重写(override)
成员函数被重载的特征:
(1)相同的范围(在同一个类中);
(2)函数名字相同;
(3)参数不同;
(4)virtual关键字可有可无。
覆盖是指派生类函数覆盖基类函数,特征是:
(1)不同的范围(分别位于派生类与基类);
(2)函数名字相同;
(3)参数相同;
(4)基类函数必须有virtual关键字。
10,数组长度的定义
C 和 C++ 是两种不同的语言。
C 自 C99 开始,在特定条件下允许使用变量作为数组长度定义数组。
C++ 至今不允许这种用法,只能使用整型常量。