易被遗忘的C/C++要点总结

作者: rh_Jameson | 来源:发表于2016-03-27 01:02 被阅读3345次
    C C++知识要点总结.png

    一、 数据类型及运算


    求补码

    • 原码的基础上, 符号位不变, 其余各位取反, 最后+1
    • 原码转补码不考虑符号位
    • 补码转原码,符号位不参与运算
    • 取反后 + 1 == 取反前 - 1

    科学计数法表示

    • 1.8 * 10^11 --> 1.8E11
    • 9.34 * 10^-3 --> 9.34E-3

    相关细节

    • sizeof()是一个运算,而非函数
    • ++运算不能用在实数上
    • 判断一个整数是否是2^n(2,4,6,8,16...)
      • !(x & (x - 1))
    • 三目条件运算符代码更优
      • 编译器能产生比if...else...更优的代码

    运算符优先级、结合方向规则

    • 单目 > 双目
    • 算术 > 关系 > 位 > 逻辑 > 条件(三目)> 赋值 > 逗号
      • 算术: + - * /
      • 关系: > < >= <=
      • 位: & | ^
      • 单目: ~
      • 逻辑: && ||
      • 单目: !
    • 自右向左的三种运算符
      • 单目
      • 赋值
      • 条件

    数据输入与输出

    • printf()语句从右向左计算输出表达式的值
        i = 1;
        printf("%d, %d\\\\n", i++, i--);
        //res: 0,1
        //先执行i--,再执行i++
    

    常用输出函数

    • printf()
    • putchar()
      • 输出一个字符
      • 必须是字符型变量或常量
    • puts()
      • 输出一个字符串
      • 必须是字符串或常量

    常用输入函数

    • scanf()

    • gets()

      • 每次读取一个字符串
    • getche()

      • conio.h中
      • 读取字符不用按回车
    • getchar()

      • stdio.h中
      • 完成后须按回车
    • getche() & getchar():
      每次读取一个字符

    • scanf() & gets()区别:
      scanf不能输入含空格字符串,gets可以

    二、选择语句和循环语句


    switch:case 常量表达式

    • 常量表达式只能为整型、字符型
    • 不允许浮点型

    三、数组


    定义

    • 定义数组未赋初值
      • Turbo C会给数组置0
      • VC则取随机值
    • 定义静态数组,则系统自动赋0

    比较字符串数组中的值

    • C:     strcmp(str1,str2)
    • C++:    str1 == str2
    • JAVA:   str1.equals(str2)
      • java中,str1 == str2 比较的是地址

    四、指针


    指针运算

    • 指针相减:   表示两指针所指地址之间的数据个数
    • 指针相加:   没有意义,错误

    数组与指针

    1、一维数组首地址

        int a[10], *p;
        p = &a[0];
        p = a
        //等价,将数组首元素的首地址赋给指针p
    
    • 表示:

      &a[0], a:  数组首元素的首地址
      &a:      数组首地址

    • 对比:

        a == &a[0]
        a != &a    //地址值相同,含义不同
    

    2、二维数组首地址

    int a[10][10];
    

    地址值相同,含义不同:

    a:

    • 二维数组首元素首地址
    • 代表一维数组元素的首地址

    &a:

    • 数组首地址

    &a[0]:

    • 二维数组首元素首地址

    &a[0][0]:

    • &a[0][0] != a
    • a[0] == &a[0][0]

    3、二维数组指针

    • int (*p)[3]:

      • 指向含3个元素的二维数组的行指针
      • 数组每列有3个元素
    • int \p[3] & int \(p[3]):

      • 指针数组,每个元素均是一个指针

    指针与引用的区别

    • 非空区别
      • 引用必须总是指向某些对象
        • 不能使用指向空值的引用
        • 不存在指向空值的引用
        • 效率比使用指针高
      • 指针可以指向空值
    • 合法性区别
      • 使用引用前,无需测试其合法性
      • 使用指针总是需要判空
    • 可修改区别
      • 指针可被重新赋值,以指向另一对象
      • 引用
        •   总指向初始化时被指定的对象
          
        •   以后都不能改变
          
        •   但指定对象的内容可以改变
          
    • 应用区别
      • 指针场景
        •   存在不指向任何对象的情况
          
        •   不同的时刻指向不同对象的情况
          
      • 引用场景
        •   指向一个对象后就不会改变指向的情况
          

    ps:声明引用 / const常量 的同时,必须初始化

    函数指针

    • float(**def)[10];

      • 二级指针

      • 指向一个一维数组的指针

      • 数组元素都是float

    • double\(\gh)[10];

      • 指针gh,指向一个一维数组

      • 该数组元素的类型均为double *

    • double(*f[10])();

      • f是一个数组,含10个元素

        • 元素都是函数指针
      • 指向的函数

        •   没有参数
          
        •   返回double类型的值
          
    • int \( (\b)[10] );

      • 和int \(\b)[10]一样
    • Long (* fun)(int)

      • 函数指针

    五、类型转换


    (int &)相关

    • float a = 1.0f;

    • (int)a实际上是以浮点数a为参数构造了一个整型数,该整数的值是1。

    • (int&)a则是告诉编译器将a当作整数看(并没有做任何实质上的转换)。

    unsigned int

    • unsigned int a = 0xFFFFFFF7;

    • unsigned char i = (unsigned char)a;

      •   i:  000000f7
        
    • char \*b = (char *)&a;

      •   *b: fffffff7
        

    隐式类型转换

    • 算术运算式中,低类型能够转换为高类型

    • 赋值运算式

      • 右边表达式的值自动隐式转换为左边变量的类型,并赋值给他
    • 函数调用中参数传递时,系统隐式地将实参转换为形参的类型后,赋给形参

    • 函数有返回值时,系统将隐式地将返回表达式类型转换为返回值类型,赋值给调用函数

    六、位运算相关


    取两数的平均值:

    (x & y) + [(x ^ y) >> 1]
    

    另类取两数较大值:

      max = [(a + b) + abs(a - b)] / 2
    

    三数取中间数:

        t1 = max(a, b);
        t2 = max(b, c);
        t3 = max(a, c);
        min( t1, min(t2, t3) )
    

    七、函数


    静态函数:   不可被其他文件调用的函数

    函数重载:

    • 参数类型不同

    • 参数个数不同

    • 对返回类型没有要求

    八、#define & const & sizeof


    #define实例

    * #define SEC (60 * 60 * 24 * 365)UL
    * #define MIIN(A, B)    ( (A) <= (B) ? (A) : (B) )
    

    const,#define的区别

    • const

      • 有数据类型

      • 可进行类型安全检查

      • 可对其进行调试

    • \#define

      • 没有数据类型

      • 仅进行字符替换,没有类型安全检查

      • 无法调试

    • c中const

      • 被当做一个不能被改变的普通变量
    • error

        const bufsize = 100;
        char buf[bufsize];
    

    字节对齐

    • 数据对齐规则

      • 结构的首地址必须是结构内最宽类型的整数倍地址

      • 结构体的每一个成员起始地址必须是自身类型大小的整数倍

    • 结构体的整体大小必须可被对齐值整除

    • 结构体的整体大小必须可被本结构内的最宽类型整除

    sizeof

    • 结构体或类内的静态变量
        struct s{
            int a;
            static int b;
        };
        s ss;
        sizeof(ss)
    

    结果:4

    • 静态变量存放在全局数据区

    • sizeof计算栈中分配的大小

    • 任何类型指针大小相同:4(32位)

    • 对函数使用sizeof

    • 在编译阶段会被函数返回值的类型取代

    • 空类大小

      • 单继承:1
      • 多继承:1
      • 虚继承:4
      • 涉及虚表(虚指针)

    内联函数 vs. 宏

    • 内联
      • 相比普通函数: 加快程序运行速度
      • 直接嵌入目标代码
      • 要做参数类型检查
      • 简单的替换
      • 不做参数类型检查

    九、 C++面向对象


    1、类和对象

    类对象的存储空间

    • 只为每个对象的数据成员和函数地址分配内存空间
    • 类中所有成员函数只生成一个副本
    • 该类每个对象执行相同的函数成员

    拷贝构造函数

    • 功能
      • 用一个已知的对象来初始化一个被创建的同类的对象
    • 特点
      • 函数只有一个参数,并且是对某个对象的引用
      • 每个类都必须有一个拷贝初始化构造函数
    • 格式
      • 类名::拷贝初始化构造函数名(const 类名 &引用名)

    静态成员

    • 静态数据成员
      • 特点
        • 类的所有对象共享
        • 必须初始化,且要在类外初始化
      • 引用格式
        • 类名::静态数据成员名
    • 静态成员函数
      • 特点
        • 类的所有对象共享
        • 只能使用类的静态成员和非数据成员
      • 引用格式
        • 类名::静态成员函数名

    类成员指针
    const成员函数

    定义: 任何不修改成员数据的函数都应声明为const函数

    原型: int GetY() const;

    细节:

    • const函数想修改成员变量
      • 在相应变量定义处加上mutable
      • mutable int m_Count;

    2、友元函数

    定义

    • 需在类体内声明
    • 可访问类的私有成员
    • 不是类的成员函数

    优点:    提高程序运行效率

    缺点:   破坏类的封装性和隐藏性

    特点:    可以是多个类的友元

    3、继承和派生

    公有继承

    • 派生类成员函数可访问基类中的公有成员和保护成员
    • 派生类的对象仅可访问基类中的公有成员

    派生类

    • 构造函数执行顺序

      • 基类构造函数
      • 子对象类的构造函数(如果有的话)
      • 派生类构造函数
    • 析构函数执行顺序

      • 派生类的析构函数
      • 基类的析构函数

    虚基类

    相关文章

      网友评论

      本文标题:易被遗忘的C/C++要点总结

      本文链接:https://www.haomeiwen.com/subject/kxodlttx.html