1.1 2进制、8进制、16进制的相互转换
2进制转换成8进制方法为:
3位二进制数按权展开相加得到1位八进制数。(注意事项,3位二进制转成八进制是从右到左开始转换,不足时补0)。
8进制转换成2进制数:
八进制数通过除2取余法,得到二进制数,每个八进制对应三个二进制,不足时在最左边补充零。
2进制转16进制 :
与二进制转八进制方法近似,八进制是取三合一,十六进制是取四合一。(注意事项,4位二进制转成十六进制是从右到左开始转换,不足时补0)。
16进制转2进制 :
十六进制数通过除2取余法,得到二进制数,对每个十六进制为4个二进制,不足时在最左边补零。
8进制转换成16进制 :
与二进制转八进制方法近似,八进制是取三合一,十六进制是取四合一。(注意事项,4位二进制转成十六进制是从右到左开始转换,不足时补0
16进制转换成8进制 :
将十六进制转换为二进制,然后再将二进制转换为八进制,小数点位置不变。
1.2 位运算
1.2.1 概括
符号 描述 运算规则
& 与 同为1时,结果为1
| 或 同为0时,结果为0
^ 异或 相同为0,不同为1
<< 左移 二进位全部左移若干位,后面低位补0
>> 右移 二进位全部右移若干位,低位丢失,高位补0
~ 取反 0变1,1变0
1.2.2 或运算符(|)
只有同为0的时候结果才为0
其他情况都为1
只要出现1结果就为1
1.2.3 与运算(&)
运算规则:
都为1的时候结果为1
不同的时候结果为0
都为0的时候也为0
1.2.4 异或运算符(^)
运算规则:
异或运算不管0还是1,只要遇到相同的就为0,只要遇到不相同就为1
1.2.5 取反运算符(~)
运算规则:
~1=0;
~0=1;
即:对一个二进制数按位取反,即将0变1,1变0。
使一个数的最低位为零,可以表示为:a&~1。
~1的值为1111111111111110,再按“与”运算,最低位一定为0。
因为“~”运算符的优先级比算术运算符、关系运算符、逻辑运算符和其他运算符都高。
1.2.5 左移运算符(<<)
运算规则:
1、左移可看作 整数M乘以2的N次方
2、"<<"右边的数字就是N,左边的数字就表示这个整数M
1.2.6 右移运算符(>>)
1、右移可看作 整数M除以2的N次方
2、"<<"右边的数字就是N,左边的数字就表示这个整数M
1.3结构体的使用及参数传递
1.3.1 结构体(struct)
1、基本概念
结构体-----将不同类型的数据成员组织到统一的名字之下,适用于对关系紧密,逻辑相关、具有相同或不同类型的数据进行处理
2、结构体定义格式
struct 结构名(也可称作结构标识符)
{
类型 变量名;
类型 变量名;
};
struct 结构名 结构变量;
或者
struct 结构名
{
类型 变量名;
类型 变量名;
}结构变量;
1.3.2 typedef函数
为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等),
注意typedef与define的区别,typedef 是用来定义一种类型的新别名的,它不同于宏#define,宏是简单的字符串替换
例:
typedef int INTEGER;
为int定义了一个新的名字INTEGER,也就是说INTEGER与int是同义词,也可以为结构体定义一个别名
typedef struct student STUDENT;
或者
typedef struct student { int num; }STUDENT;
上述两条语句是等价的,二者都是为struct student结构体类型定义了一个新的名字STUDENT,即STUDENT与struct student是同义词,所以下列两条语句等价
1.3.3参数传递
参数传递传值方式:将实参的值拷贝给函数或方法,在函数内对形参进行操作,操作的对象是实参的拷贝,对实参本身没有影响,在函数结束返回后,形参被丢弃释放,实参的内容不会被改变
参数传递传址方式:将实参的地址传递给函数,在函数内对形参进行操作等同于对实参进行相同的操作,在函数调用结束返回后,形参被释放,实参的内容是对形参进行操作后的结果。
参数传递引用方式:
1.引用实际上是某一个变量的别名,和这个变量具有相同的内存空间;
2. 实参把变量传递给形参引用,相当于形参是实参变量的别名,对形参的修改都是直接修改实参;
3. 在类的成员函数中经常用到类的引用对象作为形参,大大的提高代码的效率。
1.4 静态变量(static)、extern变量,关键字const
static
主要用于修饰变量或常量, 使其成为静态变量或常量,延长其生命周期, 可用于修饰局部变量和全局变量。 使用其来修饰的数据类型使其变为静态类型。
在全局变量前加static,全局变量就被定义成为一个全局静态变量(全局变量和静态全局变量的生命周期是一样的,都是在堆中的静态区,在整个工程执行期间内一直存在) 特点如下:
①存储区:静态存储区没变(静态存储区在整个程序运行期间都存在);
②作用域:全局静态变量在声明他的文件之外是不可见的。准确地讲从定义之处开始到文件结尾。非静态全局 变量的作用域是整个源程序(多个源文件可以共同使用);
而静态全局变量则限制了其作用域, 即只在定义该变量的源文件内有效, 在同一源程序的其它源文件中不能使用它。
好处:
不会被其他文件所访问,或者所修改;其他文件中可以使用相同名字的变量,不会发生冲突。
修饰局部变量
-
延长局部变量的生命周期,程序结束才会销毁。
-
局部变量只会生成一份内存,只会初始化一次。
-
虽然出了声明的作用域,并且其未销毁,但是并无法进行访问。
-
存储区域由栈转移到静态存储区。
- 修饰全局变量
-
改变其作用域,只能在当前文件下访问,其他文件不可见。
-
其他文件如果声明同名则不会报错,也不会对此全局变量有影响。
- 修饰函数
类似修饰变量的作用。
extern用法详解:
1. 声明外部实体
声明外部全局变量或对象,一般用于头文件中,表示在其它编译单元内定义的变量,链接时进行外部链接,如:
extern int ivalue;
此时的extern是必须的,省略了extern编译器将视为定义而不是声明,一般地在源代码中定义变量并进行初始化,在头文件中使用extern声明变量。
类似地用于声明外部全局函数,表示该函数在其它编译单元中定义,如:
extern void func( void );
此时的extern可以省略。
2. 声明函数的编译和链接方式
extern 后可以跟"C"或"C++"用于声明全局函数的编译和链接方式,例如:
extern "C" void add( int a, int b); extern "C++" void sum(int* ia, int leng); void sum(int* ia, int leng);
其中的extern "C++"可以省略,它是在C++中默认的链接方式,即后面两种声明方式是等效的。这种声明有两种含义:首先,声明这些函数使用外部链接方式,其实现不在本编译单元之内;另一种含义,则是告诉编译器编译方式,如extern "C"则是告诉编译器使用C语言的编译方式编译该函数。
C++支持函数重载,所以参数不同在编译后生成的函数名也不同,如:
int max(int a, int b);
int max(float a, float b);
在编译时生成的函数名可能分别为_max_int_int、_max_float_float,通过在函数名后加上参数类型来区分不同的函数,如果使用C语言方式,则生成的函数名中不包含参数信息,只生成_max,所以无法实现重载,也就是说在extern “C”中不能出现函数名重载,例如:
extern "C" { int max(int a, int b); int max(float a, float b); }
非法,编译器将报错。而C++标准中并没有定义extern “C”与extern “C++”的具体实现方式,不同编译器生成的符号规则可能不同。
需要注意的是,如果函数声明使用了extern "C",则函数定义必须使用C编译器编译,或者使用extern "C"来修改函数的编译方式,一般地将extern "C"声明的函数的定义所在的源程序扩展名使用.c即可,而C++代码放在.cpp文件中。如果将extern "C"声明的函数实现也放在.cpp中,则需要使用extern "C"来声明函数编译方式,例如:
extern "C" { int max( int a, int b) { return a > b ? a : b; } }
只有在C++中使用C语言的库或者两种语言混合编程的时候才会用到extern "C",而在C语言中是不支持extern "C"的,所以为了头文件通用,需要使用宏来控制,例如:
1 #ifndef MAX_H 2 #define MAX_H 3 #ifdef __cplusplus 4 extern "C" { 5 #endif 6 int max (int a, int b); 7 #ifdef __cplusplus 8 } 9 #endif 10 #endif
其中__cplusplus为C++定义的宏,凡是C++的编译器都定义了该预编译宏,通过它来检测当前编译器是否使用的是C++编译器。
const
const修饰的量为一个常量即不能被修改的量。但在C语言中的const可以不初始化但后续也就无法对其赋值,所以尽管不初始化不会出错。但要使用const修饰的量就需要对其进行初始化。编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高。