1.在C语言中如果没有做特殊声明,浮点数一律按双精度浮点数处理。除非在浮点数后面加了f做特殊声明,则按照单精度浮点数处理。例如:
float=12.25;//按照双精度浮点数处理。
float=12.25f;//按照单精度浮点数处理。
2.所有字符串常量都存储在全局变量区。
char*p="yhping";//因为字符串常量存储在全局变量区,所以指针p中存储的是"yhping"字符常量在全局变量区中的地址。
3.下面一段代码:
void main()
{
const int a=10;
int b=a;
int &c=a;
}
这段代码是不能编译通过的。因为常变量a的值是不可更改的,但是通过引用则有可能改变a的值,所以编译时无法通过的。
可以做以下更改:
void main()
{
const int a=10;
int b=a;
const int &c=a;
}
或者下面一段代码也是可以编译通过的:
void main ()
{
int a=10;
int &b=a;
const int &c=a;//c引用了a的值,但不能通过c的改变而改变a的值。这个实际上被编译器变成了:int const *p=&a;c=*p;
}
下面一段代码:
const int a=10;
const int &b=10;//这段代码也是可以编译通过的。它被编译器处理为:int tmp=10;const int &b=tmp;
为什么要这样做呢?因为C语言和c++不安全,它所定义的引用有可能改变其常性。必须经过中间变量予以消除。
4.实参、形参的传递过程,实际上就是压栈的过程。
5.凡是在函数中定义的变量都是局部变量,凡是在函数外面定义的变量都是全局变量。
局部变量是在函数被调用的时候才产生的,函数调用结束释放。
6.函数的返回值99%都是通过eax寄存器完成的。
7.返回局部变量的地址是没有价值的。所以决不允许返回局部变量的地址。
下面一段代码:
int *add(int a,int b)
{
int c=a+b;
return &c;
}
void fun()
{
int a=10;
int b=20;
int c=40;
}
void main()
{
int x=10;
int y=20;
int *p=NULL;
p=add(x,y);
fun();
printf("%d\n",*p);
}
可见所打印的p指针所指向的空间内容是一个随机值。因为当add函数被调用时会在栈区产生一段栈帧供add函数使用,当add函数被调用结束后,此段栈帧区域被释放掉。在这段内存空间中它的值可能会存在,但这段内存空间已不再为add函数所控制,所以当再有函数被调用时,此段内存空间又会再被分配给其他函数使用。因此此内存空间中的值有可能会被覆盖,所通过此指针所访问到的值自然也就是一个随机值。
8.函数对栈帧是重复使用的。
9.下面一段代码:
int *add(int a,int b)
{
int c=a+b;
return &c;
}
void fun()
{
c=100;
}
void main()
{
int x=10;
int y=20;
int *p=NULL;
p=add(x,y);
fun();
printf("%d\n",*p);
}
因为fun函数与add函数的结构相似,所以当调用fun函数是,为fun函数所分配的栈帧会覆盖之前add函数所占据的栈帧,并且变量c恰好占据了指针指向的内存区域。所以打印出来的值会是100,而不是30。
10.寄存器没有地址,没有对寄存器编址,不能对寄存器取地址。
11.下面一段代码:
int &add(int a,int b)
{
int c=a+b;
return c;
}
void main ()
{
int x=10;
int y=20;
int c=add(x,y);
int *p=&add(x,y);
int &a=add(x,y);
printf("%d%d%d\n",c,*p,a);
}
这段代码被编译器编译成:
int *add(int a,int b)
{
int c=a+b;
return &c;
}
void main ()
{
int x=10;
int y=20;
int c=*add(x,y);
int *p=&add(x,y);
int &a=add(x,y);
printf("%d%d%d\n",c,*p,a);
}