C标准库
字符串
字符串函数包括在头文件string.h中:
#include <string.h>
字符串复制:
char* strcpy(char* dest, const char* src); char* strncpy(char* dest, const char* src, size_t n);
strcpy()将把src复制到dest,包括最后的\0。它的实现大致如下:
char* strcpy(char* dest, const char* src) { while(*dest = *src); return dest; }
strncpy()则只复制n个元素,最后的\0是否复制到需要程序员提供保证:
char src[] = "abc"; char dest[4]; strncpy(dest, src, sizeof(src)); strncpy(dest, src, strlen(src) + 1);
另一种方案是初始化dest时将其所有元素置为0:
char dest[4] = {0};
字符串复制需要确保dest有足够的空间,否则溢出会导致不确定行为。如果dest和src指向相同的地址,那结果也是未知的。
<stddef.h>
offsetof宏
C++标准库
<typeinfo>
typeid()操作符将返回一个type_info对象,通过type_info对象获取类型信息,比较类型是否相等。<typeinfo>定义了type_info类,以及两个异常:bad_typeid、bad_cast。
判断两个类型是否相同:
if(typeid(type1) == typeid(type2)) { }
当typeinfo用于自定义类型时,需要通过RTTI(Run-Time Type Information)来动态获取对象类型。
class Base {}; class Derived : public Base {}; int main() { Derived d; Base* pb = &d; printf(" d type: %s\n", typeid(d).name()); // d type: 7Derived printf("*pb type: %s\n", typeid(*pb).name()); // *pb type: 4Base return 0; }
对比存在虚函数下的类型获取:
class Base { public: virtual void str() {} }; class Derived : public Base {}; int main() { Derived d; Base* pb = &d; printf(" d type: %s\n", typeid(d).name()); // d type: 7Derived printf("*pb type: %s\n", typeid(*pb).name()); // *pb type: 7Derived return 0; }
如果指针指向一个多态类型,且其指为0,则用typeid()获取其类型信息时会抛出bad_typeid异常:
class Base { public: virtual void str() {} }; int main() { try { int *p = 0; printf("%s\n", typeid(*p).name()); // output: i Base *pb = 0; printf("%s\n", typeid(*pb).name()); // throw exception } catch(std::bad_typeid& e) { printf("%s\n", e.what()); // output: St10bad_typeid } return 0; }
如果调用dynamic_cast进行错误的类型转换(引用,而非指针),将抛出bad_cast异常:
class Base { public: virtual void str() {} }; class Derived : public Base {}; int main() { try { Base b; Derived& rd = dynamic_cast<Derived&>(b); } catch(std::bad_cast& e) { printf("%s\n", e.what()); // output: St8bad_cast } return 0; }