解释"C从根本上说是一个腐败型系统"

Ian*_*non 23 c c++ type-systems

Coders at Work(p355)一书中,Guy Steele谈到了C++:

我认为向后兼容C的决定是一个致命的缺陷.这只是一系列无法​​克服的困难.C基本上有一个腐败型系统.它足以帮助你避免一些困难,但它不是密不透风的,你不能指望它

将类型系统描述为"腐败"是什么意思?

你能用C中的一个简单例子来证明吗?

编辑:

  1. 引用听起来很有争议,但我并不想成为.我只想了解他的意思.

  2. 请举例说明C而不是C++.我也对"基本"部分感兴趣:)

Cas*_*Cow 19

非类型安全C中的明显示例仅仅来自于您可以从void*转换为任何类型而无需显式转换的事实.

struct X
{
  int x;
};

struct Y
{
  double y;
};

struct X xx;
xx.x = 1;
void * vv = &xx;
struct Y * yy = vv; /* no need to cast explicitly */
printf( "%f", yy->y );
Run Code Online (Sandbox Code Playgroud)

当然printf本身并不完全是类型安全的.

C++并不完全是类型安全的.

struct Base
{
   int b;
};

struct Derived : Base
{
  int d;

  Derived() 
  {
     b = 1;
     d = 3;
  }
};

Derived derivs[50];
Base * bb = &derivs[0];
std::cout << bb[3].b << std::endl;
Run Code Online (Sandbox Code Playgroud)

将Derived*转换为Base*没有问题但是当你尝试使用Base*作为数组时遇到问题,因为它会使指针算术全部错误,而所有b值都是1,你可能得到3 (因为整数将进入1-3-1-3等)

  • @CashCow,只是为了挑剔.在C中,您不能从`void*`转换为任何其他指针类型,而只能转换为指向数据的指针.不允许转换为函数指针. (3认同)
  • @Matt Joiner:如果你"必须在C++中左右抛出一切",你就会做错事 (2认同)

Han*_*ant 5

char buffer[42];
FunctionThatDestroysTheStack(buffer);  // By writing 43 chars or more
Run Code Online (Sandbox Code Playgroud)

  • 我不确定这是类型系统中的缺陷. (8认同)
  • @KenBloom:无限制的内存访问与类型系统无关.(例如PEEK和POKE只接受整数参数) (4认同)
  • 一个很好的例子,但任何支持直接无限制内存访问的语言都允许您轻松编写可怕的代码,并且所有这些代码都提供了易于理解的编程模式以避免这些陷阱.糟糕的程序员!=糟糕的语言. (2认同)

sha*_*oth 5

基本上你可以将任何数据类型转换为任何数据类型

struct SomeStruct {
    void* data;
};

struct SomeStruct object;
*( (int*) &object ) = 10;
Run Code Online (Sandbox Code Playgroud)

没有人抓住你。

  • 这不是 C,而且强制转换会关闭类型系统,这并不是类型系统损坏的证据。 (3认同)
  • @Ben:是的。类型系统控制允许哪些类型转换。允许您忽略类型系统的强制转换很好地表明类型系统已损坏(尽管这当然并不意味着*语言*已损坏。甚至类型系统毫无用处) (3认同)