windows 头文件 far near

经常在windows的头文件中见到 类似一下类型重定义:

typedef BOOL near           *PBOOL;
typedef BOOL far            *LPBOOL;
typedef BYTE near           *PBYTE;
typedef BYTE far            *LPBYTE;
typedef int near            *PINT;
typedef int far             *LPINT;
typedef WORD near           *PWORD;
typedef WORD far            *LPWORD;
typedef long far            *LPLONG;
typedef DWORD near          *PDWORD;
typedef DWORD far           *LPDWORD;
typedef void far            *LPVOID;

好奇的是为什么在类型和指针之间加上far 或者 near?
参考 https://www.cnblogs.com/littlepear/p/5933649.html
首先转到far 和near的定义,在这里插入图片描述
发现二者是配套使用的,需同时存在:
在16位Windows中,内存是分段的,所以指针分为两类:FAR指针和NEAR指针。FAR表示指示的是另外一个段或者说全局地址,NEAR表示指示的是本段内部的地址。
到了Win32中,采用虚拟内存,认为内存是平坦的,线性的,等到链接阶段进行符号重定位时才会把真正的地址映射到物理内存地址空间,具有32位的线性地址,没有分段的概念了,但是为了照顾Win16程序员的习惯,FAR和NEAR都被保留了下来,但是它们的意思是一样的,都表示指针(其实不使用它们也可以)。

还有Win32中的LP(Long Pointer)中的L(Long)也是一样的道理。
16位的寻址空间为 64KB,所以有near,far之称

32位的寻址空间为 4GB,地址非常平坦,无near,far

首先这里的far,在32位系统已经废除不用了。它是C/C++语言在16位系统中用以标明指针是个远指针的修饰符。

远指针是说指针所指向的地址已经超出了64K(2的十六次方),所以需要使用DS加偏移量的方法来寻址,而不能直接寻址。其反义的修饰符是near。

举例:

int far fptr;
fptr=(int far
)0xb0000000;

16位PC机的存储器地址是由段地址和偏移地址组合而成,每一段不能超过64k字节地址,因而同一个段内的地址存取,用偏移地址就可以实现,因段地址寄存器所存的段地址是不变的。当用指针时,只16位就够了,这一类就是near指针。当要在另一个段内取数据,就要跨越段,即要指明存取段的段地址和偏移地址,这时段地址寄存器所存段地址要改变,在使用指针指向另一个段内地址时,就要用32位表示,就是far指针了。由此可见,如果你想写在Win16上也能运行的程序,才会涉及到newr、far指针的概念。在Win32上,指针已无near、far的区分。

### 关于 `error redefining nch.0` 的解决方案 在C/C++编程中,当编译器报告类似于“redefining”的错误时,通常意味着某个变量、常量或宏已经在之前的代码中被定义过一次,而现在又尝试再次定义它。这种问题可能由多种原因引起,比如重复的头文件包含或者全局范围内的多次声明。 对于具体提到的 `nch.0` 错误,虽然没有直接的相关引用描述此问题,但从常见的实践来看,这可能是由于以下原因之一: #### 1. **重复定义** 如果程序中有两个地方都试图定义名为 `nch` 或类似的名称,则会出现此类错误。可以通过检查是否有重复的 `#define` 宏定义或其他形式的重复声明来解决问题[^1]。 ```cpp #ifndef NCH_0_DEFINED #define NCH_0_DEFINED typedef unsigned char byte; #endif ``` 上述代码片段展示了如何通过条件编译防止重复定义。这里假设 `nch.0` 可能是一个与字节类型相关的定义,因此使用了一个简单的保护机制以避免重复定义的情况发生。 #### 2. **头文件管理不当** 另一个常见原因是头文件未正确管理。例如,在多个源文件中包含了同一个头文件却没有采取措施阻止重复包含,也可能引发这样的错误。推荐的做法是在每个头文件顶部加入防重复包含的宏定义: ```cpp #ifndef HEADER_GUARD_NCH_H #define HEADER_GUARD_NCH_H // Header file content here... #endif /* HEADER_GUARD_NCH_H */ ``` 这样可以确保即使同一头文件被多次引入到不同的模块里也不会造成实际的内容重复加载。 #### 3. **第三方库干扰** 有时项目的依赖项(如 Windows API 库)会带来一些意想不到的名字空间污染情况。正如第一个引用所指出那样,有时候需要显式地禁用某些默认行为以免影响自己的实现逻辑。 ```cpp #ifndef NOMINMAX #define NOMINMAX 1 // 防止 Windows.h 中重新定义 min/max 函数 #endif #include <Windows.h> #undef far #undef near ``` 尽管这段话主要讨论的是关于 `min`, `max` 这样的关键字冲突处理方法,但对于其他潜在名字冲突同样适用相同的思路——即明确指定哪些外部定义不需要生效。 --- ### 提供一段示范性的修正代码 以下是综合考虑以上几点之后的一个简单例子,展示怎样安全地定义以及使用像 `nch.0` 这样可能存在争议的对象名: ```cpp #ifndef SAFE_TYPEDEF_BYTE #define SAFE_TYPEDEF_BYTE #ifdef _WIN32 #ifndef NOMINMAX #define NOMINMAX 1 #endif #include <Windows.h> #undef far #undef near #else typedef unsigned char byte; #endif namespace safe { const byte nch_0 = static_cast<byte>(0); // 使用更清晰的安全命名方式代替原始 'nch.0' } #endif /* SAFE_TYPEDEF_BYTE */ int main() { std::cout << "Safe definition of nch_0: " << (int)safe::nch_0 << std::endl; } ``` 在这里,我们不仅解决了可能存在的重复定义风险,还改进了对象名称使其更加符合现代编码习惯和风格指南的要求。 --- ### 总结 综上所述,“Redefining” 类型的错误通常是因重复定义引起的。解决办法包括但不限于采用头文件卫士预防多重导入;合理运用条件编译控制特定平台下的特殊需求;最后还要注意排查是否存在来自第三方组件带来的隐秘副作用等问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值