C/C++关于版本兼容的方法.txt

引言
编程多了,常常有些感触.笔者发现在windows下很多结构都有一个dwSize来表示这个结构多大,实际上这个成员是用来进行版本兼容的.
最典型的一个结构就是OPENFILENAME.这个结构用在了打开文件对话框.里面的第一个成员lStructSize就是用来存放结构的大小.使用在不同的环璄下
_WIN32_WINNT > 0x0500 时和不定义这个宏sizeof(OPENFILENAME)会不一样的那么lStructSize就会不一样,这样windows内部根据这个成员来得知程序运行的版本.
所显示出的对话框就会不相同.这些都是大家共知的啦,笔者谈了这些只是想引入一个话题:我们如何来进行代码的兼容性.
正题
我们先来看如下的一个例子.
a.h
typedef struct tagOPTION
{
   DWORD dwSize;
   DWORD AAA;
   DWORD BBB;  
   DWORD CCC;
}OPTION;

比如这是我定义的一个结构可以进行一些功能的设置.
通过一个结构的指针传给我写的一个引出函数 HRESULT SetOption(OPTION *);
我在代码里判断结构大小如果大小==sizeof(OPTION)则进行操作,否则返回一个错误代码.
在代码用了一些时间后我们需要对这个结构进行扩充,但要求对以前的这个版本兼容.由于这个头文件是给了别的开发者用的.兼容性要考虑到那些开发者生成的可执行代码是可以在新的平台上运行的.
这时我的dwSize就发挥了强大的作用,我只需要判断一下dwSize是不是旧版本的大小,如果是则调用原来的那份代码就可以了.

我的头文件马上变成了

typedef struct tagOPTION
{
   DWORD dwSize;
   DWORD AAA;
   DWORD BBB;
   DWORD CCC;
#ifdef MYSYSTEMVER >= 2
   DWORD DDD;
#endif 
}OPTION;
把旧的SetOption改为SetOption_V1()
新开了一个函数SetOption调用方式相同
HRESUT SetOptiton(OPTION * opt)
{
    if(opt->dwSize == 12)
        return SetOption_V1(opt)
    if(opt->dwSize == sizeof(OPTION))  
.....

}
难道我们一定要在代码中留下MagicNumber吗?
所以再改

#define SIZE_OPTION_V1 12
HRESUT SetOptiton(OPTION * opt)
{
    if(opt->dwSize == SIZE_OPTION_V1 )
        return SetOption_V1(opt)
    if(opt->dwSize == sizeof(OPTION))  
.....

}

代码现在不错了,但是笔者认为代码现在还不理想.因为手动算大小很容易把结构算错.
如果结构成员多了,我们如何来计算呢?,还有SetOption_V1里的代码还有一个sizeof(OPTION)也要改一下
不然原来的代码可不能运行得了.
但是#define OPTION_V1 sizeof(OPTION)会总是新版本的大小.
又想用sizeof()来自动计算结构的大小.
天无绝人之路我还是想到了方法
比如旧版文件采用如下方法编写

typedef struct tagOPTION_CORE
{
   DWORD dwSize;
   DWORD AAA;
   DWORD BBB;  
   DWORD CCC;
}OPTION_CORE;

typedef OPTION_CORE OPTION_V1;
typedef OPTION_CORE tagOPTION_V1;
const SIZE_OPTION_V1  = sizeof(OPTION_V1);
#define OPTION OPTION_V1
如果需要升级则新加如下代码

struct tagOPTIONV2:public OPTION_CORE
{
   DWORD DDD;
};
typedef tagOPTIONV2 OPTIONV2;
const SIZE_OPTION_V2 = sizeof(OPTIONV2)

#undef  OPTION
#define OPTION tagOPTIONV2
#endif

现在我的代码就变成了


HRESUT SetOptiton(OPTION * opt)
{
    if(opt->dwSize == SIZE_OPTION_V1 )
        return SetOption_V1(opt)
    if(opt->dwSize == SIZE_OPTION_V2)  
.....

}


如果还需要升级只需要按以上的代码再新加一个结构.
并且使用者永远只需要使用OPTION结构,并且sizeof(OPTION)总等于他拿到的头文件的版本中结构的大小.

### 宏定义 `#define` 的含义 在 C 和 C++ 中,`#define` 是一种预处理指令,用于定义宏。它允许程序员通过指定一个简单的名称来替代一段代码或常量值,在编译之前替换所有的宏名实例为其对应的值[^1]。 对于 `#define HFILE` 这样的宏定义,如果其右侧是一个字符串字面量或者多个字符串字面量,则这些字符串会被连接成一个单一的字符串。这是因为在 C/C++ 中,相邻的字符串字面量会自动被拼接在一起[^1]。 例如: ```c #define HFILE "file1.txt" "file2.txt" ``` 在这个例子中,`HFILE` 被定义为两个字符串字面量 `"file1.txt"` 和 `"file2.txt"`。当这个宏展开时,这两个字符串会被合并为单个字符串 `"file1.txt""file2.txt"`,最终效果相当于 `"file1.txtfile2.txt"`[^1]。 然而,这种写法通常并不是为了简单地将两个文件名连起来,而是可能有其他用途,比如构建复杂的路径、版本信息或者其他需要动态组合的内容。 ### 字符串字面量的意义和作用 字符串字面量是指程序中的固定文本序列,它们通常是双引号括起来的一系列字符。在代码中使用字符串字面量的主要目的是提供固定的文本数据给程序运行时使用。例如,可以用来表示文件名、错误消息或其他任何静态文本信息[^1]。 当我们在宏定义中包含多个字符串字面量时,这可能是出于以下几个原因: 1. **跨平台兼容性**:某些情况下,不同操作系统对路径分隔符的要求不同(Windows 使用反斜杠 `\`,而 Unix/Linux 使用正斜杠 `/`)。因此可以通过分开书写并依赖于编译器的行为将其正确组装。 ```c #define PATH "C:" "\\" "Users" "\\" "Data" ``` 上述代码会在 Windows 平台上生成有效的路径字符串 `"C:\\Users\\Data"`。 2. **提高可读性和维护性**:较长的字符串可以拆分成较短的部分以便更容易阅读和修改。这样也可以减少因超出某一行长度限制而导致的问题。 3. **条件编译支持**:利用预处理器的功能可以在不同的条件下插入不同的部分到最终形成的字符串里去。 4. **防止意外断行**:有些旧版编辑器可能会因为特定设置而在长行中间强行折行,从而破坏原始意图;采用这种方式能够有效规避此类风险。 5. **资源管理与配置注入**:有时开发者希望把一些外部资源配置项直接嵌入到应用程序内部作为默认选项之一,此时就可以借助这种方法实现灵活调整而不必每次都重新编写源码本身。 综上所述,虽然表面上看只是单纯地把几个独立的小片段粘合到了一起形成一个新的整体对象而已,但实际上背后隐藏着许多深层次的设计考量和技术细节值得我们深入探讨学习。 ```c #include <stdio.h> #define FILE_PATH_PART1 "path/to/" #define FILE_NAME "example" int main() { const char *filePath = FILE_PATH_PART1 FILE_NAME ".txt"; printf("File Path: %s\n", filePath); return 0; } ``` 上面这段小程序展示了如何利用宏定义技巧创建完整的文件路径字符串,并打印出来验证结果是否符合预期。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值