首页 > 编程语言 >32.C和C++的类型安全

32.C和C++的类型安全

时间:2023-07-03 21:34:28浏览次数:51  
标签:int 32 void C++ 安全 类型 指针

什么是类型安全?

类型安全很大程度上可以等价于内存安全,类型安全的代码不会试图访问自己没被授权的内存区域。“类型安全”常被用来形容编程语言,其根据在于该门编程语言是否提供保障类型安全的机制;有的时候也用“类型安全”形容某个程序,判别的标准在于该程序是否隐含类型错误。

类型安全的编程语言与类型安全的程序之间,没有必然联系。好的程序员可以使用类型不那么安全的语言写出类型相当安全的程序,相反的,差一点儿的程序员可能使用类型相当安全的语言写出类型不太安全的程序。绝对类型安全的编程语言暂时还没有。

(1)C的类型安全

C只在局部上下文中表现出类型安全,比如试图从一种结构体的指针转换成另一种结构体的指针时,编译器将会报告错误,除非使用显式类型转换。然而,C中相当多的操作是不安全的。以下是两个十分常见的例子:

●printf格式输出

#include <stdio.h>

int main()
{
    printf("整型输出:%d\n", 10);
    printf("浮点型输出:%f\n", 10);
    return 0;
}

输出:

整型输出:10
整型输出:0.000000

上述代码中,使用%d控制整型数字的输出,没有问题,但是改成%f时,明显输出错误,再改成%s时,运行直接报segmentation fault错误

●malloc函数的返回值

malloc是C中进行内存分配的函数,它的返回类型是void*即空类型指针,常常有这样的用法char* pStr=(char*)malloc(100*sizeof(char)),这里明显做了显式的类型转换。

类型匹配尚且没有问题,但是一旦出现int* pInt=(int*)malloc(100*sizeof(char))就很可能带来一些问题,而这样的转换C并不会提示错误。

(2)C++的类型安全

如果C++使用得当,它将远比C更有类型安全性。相比于C语言,C++提供了一些新的机制保障类型安全:

●操作符new返回的指针类型严格与对象匹配,而不是void*

●C中很多以void*为参数的函数可以改写为C++模板函数,而模板是支持类型检查的;

●引入const关键字代替#define constants,它是有类型、有作用域的,而#define constants只是简单的文本替换

●一些#define宏可被改写为inline函数,结合函数的重载,可在类型安全的前提下支持多种类型,当然改写为模板也能保证类型安全

●C++提供了dynamic_cast关键字,使得转换过程更加安全,因为dynamic_cast比static_cast涉及更多具体的类型检查。

例1:使用void进行类型转换*

img

在C++中,使用void*指针可以进行类型转换。void*指针是一个通用指针,它可以指向任何类型的数据,包括结构体、类和数组等。

以下是一些使用void*进行类型转换的示例:

1.将一个结构体指针转换为void*指针:

struct MyStruct
{
    int x;
    float y;
};

MyStruct* myStruct = new MyStruct();
void* voidPtr = myStruct; // 将结构体指针转换为void*指针

2.将一个类指针转换为void*指针:

class MyClass
{
public:
    int x;
    float y;
};

MyClass* myClass = new MyClass();
void* voidPtr = static_cast<void*>(myClass); //将类指针转换为void*指针

例2:不同类型指针之间转换

#include<iostream>
using namespace std;
 
class Parent{};
class Child1 : public Parent
{
public:
	int i;
	Child1(int e):i(e){}
};

class Child2 : public Parent
{
public:
	double d;
	Child2(double e):d(e){}
};
int main()
{
	Child1 c1(5);
	Child2 c2(4.1);
	Parent* pp;
	Child1* pc1;
 	
	pp=&c1; 
	pc1=(Child1*)pp;  // 类型向下转换 强制转换,由于类型仍然为Child1*,不造成错误
	cout<<pc1->i<<endl; //输出:5
 
	pp=&c2;
	pc1=(Child1*)pp;  //强制转换,且类型发生变化,将造成错误
	cout<<pc1->i<<endl;// 输出:1717986918
	return 0;
}

上面两个例子之所以引起类型不安全的问题,是因为程序员使用不得当。第一个例子用到了空类型指针void*,第二个例子则是在两个类型指针之间进行强制转换。父类转子类不安全,子类转父类安全。发生多态安全。因此,想保证程序的类型安全性,应尽量避免使用空类型指针void*,尽量不对两种类型指针做强制转换

参考资料来源:

阿秀

标签:int,32,void,C++,安全,类型,指针
From: https://www.cnblogs.com/codemagiciant/p/17524136.html

相关文章

  • 34.C++有哪几种的构造函数
    34.C++有哪几种的构造函数C++中的构造函数可以分为4类:默认构造函数:在没有显式定义构造函数时,C++会自动生成一个默认构造函数,该函数没有参数,不执行任何操作。初始化构造函数(有参数)拷贝构造函数:当使用现有对象初始化新对象时,拷贝构造函数被调用。它的语法是在函数声明时使用一......
  • 33.C++中的重载、重写(覆盖)和隐藏的区别
    (1)重载(overload)  重载是指在同一范围定义中的同名成员函数才存在重载关系。主要特点是函数名相同,参数类型和数目有所不同,不能出现参数个数和类型均相同,仅仅依靠返回值不同来区分的函数。重载和函数成员是否是虚函数无关。举个例子:classA{...virtualintfun();......
  • 【C++】关于常引用的问题 #什么是权限放大?权限放小?隐式或强制转换居然还有这一步?...#
    前言引用在c++中的使用非常常见,可以说是很重要的,引用的常引用相关的问题让很多人稍不留神就出错了,这里我们就来谈谈常引用的问题。关于权限关于权限有权限缩小和权限放大的问题,比如一个文件,当初它只有读的权限,而现在你给它再加个写的权限,这就是权限放大;又或当初它读,写的权限......
  • 7.区别以下指针类型?
    int*p[10]int(*p)[10]int*p(int)int(*p)(int)int*p[10]表示指针数组,强调数组概念,是一个数组变量,数组大小为10,数组内每个元素都是指向int类型的指针变量。int(*p)[10]表示数组指针,强调是指针,只有一个变量,是指针类型,不过指向的是一个int类型的数组,这个数组大小是10。i......
  • 11.既然有了malloc-free,C++中为什么还需要new-delete呢?直接用malloc-free不好吗?
    malloc/free和new/delete都是用来申请内存和回收内存的。在对非基本数据类型的对象使用的时候,对象创建的时候还需要执行构造函数,销毁的时候要执行析构函数。而malloc/free是库函数,是已经编译的代码,所以不能把构造函数和析构函数的功能强加给malloc/free,所以new/delete是必不可少......
  • C++学习笔记
    类型兼容不同类型的数据在一定条件下可以进行转换,比如intn='a',是将字符'a'赋值给整型变量n,在赋值过程中发生了隐式类型转换,字符类型的数据转换为整型数据。这种现象称为类型转换,也称为类型兼容。继承与派生继承方式public继承private继承protect继承类型兼容在C++中,基类与派生......
  • C++ 宏定义
    看到一段C++代码,大致是说如果如果定义了RUN_ALL_TESTS就执行下面的代码,遂研究了一下。#ifdefined(RUN_ALL_TESTS)//somecodehere#endif首先RUN_ALL_TESTS是定义的宏:#defineRUN_ALL_TESTS//空字符串#defineRUN_ALL_TESTS1//赋值为1#ifdefined......
  • Inno setup 脚本判断 Microsoft Visual C++ Redistributable 不同版本区别
    有个需要是需要在安装包安装初始化时安装MicrosoftVisualc++2013Redistributable也就是判断软件安装前需不需要运行vcredist_x64.exe和VC_redist.x64.exe这两个程序第一反应就是可以通过注册表判断是否已经安装过环境但测试发现需求的两个版本不同,注册表位置竟然也不......
  • yaml文件类型解析
    yaml文件类型mysql:host:127.0.0.1user:testport:35039db:testpassword:1234567dp_ip:-192.168.0.1-192.168.0.2-192.168.0.3读取后结果为{'mysql':{'host':'127.0.0.1','user':'test',......
  • 记录一个boost1.72和Win32api的冲突
    报错:2>C:\ProgramFiles(x86)\WindowsKits\10\Include\10.0.19041.0\um\fileapi.h(53,1):errorC2116:'boost::interprocess::winapi::CreateDirectoryA':functionparameterlistsdonotmatchbetweendeclarations2>D:\software\boost_1_7......