C ++ small vs all caps数据类型

时间:2018-03-08 20:44:56

标签: c++ c visual-studio typedef

为什么在C ++(MSVS)中,定义了具有全部大写的数据类型(并且大多数都是相同的)?

  1. 这些完全一样。为什么定义所有大写版本?

    doubletypedef double DOUBLE

    chartypedef char CHAR

  2. boolBOOLtypedef int BOOL),这里所有小写和全部大写代表布尔状态,为什么int用于后者?

  3. 通过这些额外的数据类型获得了什么额外的能力?

4 个答案:

答案 0 :(得分:8)

ALLCAPS typedef在Windows编程的最初几天(1.0及之前)开始。那时候,例如,没有bool类型的东西。 Windows API和标题是为老派C定义的.C ++在开发时甚至不存在。

为了更好地帮助记录API,引入了BOOL之类的编译器宏。尽管BOOLINT都是同一基础类型(int)的宏,但这可以让您查看函数的类型签名,以查看参数或返回值用作布尔值(定义为" 0表示false,任何非零值表示true")或任意整数。

作为另一个例子,考虑LPCSTR。在16位Windows中,有两种指针:near指针是16位指针,far指针同时使用16位&#34;段&#34;值和该段的16位偏移量。实际内存地址在硬件中计算为( segment << 4 ) + offset

每种指针都有宏或typedef。 NPSTR是指向字符串的near指针,LPSTR是指向字符串的far指针。如果是const字符串,则会在CNPCSTR中添加LPCSTR

您可以在&#34; small&#34;中编译代码。 model(默认使用near指针)或&#34; large&#34; model(默认情况下使用far指针)。各种NPxxxLPxxx&#34;类型&#34;将显式指定指针大小,但您也可以省略LN,只需使用PSTRPCSTR来声明与您当前编译匹配的可写或const指针模式。

大多数Windows API函数使用far指针,因此您通常会在那里看到LPxxx指针。

BOOLINT不是唯一一种情况,其中两个名称是同一基础类型的同义词。考虑一种情况,你有一个指向单个字符的指针,而不是一个以零结尾的字符串。这也有一个名字。您可以使用PCH作为指向字符的指针,以区别于指向以零结尾的字符串的PSTR

即使底层指针类型完全相同,这也有助于记录代码的意图。当然,所有变体都有相同之处:PCCH表示常量字符,NPCHLPCH表示明确的近距离和远距离,当然还有NPCCH和{ {1}}指向常量字符的近指针和远指针。是的,在这些名称中使用LPCCH来表示两者&#34; const&#34;和&#34; char&#34;很困惑!

当Windows使用&#34; flat&#34;移动到32位时内存模型,没有更多的Cnear指针,只是平坦的32位指针。但是所有这些类型的名称都被保留下来,以便旧代码可以继续编译,它们只是全部折叠成一个。因此,farNPSTR,普通LPSTR以及上面提到的所有其他变体都成为相同指针类型的同义词(包含或不包含PSTR修饰符)。

Unicode大约在同一时间出现,最不幸的是,UTF-8尚未发明。因此,Windows中的Unicode支持采用ANSI的8位字符和Unicode的16位字符(UCS-2,后来的UTF-16)。是的,当时人们认为16位字符对任何人都应该足够了。世界上怎么可能有超过65,536个不同的角色?! (着名的遗言......)

你可以猜到这里发生了什么。 Windows应用程序可以用ANSI或Unicode(&#34;宽字符&#34;)模式编译,这意味着它们的默认字符指针可以是8位或16位。您可以使用上面的所有类型名称,它们将匹配您的应用程序编译的模式。几乎所有采用字符串或字符指针的Windows API都有ANSI和Unicode版本,const或{{1实际函数名称后缀。例如,A成为两个函数:WSetWindowText( HWND hwnd, LPCSTR lpString)SetWindowTextA( HWND hwnd, LPCSTR lpString )本身成为一个宏,定义为一个或另一个,具体取决于您是为ANSI还是Unicode编译的。

当时,您可能实际上想要编写代码,以便可以在ANSI或Unicode模式下编译。因此,除了宏观函数名称之外,还有一个问题是是否使用SetWindowTextW( HWND hwnd, LPCWSTR lpString )SetWindowText作为窗口标题。 "Howdy"宏(今天通常称为L"Howdy")解决了这个问题。你可以写:

TEXT()

它将根据您的编译模式编译为其中任何一个:

_T()

当然,今天大部分都没有实际意义。几乎每个人都以Unicode模式编译他们的Windows应用程序。这是所有现代Windows版本的本机模式,API函数的SetWindowText( hwnd, TEXT("Howdy") ); 版本是本机Unicode SetWindowTextA( hwnd, "Howdy" ); SetWindowTextW( hwnd, L"Howdy" ); 版本的填充/包装。通过编译Unicode,您可以避免通过所有这些shim调用。但是,如果需要,您仍然可以使用ANSI(或&#34;多字节字符集&#34;)模式编译您的应用程序,因此所有这些宏仍然存在。

答案 1 :(得分:6)

Microsoft决定在Windows代码中为所有这些类型创建宏或类型别名。他们可能会追求一致性&#34;使用全大写WinAPI类型别名,如LPCSTR

但它有什么真正的好处呢?无。

BOOL的情况特别令人头疼。虽然有些老派C有这样做的惯例(在实际bool输入语言之前),但现在它真的很混乱......特别是在使用带有C ++的WinAPI时。

答案 2 :(得分:2)

这个约定可以追溯到Windows操作系统早期的30多年。

70年代和80年代早期的当前实践仍然是使用所有大写字母进行各种汇编语言和当天的高级语言编程,Fortran,Cobol ......以及命令行解释器和文件系统默认值。一种习惯可能源于打卡的编码,可以追溯到20世纪的曙光。

当我在1975年开始编程时,我们使用的打卡机甚至不支持小写字母as you can see on the pictures, it did not even have a shift key

enter image description here

MS / DOS是用汇编语言编写的,80年代早期最成功的PC软件包,例如Lotus 1-2-3,MS Word等.C是贝尔实验室为Unix系统发明的,并采用了很长一段时间才能在PC世界中获得动力。

在萌芽的微处理器世界中,有两个独立的学校:英特尔小端世界,全部大写装配文档和大端摩托罗拉替代品,小盘装配,C和Unix操作系统和克隆和其他奇怪的语言,如作为lisp。

Windows是前者的心血结晶,所有大写类型和修饰符的扩散似乎并不丑陋,它看起来一致且令人放心。 Microsoft为指针修饰符尝试了各种替代方法:far_far__farFAR并最终完全摆脱了这些,但为了兼容性目的保留了原始的allcaps typedef,导致即使在64位系统上也是如32位LONG那样的愚蠢妥协。

这个答案并非没有偏见,但恢复这些记忆很有趣。

答案 3 :(得分:1)

只有MS知道。

我能想到的唯一好处是某些类型(例如int),其大小取决于操作系统(参见the table here)。这将允许在64位OS上使用16位类型,还有一些typedefs#defines。代码将更容易移植到其他操作系统版本。

现在,如果这个&#34;便携式&#34;事情是真的,那么剩下的类型将遵循相同的惯例,即使它们的尺寸在所有机器中都是相同的。