1,指针实现变量交换问题
对于问题:
void swap_int(int *a,int *b){
*a=*a+*b;
*b=*a-*b;
*a=*a-*b;
}
对于上面的代码,如果是两个负数,比如-5和-7
,以4bit为例:
以补码形式可得,-5 = 1011,-7 = 1001
(-5)+ (-7)= 10100=0100=4 (溢出后为4)
4-(-7)= 4 +7=0100 + 0111 = 1011 = -5的补码
4-(-5)= 4 + 5 = 0100 + 0101 = 1001 = -7的补码
即,可能发生溢出,但是最后结果是做正确的,即可以实现交换。
但是,需要保证输入的两个参数不能指向同一个地址,否则,无论两个数字是多少,交换之后,结果都为0。
即:*a=*a+*b;对一块内存赋值,*b=*a-*b;将改块内存中的值赋值为0;
2,函数的参数传递问题
对于问题:
int f(int a, int b, int c)
{
return 0;
}
int main(){
return f(printf("a"),printf("b"),printf("c"));
}
乍一看,这个编译不通过。
但是,printf是有返回值的,返回值是输出的字符的个数,是int型。
在x86架构(Linux或Unix系统)上,函数的参数是通过栈传递的。因此参数从右往左入栈顺序是:printf(“c”),printf(“b”),printf(“a”)。依次计算出结果:cba
3,模板类的声明
函数模板的格式如下:
template<类型 形参名1,类型 形参名2...>
类型有class和typename。
因此,正确的例子有:
template<class T1,class T2>
template<typename T1,typename T2>
template<class T1,typename T2>
4,隐含的this指针
对于问题:
下面程序段包含4个函数,其中具有隐含this指针的是哪一个?
int f1();
class T
{
public:static int f2();
private:friend int f3();
protect:int f4();
};
this指针只能在类的成员函数中使用,它指向该成员函数被调用的对象。
因此:
- 非类内的函数,没有this指针。
- 静态成员函数属于整个类所拥有,没有this指针。
- 友元函数是非成员函数,没有this指针。
因此,只有f4()有this指针。
5,32位和64位下各变量所占字节数
32,64位编译环境下的sizeof问题经常出现。
不过,两者环境下的数据类型所占字节数都是一样的:
数据类型 | 所占字节数 |
---|---|
char | 1 |
short | 2 |
int | 4 |
long long | 8 |
float | 4 |
double | 8 |
long double | 8 |
不同的是:
1,long的字节数不同
- 32位:long占用4个字节
- 64位:long占用8个字节
2,指针类型大小不同:
- 32位:指针类型占4个字节
- 64位:指针类型占8个字节
6,常量、指针常量、常量指针
对于问题:
给出以下定义,下列哪些操作是合法的?
const char *p1 = “hello”;
char *const p2 = “world”;
A. p1++;
B. p1[2] = ‘w’;
C. p2[2] = ‘l’;
D. p2++;
这道题,选择A。
首先,我们有口诀:
左定值,右定向。
即:
- const在*的左边不能改变字符串常量的值,此时是一个常量指针——常量的指针。
- const在*的右边不能改变指针的指向,此时是一个指针常量——指针本身是一个常量。
由上面的两个规则,B、D都是错的。
由于 “world“存储在字符常量区,不能直接修改其值,故C错。
若要修改其值,应该改为char str []= “world”;
7,静态联编与动态联编
- 静态联编是指联编工作在编译阶段完成的,这种联编过程是在程序运行之前完成的,又称为早期联编。
- 动态联编是指联编在程序运行时动态地进行,根据当时的情况来确定调用哪个同名函数,实际上是在运行时虚函数的实现。
8,默认构造函数问题
对于问题:
有以下代码:
struct Foo
{
Foo() { }
Foo(int) { }
void fun() { }
};
int main()
{
Foo a(10); //语句1
a.fun(); //语句2
Foo b(); //语句3
b.fun(); //语句4
return 0;
}
在上面的代码中,最终会出问题是语句4。
因为,语句3并没有声明一个b的Foo类型,而是定义了一个无参数的、返回类型为Foo的函数b。
如果要声明一个Foo,并调用默认构造函数,那么应该是:
Foo b;
9,默认参数问题
- 默认参数在函数声明中提供,当又有声明又有定义时,定义中不允许默认参数。如果函数只有定义,则默认参数才可出现在函数定义中。
- 一旦某个形参被赋予了默认值,它后面的所有形参都必须有默认值。即默认参数的定义必须是从右向左,并且最右边一个参数的右边不能有未指定默认值的参数。
10,C语言中的文件
- 源程序: XXX.c
- 目标程序: XXX.obj(编译生成的)
- 可执行程序: XXX.exe