1、全局变量和局部变量的应用:
局部变量会屏蔽全局变量,函数中默认使用的是局部变量,而我们可通过在变量名前添加“::”来指定访问全局变量。
全局变量可声明在可被多个.c文件包含的头文件中,但在这些同名的全局变量中只能有一个C文件对其赋值(定义)。
可以用引用头文件的方式,也可以用extern关键字来引用刚已经定义过的全局变量。
我们通过实例解析下:
Global.h
1 #ifndef GLOBAL_H
2 #define GLOBAL_H
3 extern int g;
4 #endif
这里声明了一个全局变量 g,注意,头文件只是一些接口的说明及数据的声明,一般不采用定义方式。
global1.cpp
1 #include "Global.h"
2 #include <stdio.h>
3
4 extern int g;
5
6 void func(int a)
7 {
8 a += 1;
9 printf("%d",a);
10 }
11
12 int main()
13 {
14 func(g);
15 }
注意第4行,我们使用了extern关键字便是引用已经定义过的全局变量。
global2.cpp
1 #include "Global.h"
2
3 int g = 20;
这里讲一点:只能有一个赋值,否则出错。
编译执行结果为:21.
全局变量时存储在 全局/静态存储区,而局部变量存储在堆栈。
在这里的局部变量我们可引生出一个知识点:静态变量,使用关键字static。
通常,函数中定义的局部变量在函数作用域结束时消失,如果再调用该函数时,将重新创建该变量的存储空间,并被重新初始化。如果我们想使该变量在程序的整个生命周期内有效,即可使用static定义该变量为静态变量,其值只执行一次初始化,之后被持续保存。而又不像全局变量,static变量不同之处在于它在其作用域之外是不可用的。
static的第二层意思:在某个作用域外不可访问。
当应用static于函数名和所有函数外部的变量时,它的意思是“在文件的外部不可以使用这个名字”。所以如果在一个文件内(所有函数外部)定义变量,而在另一个文件使用extern 引用该变量时是不可行的。即将上文的global2.cpp中的g定义为 static int g = 20,则global1.cpp中不会找到g。
2、整型常量的存储
整型数据在内存中是以二进制的形式存放的,数值是以补码表示的。一个整数的补码和其原码的形式相同,一个负数的补码是将该数绝对值的二进制形式按位取反再加1.
3、整型数据的计算
float i ;
i = 5/2;// 2
两操作数类型一样才能做运算,不一样时按类型转换
float i;
i = 5.0/2; // 2.5
4、float型变量
float a与“零值”比较的if语句:
if( (a >= -0.00001) && ( a <= 0.00001 ) )
5、整数自动转换
当将一个负数赋值给无符号类型变量时,负数将自动转换为无符号类型数值,其值范围为0~65535.
6、取模 % 运算:两侧必须为整数
7、define的复合表达式
#define fun(a)( (a)*(a) )
int a = 5;
int b ;
b = fun(a++);
实际fun展开为(a++)*(a++),则得结果为b = 25,a = 7.在此a累加了两次。
8、内存越界
char *p1 = “BeanKo”;
char p2 = (char )malloc( sizeof(char) * strlen(p1) );
strcpy(p2,p1);
p1是个字符串常量,它的长度为6个字符,但实际上所占的内存大小是7个字节,即包括结束标识”\0”.
若以写法 char a[7] = {‘B’,’e’,’a’,’n’,’K’,’o’}; 则就没有结束标志符 。
可修改 :char p2 = (char )malloc( sizeof(char) * (strlen(p1) + 1) );
9、数组名作为左值和右值的区别
char a[3] ,b[] = "china";
a = b;
printf("%s",a);
你发现什么问题了么?
GCC下报错:
arrayAsValue.c:6: error: incompatible types when assigning to type ‘char[3]’ from type ‘char *’
这并不能通过编译。
当数组作为右值时,与&a[0]一样,它代表的是数组首元素的地址,而不是数组的首地址。
同样的,数组作为左值时,代表的也是数组首元素的地址,但是这个地址开始的一块内存是一个整体,只能访问数组中的某个元素而无法访问整个数组,所以可以把a【3】当成左值,而不能把a当成左值。
若将a改为 char *a, 则将b赋值给a时,表示a指向数组首元素的地址,这是一个整体。
10、const 与 #define相比有何优点
const 修饰的只读变量具有特定的类型,而宏没有数据类型。编译器可以对前者进行类型安全检查,而对后者只能进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误。
有些集成化的调试工具可以对const常量进行调试,但不能对宏常量进行调试。
编译器通常不为普通const只读变量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的值,没有了存储与读内存的操作,使得它的效率也很高。