当前位置: 代码迷 >> 综合 >> C/C++define、assert、自增自减、类型转换相关认识
  详细解决方案

C/C++define、assert、自增自减、类型转换相关认识

热度:38   发布时间:2023-12-14 12:15:19.0

1.#与##在define中的作用

1.0 宏定义中#运算符将其后面的参数转换成字符串;

如下代码:

#define TEST_1(x) cout << #x << endl

int n = 100;
TEST_1(n);

输出如下:

n

输出的是字符串化后的n,而不是其他值;

1.1 宏定义中##运算符将前后的参数进行字符串连接;

测试代码和结果如下:

#define TEST_2(x,y,z) cout<< x##y##z << endl
int main()
{TEST_2("st", "ri", "ng");
}

string
请按任意键继续. . .

2.assert断言相关认识点

2.0 本质经查是一个函数,检测条件表达式,如果为假,表示检测失败,程序会向stderr中输出一条错误信息,再调用abort函数终止程序执行。

2.1 在#include语句之前插入#define NDEBUG 可禁用assert函数

2.2 在每个assert中只检测一个条件,不要在assert中修改变量的值

测试代码如下:

int main()
{int x = 1, y = 2;assert(x > y);cout << "x > y" << endl;
}

程序直接报错了,当加#define NDEBUG 后 可忽略程序中的assert语句。

#define NDEBUG
#include "test_1.h"int main()
{int x = 1, y = 2;assert(x > y);cout << "x > y" << endl;
}

x > y
请按任意键继续. . .

3. 自增自减

3.0 如下代码在不同编译器环境下可能会产生二义性

int main()
{int i = 1;int m = (++i) + (++i) + (++i);cout << "m : " << m << endl;cout << "i : " << i << endl;
}

在本人VS2015中运行结果如下:

m : 12
i : 4
请按任意键继续. . .

而在GCC编译器中,只要有连个完整的操作数就会立即执行加法运算(本人并未亲自验证,参考自书籍《程序员面试笔记C/C++、算法、数据结构篇》。其与VS编译器执行差别图示如下:

4.0 c++中的类型转换操作符

4.0 static_case

除了基本类型外,在对象指针之间的类型转换时,可以将父类指针转换成子类指针,也可以将子类指针转换成父类。

int i = 1;
double di = static_cast<double>(i);class Base {};
class Derived : public Base {};Base * b1ptr = new Base;
Base * b2ptr = new Derived;
Derived *d1ptr = static_cast<Derived * >(b1ptr);    //父指针转子指针
Derived *d2ptr = static_cast<Derived * >(b2ptr);	 //父指针转子指针Derived * d3ptr = new Derived;
Base * b3ptr = static_cast<Base *>(d3ptr);				 //子指针转父指针                   

4.1 dynamic_cast

只能用于对象指针建的转换,转换结果可以是引用。

在将父指针转换成子指针的过程中,需要对其背后的对象类型进行检测,以保证类型完全匹配,而static_cast不会怎么做,只有当有一个父类指针指向一个子类对象,并且父类中包含虚函数时,使用dynamic转化才会成功,否则返回空指针,如果是引用则抛出异常。

class Base { virtual void Test() {} };
class Derived : public Base {};Base * b1ptr = new Base;
Base * b2ptr = new Derived;Derived *d1ptr = dynamic_cast<Derived * >(b1ptr);    //失败,d1ptr值为NULL
Derived *d2ptr = dynamic_cast<Derived * >(b2ptr);	  //成功Derived * d3ptr = new Derived;
Base * b3ptr = dynamic_cast<Base *>(d3ptr);				//成功                                                                                                                                                       
int main()
{assert(d2ptr != NULL);assert(b3ptr != NULL);assert(d1ptr != NULL);
}

4.2 const_cast

 在转换过程中增加或删除const属性。

class Base { };
class Derived : public Base {};const Base * b1 = new Base;				//指向常量的指针
Base * const b2 = new Base;				//常量指针
const Base * const b3 = new Base;		//指向常量的常量指针Base * b4 = const_cast<Base *>(b1);	//去掉外层const		
Base * b5 = const_cast<Base *>(b2); //去掉内层const
Base * b6 = const_cast<Base *>(b3); //都去掉const Base * const b7 = const_cast<Base *>(b6);//增加外层和内层constint main()
{assert(b4 != NULL);assert(b5 != NULL);assert(b6 != NULL);assert(b7 != NULL);
}

4.3 reinterpret_cast

可以将一种类型转换成另一种类型 ,不论两个类型之间是否有继承关系。此外还可以把一个指针转换成一个整数,也可以把一个整数转换成一个指针。

class Test1 { };
class Test2 { };Test1 * t1 = new Test1;
Test2 * t2 = reinterpret_cast<Test2 *>(t1);unsigned int n = 0x12345678;
unsigned int * p = reinterpret_cast<unsigned int *>(n);int main()
{assert(t2 != NULL);assert((int)p == 0x12345678);
}

 

  相关解决方案