替换 C 代码宏并在C++代码中定义常量

Replacing C code macros and defining constants in C++ code

本文关键字:代码 定义 C++ 常量 替换      更新时间:2023-10-16

我问题的要点:我的项目由 C 和 C++ 文件组成,一些字符串常量(它们在项目的 C 部分中硬编码,带有#define)需要通过 USB 连接到计算机,但是如果我连接两个或多个相同类型的设备,它们会停止响应,因为这些常量相同。此问题的解决方案是从C++文件中动态分配这些常量,以便C++代码中的变量可以到达使用这些值的 C 部分。

我现在拥有的:值在 C 标头中定义为#define IDENTIFIER VALUE(硬编码),其中两个VALUE都是C的原始常量,int0x1234char数组像"Some string"。例如:

#define IDENTIFIER1 0x1234
#define IDENTIFIER2 0x5678
#define IDENTIFIER3 "Some string"
#define IDENTIFIER4 "Another string"

我知道 C 中的方法将这些标识符与其他宏(如LOBYTEHIBYTE)一起使用,值也会传递给一些函数。

我尝试通过将字符串defines替换为包装在#ifndef中的变量定义来解决此问题static cast char[]但编译器注意到标识符正在初始化某些函数中的非常量变量或作为参数传递。

我成功地编译了将定义字符串从#define IDENTIFIER VALUE更改为static const unsigned char IDENTIFIER[] = VALUE;的代码,但我仍然需要用 C++ 定义它们。

但是,我很难定义十六进制数,例如0x1234.我发现了其他问题,包括与我的问题相关的问题,到目前为止,我尝试通过以下方式定义十六进制值(发现uint8_t只是无符号字符的 typedef,还发现了一些关于将数字转换为unsigned char的问题以及有关强制转换类型的一些问题的答案):

static uint8_t IDENTIFIER[] = {0x12, 0x34, 0};
static const uint8_t IDENTIFIER[] = {0x12, 0x34, 0};
static const uint8_t IDENTIFIER[] = (uint8_t*)0x1234;
static const uint16_t identifier_int = 0x1234;
static const unsigned char IDENTIFIER[3] = identifier_int;

有一个使用标识符作为参数的函数,它的原型看起来像这样:

void foo (uint8_t *bar, /*other arguments*/);

后来这样称呼:

foo(IDENTIFIER, /*other arguments*/)

我想要实现的:值应该在C++代码中定义,其中应该使用某种方法将这些值传递给 C 代码。

问题:

  1. 将值从C++代码传递到 C 代码的最佳方法是什么?有哪些替代方案?

如果我能提高我的问题的清晰度,请告诉我!

非常感谢@AhmedMasud帮助我更清楚地定义我的问题,并提供一些澄清问题的提示。

应该在C++代码中定义,其中应该使用一些方法 将这些值传递给 C 代码,然后定义它们。

您当然可以在一般意义上执行此操作,但是要使其与现有 C 代码一起使用将需要对该代码进行更改。 这些变化显然不是微不足道的。

如果我明白 正确地,宏会更改用于IDENTIFIER的所有位置VALUE在编译之前,

是的,这是一个相当好的描述。

因此我认为不应该使用宏 了。

我的意思是,因为您想在运行时设置值,所以不能使用宏。 这是完全正确的。 在 C 代码中适应这种情况的破坏性最小的方法可能是声明并使用外部变量来保存值。 但是,请注意,您可能需要解决各种各样的问题才能将 C 代码转换为以这种方式工作。

我希望代码看起来像

void setIdentifier(identifier)
{
#ifndef IDENTIFIER
static const unsigned char IDENTIFIER[] = identifier;
#endif
}

据我所知,康斯特应该已经这样做了。

不,它看起来根本不像那样。

首先,你合理地说,你不想使用宏。 在这种情况下,#ifndef IDENTIFIER#endif就没有作用了。

其次,您在函数中声明了变量IDENTIFIER,因此它没有链接。 如果您希望一个函数设置它而另一个函数来读取它,则需要一个外部变量。

第三,由于您需要外部变量,因此无法使用初始值设定项来设置其值。 如果将变量声明为char数组(而不是char *),则需要使用strcpy()或类似函数将参数的字符复制到该数组中。 但是,您可以对数值或指针变量使用简单赋值。

我还不太了解与 C 代码
  1. 的交互C++,将值从 C++ 代码传递到 C 代码的最佳方法是什么?什么 有替代品吗?

在代码中传递值的替代方案几乎相同C++:将值存储在可访问的变量中,或将其作为函数参数传递。 C 没有"方法",但为此,C++方法可以被认为是一种函数。

  1. 分配这些"常量"时应该采取哪些预防措施?我注意到建议使用static const而不是#define,如上所述,在这种情况下使用宏可能不太可能。

这个问题没有意义。 如果你有一个常量,那么你不能给它赋值(注意赋值初始化不同)。 如果要在编译时设置文件范围const或变量的值,可以使用文件范围或static const变量,但正在使用的宏无论如何都已经完成了这一点。 为什么要去所有的工作去改变?

另一方面,如果要在运行时分配给非const变量,则需要非变量。 此外,如果要在一个源文件中分配值,而这些值将从另一个源文件中读取,则需要外部变量(非static)。

  1. C++程序中定义的静态常量会在 C 代码中看到吗?

在文件/命名空间范围内,没有,因为防止这种情况是static上下文中的确切目的。 在函数或方法内部,不,因为函数/方法的局部变量在声明它们的函数/方法之外不可见。 所以,没有。

如果你想要一个函数或方法可以写入的变量,另一个函数或方法可以从中读取,并且至少有一个访问该变量的函数是用 C 实现的,那么你需要一个文件范围的外部变量。 这样的变量是用以下形式的文件范围声明声明给所有用户(C 和 C++):

/* "extern" is essential */
extern int IDENTIFIER1;

这通常放在访问该变量的所有源都包含的头文件中。 此外,项目中只有一个源文件必须定义变量,其代码形式如下:

/*
* either the initializer or the absence of "extern" is essential;
* both together is good form.
*/
int IDENTIFIER1 = 0x1234;

我会从简单地替换宏定义开始

#define IDENTIFIER1 0x1234
#define IDENTIFIER2 0x5678
#define IDENTIFIER3 "Some string"
#define IDENTIFIER4 "Another string"

const auto IDENTIFIER1 = 0x1234;
const auto IDENTIFIER2 = 0x5678;
const auto IDENTIFIER3 = "Some string";
const auto IDENTIFIER4 = "Another string";

之后,如果出现进一步的问题,我会逐步解决它们。