什么是类型安全,什么是“类型安全”替代品?

可能重复:
什么是类型安全的?
什么是类型安全?

我正在阅读有关c ++向量的内容,并且提到C中的memcpyprintf函数不是类型安全的。 文章: http : //en.wikipedia.org/wiki/Vector_(C%2B%2B) 。

问题:简单的英语,什么是类型安全,什么是“类型安全”替代品?

类型安全意味着编译器可以检查您是否使用了正确的类型。 例如,如果您使用的是printf ,则可能会因为写入以下内容而意外崩溃您的程序:

 printf("The meaning of life is %s", 42); 

因为42是整数,而不是字符串。

类型安全意味着编译器将帮助检查您是否混合(不兼容)数据类型。

例如,当你调用memcpy ,函数(和编译器)只在内存中看到两个指针,并且很乐意开始复制数据。 这意味着您可以混合不兼容的数据类型,如下所示:

 SomeClass a; AnotherClass b; memcpy((void*)&a, (void*)&b, sizeof(b)); 

有许多方法可以获得类型安全性。 您可以使用模板并围绕mempcy()创建一个包装器,确保两个指针指向相同的数据类型,或者您可以使用其他方式。

由于您已经在使用STL中的向量,因此您已经在使用或多或少类型安全的实现。

类型安全性控制编译器的使用,检查变量是否为正确类型。 C在数据类型安全方面非常松散,例如,这实际上是在ANSI C标准中,声明类型提升将发生在数据类型char ,此赋值中的一个示例将解释这一点,

 char ch = 32; /* that is a space character accordingly to ASCII */ int n = ch + 3; 

注意ch变量如何被“提升”为int类型。 这是合法的,但如果这就是你所暗示的,则值得仔细检查。

像C#编译器这样的编译器不会允许这种情况发生,这就是为什么在C中,使用强制转换运算符的原因如下:

 int n = (int)3.1415926535f; 

除了挑剔之外,这是一个pi值,会发生什么, n的值将是3。

以上用于说明类型安全性,并且C在这方面非常松散。

现代语言中的类型安全性更严格,例如Java,C#,以限制变量的用法和含义。 PHP是松散类型的一个很好的例子,你可以这样做:

 $myvar = 34; $myvar = $myvar + "foo"; 

$myvar是一个整数,还是浮点数,或者是一个字符串。 这里的类型安全性并不十分清楚可能导致错误的意图是什么,以及试图找出正在发生的事情的快乐调试会话。

希望这可以帮助

既然你还在维基百科上: 键入安全性 。

粗略地说,类型安全意味着该语言禁止您意外混淆您的类型。

memcpy不是类型安全的,因为您可以轻松地将某些int的内存复制到char数组中,最终得到无意义的数据。 printf不是类型安全的,因为您可以使用字符串提供%i格式说明符; 再一次,字符串将被解释为一个int ,你最终会得到垃圾。 (顺便说一下,VC ++编译器在某些情况下检查格式字符串。)

std::vector是类型安全的,因为它只允许您将给定类型T值放入其中。 (当然,你可以做明确的类型转换,但重点是你必须明确做一些不安全的事情)。

“类型安全”意味着编译器检查您正在使用正确的类型做正确的事情(例如,如果您尝试将Banana视为橙色,则触发编译器错误,或者为期望输出整数的函数提供字符串) 。

void*进入图片时,类型安全(大多数)就会从窗口出来 – 它是一个可以指向任何东西的指针(完全没有意识到所涉及的类型),并且语言在程序员手中完全消失了(例如, void*对于任何东西都不是很好,除了被回流到原始类型;它可以代表任何东西,但你必须知道它是什么之后你可以使用它)。

类型不安全也可以使用像varf这样的可变函数(编译器不关心有多少参数以及它们的类型是什么 – 再次由调用者来确保格式字符串与参数及其类型匹配) 。

memcpy的类型安全替代(对于数组和容器)可以是 std::copy – 如果所有涉及的类型满足某些要求,它可以用memmove实现,否则它执行赋值 – 对于某些类,你可以打破某些不变量,如果你绕过他们的公共接口,只是在内存中移动/复制它们(例如,我想任何具有非平凡复制构造函数的类如果你用memcpy复制它就会行为不端)。

CI / O例程的类型安全替代方法是iostream(如果您希望获得格式字符串的优点,可以使用boost::format )。

“类型安全”使用“类型系统”来确保错误不会在程序中传播。 例如,在没有类型安全的情况下,可能(以静默方式)以某种不期望的方式将字符串类型添加到浮点类型。

在你所讨论的实例中, memcpy()printf() ,缺乏类型安全性是由于函数如何处理它们的参数。 例如,对于memcpy(arg1,arg2,len) ,从内存地址arg2开始的len个字节将被复制到内存地址arg1 ,无论arg1指向多少字节,可能会覆盖程序的其他部分。

对于类型安全的替代方案,请查看构造函数和cout

实际上,请查看整个C ++ FAQ Lite

这意味着如果您尝试以对该类型没有意义的方式使用类型,编译器将不会生成警告。 例如,以下是未定义的行为,并且在实践中将指针的位复制到浮点的位,在那里它们完全没有意义。 如果sizeof(char*) > sizeof(float) ,它将覆盖碰巧位于f所在位置的任何内存位置。

 float f; char *c = someString(); memcpy(&f, &c, sizeof(char*)); 

类型安全是指一种编码范例,它强制每个变量在编译时具有专用类型,例如int a = 4; double d = 100.0; struct ms {char s;} mystruct; int a = 4; double d = 100.0; struct ms {char s;} mystruct; 变量的类型永远不会“丢失”。 如果要将其类型从a更改为b,则必须定义显式或隐式转换。

printf 不是类型安全的,因为您在可变参数列表中传递参数:

 float f = 1.f; printf("This is a float: %f\nAnd this is a string: %s",f,f); 

printf不知道她收到了哪种价值观。 实现使用格式字符串来查找,但如果字符串错误,则实现没有机会找到它,因为在编译时没有可用的类型信息。 上面的printf调用最有可能最终发生灾难性的事 – printf期望一个字符串作为第二个参数,但得到一个浮点数。

答案的简短版本:

 class Person; person.DoSomething(); // This is type safe. void * p = &person; // You can now start doing unsafe things with p. 

你不能将Person传递给memcpy。 它只知道并关心记忆。 字节。

memcpy函数的签名是

 void *memcpy (void* destination, const void* source, size_t num); 

所以你可以看到它没有假设任何涉及副本的指针,它们只是指针。 因此,如果您想要将一系列的ints复制到一系列floats编译器就不会抱怨它。

Type Safety是一种工具,可以帮助开发人员避免某些错误,防止某些错误代码被编译(并最近执行)。 它分析源代码的语义方面,以检查类型和类型之间的转换是否一致。

那是什么意思? 这意味着如果您的程序通过了类型检查阶段,您可以确保在运行时不会生成某些错误。

当然有时你需要强制执行此检查,这就是为什么你可以使用强制转换来强制你想要的东西。 想想另一个例子, malloc :它被定义为

 void* malloc (size_t size); 

因此,当您想要分配指向floats的指针时,例如,您执行以下操作:

 float* ptr = (float*)malloc(sizeof(float*)*COUNT); 

你被迫将函数的结果转换为float*否则typecheck将为float*找到void*的赋值但是void*太通用而不能被赋值: TYPE CHECK FAIL!

这就是memcpy不是类型安全的原因。 它不会检查任何内容,只是从指针复制到另一个指针。