测试标识符没有被截断从而混淆的好方法是什么?

What's a Good Way to Test that Identifiers aren't Being Truncated and Thereby Mixed Up?

本文关键字:方法 是什么 标识符 测试      更新时间:2023-10-16

在今天的c++课上,我们讨论了标识符的最大可能长度,以及编译器在达到一定长度后如何最终停止将变量视为不同的。(我的教授似乎暗示,真正长的标识符会被截断。)我早些时候发布了另一个问题,希望看看是否在某个地方定义了极限。我的问题有点不同。假设我想测试标识符名称长度的实际限制或强制限制。我该怎么做呢?这就是我想做的事,但不知怎么的,它似乎太简单了。

  • 步骤1:生成至少两个具有很长名称的变量,并将它们打印到控制台。如果标识符名称确实没有限制,我就不会浪费时间键入它们。我的代码应该为我做这件事。
  • 步骤2:尝试对变量执行一些操作,例如比较它们,或任何算术。如果编译器停止微分,那么从理论上讲,某些算法将会中断,例如x/(reallyLongA-reallyLongB),因为reallyLongAreallyLongB太长了,编译器会将它们视为相同的东西。在这一点上,除法操作将变成一个除零,这应该崩溃和可怕的燃烧。

我接近这个正确吗?在我"中断"编译器或"运行时"之前,我是否会耗尽内存?

我认为您甚至不需要对变量生成任何操作。

下面的代码将在编译时生成重定义错误;

int name;
int name;

我希望你会得到相同的错误

int namewithlastsignificantcharacterhere_abc;
int namewithlastsignificantcharacterhere_123;

我会使用脚本语言来连续生成更长的名称,直到您得到一个坏的。这是一个Ruby单行代码

C:>ruby -e "(1..2048)每个{| |我所说的"int #{"变量"*我}# {}, "}"> var.txt

当我#include var.txt在一个c文件,并与VS2008编译,我得到错误

"1>c:codequizvar.txt(512):致命错误C1064:编译器限制:令牌溢出内部缓冲区"

和512*8字符是JRL引用的4096

你的教授错了。c++标准§2.11/1说:"所有字符都是有效的"。当然,编译器可能会对允许的长度施加限制,正如您在另一个问题中指出的那样。这并不意味着它们可以忽略后面的字符。

他可能把C和c++搞混了。这两种语言有相似但不完全相同的规则。历史上,C语言的限制低至6个有效字符。

至于你的测试,有一种更简单的方法来测试你的假设。注意,

int a;
int a;

是非法的,因为您两次定义了相同的标识符。现在如果 ReallyLongNameAReallyLongNameB仅在非显著字符上不同,则

int ReallyLongNameA;
int ReallyLongNameB;

也会是编译时错误,因为两者声明的是同一个变量。您不需要运行代码。您可以用这两行生成test.cpp,并尝试编译它。因此,编写一个创建越来越长的标识符名称的小测试程序,将它们写入test.cpp,并调用system("path/to/compiler -compileroptions test.cpp");来查看是否编译。

Windows c++:

只有Microsoft c++标识符的前2048个字符是有很重要的意义。类对用户定义类型的名称进行"修饰"编译器保存类型信息。生成的名称,包括类型信息,不能超过2048个字符。

这样看来,你至少可以用MS编译器做一个相当简单的测试。

编辑:

没有做广泛的测试,但至少在我的Visual Studio Pro 2008上,一个名为aaaa的变量…(总长度4095个字符)编译,之后(>= 4096你得到Fatal Error C1064: compiler limit : token overflowed internal buffer)。

我认为如果在长度达到一些荒谬的大小(如> 1MB)后它仍然工作,那么编译器可能能够处理任意大小的标识符。

当然,没有确定的方法来判断,因为标识符长度限制完全有可能超过您拥有的内存量。(2^32 - 1是完全可能的)