我目前在STM32平台上参与嵌入式C++开发.我们的团队正在评估模板的使用,以便为各种低级硬件设备参数化驱动程序.
所有有效的模板特化都是事先已知的,因此我们可以在实现文件中明确地给出所有有效的特化(实现和声明分离).事实上,对我们来说,显式专业化非常有用,因为它有助于记录可行的参数集.
// file i2c_dev.h
template<typename traits>
struct i2c_dev
{
public:
static void init();
static void send();
static bool busy();
...
private:
static i2c_transfer periodic_transfer; // class with used-defined constructor
};
// traits class for configuration A
struct i2c_dev_traitsA
{
enum
{
I2Cx_BASE = I2C1_BASE
, PORTx_BASE = GPIOB_BASE
, PORTx_PIN_TX = PB08
, PORTx_PIN_RX = PB09
};
};
// traits class for configuration B, different I2C peripherial and pinout
struct i2c_dev_traitsB
{
enum
{
I2Cx_BASE = I2C2_BASE
, PORTx_BASE …Run Code Online (Sandbox Code Playgroud) 我正在寻找一个合适的算法来构建一个相对较小(最多255个元素)排序的整数数组.目标平台是基于STM32的嵌入式系统.由于存储器是有限的,因此优选就地方法.
我知道显而易见的方法是实现和描述通常的嫌疑人(快速排序,插入sert,shell排序),但是想要问你的经历.更具体地说,我在构建阵列时发现很少有关于性能的信息- 也就是说,不同算法可以使用所有现有元素已经订购的事实.
编辑1: 虽然问题标记为C++,但STL不可用.此外,排序确实发生在内循环内.为了进一步说明,我正在寻找一种特别适合以有效方式构建排序列表的算法.我假设(可能是错误的)必须有专门适合这项任务的算法.这就是问题所在.
编辑2: 当说构建排序列表时,我的意思是列表开始为空,并由16位整数的有界数字(最多255)填充,这些数字没有特定的顺序.必须在存储所有元素后处理该列表.对于处理,必须对列表进行排序,优选地按降序排序.
谢谢,Arne
我目前正在教自己Ada,虽然我可以从解决一些更传统的问题开始.
更具体地说,我尝试计算阶乘n !,而n> 100.到目前为止,我的实施是:
with Ada.Text_IO;
with Ada.Integer_Text_IO;
use Ada.Text_IO;
procedure Factorial is
-- define a type covering the range beginning at 1 up to which faculty is to
-- be computed.
subtype Argument is Long_Long_Integer range 1..100;
-- define a type that is large enough to hold the result
subtype Result is Long_Long_Integer range 1..Long_Long_Integer'Last;
package Result_IO is new Ada.Text_IO.Integer_IO(Result); use Result_IO;
-- variable holding the faculty calculated.
fac : Result := 1;
begin
-- loop over whole range …Run Code Online (Sandbox Code Playgroud) 我需要对定制 HID USB 设备(控制面板上的一些按钮和 LED)驱动程序进行逆向工程。该驱动程序仅在 Windows 上可用,我们需要 *nix 实现。
该设备显然是 HID 设备,尽管不属于特定类别。它提供两个接口,每个接口都有一个中断端点。
我的设置当前涉及在 Ubuntu 主机上运行 Windows 的 VirtualBox,以通过 Wireshark 捕获 USB 流量。该协议相当简单,我已经有了很好的理解。
我在一个简单的 C++ 控制台程序中使用 libusb-1.0 进行原型设计。我已经设法通过发出 SET_REPORT 控制传输来切换 LED,但在通过传输中断接收按钮按下时遇到了困难。
事实上,以下调用将永远阻塞:
unsigned char bytes[8] = { 0 };
int len = 0;
int ret = libusb_interrupt_transfer(handle, 0x81, bytes, 8, &len, 0);
Run Code Online (Sandbox Code Playgroud)
在 Wireshark 中检查生成的 URB 时,它看起来与在 Windows 会话中捕获的等效内容完全相同。但我仍然没有收到设备的回复。
我觉得我缺少一些设置。请注意,设备已正确打开,并且设备提供的两个接口已成功声明。即使在我的 Linux 应用程序中,通过控制传输的输入报告也会出现。
感谢您的指点!阿内
附录一:我想知道在使用时我应该如何指定我想要接收的报告ID libusb_interrupt_transfer()?
附录二:将 Windows 驱动程序发出的请求与 Wireshark 中上述代码生成的请求进行比较时,我没有看到任何差异(URB 中的值相同)。但是,只有当 Windows 驱动程序发出中断传输时才会返回。
在 Wireshark 中检查 Windows 驱动程序通信时,除了各种GET_DESCRIPTOR(...). …
这是一个概念验证问题。我正在设计一个 GUI,用于在飞行模拟应用程序中编辑空中交通参与者的航路点。在当前的概念中,所选航路点的参数显示在一堆文本框中。该输入掩码既充当数据视图又充当编辑掩码。编辑字段后,用户可以:
如果仅需要为新路径点更改某些参数子集,则此设计可以避免重新输入数据。
只有一个问题:在哪里插入路径点?我的答案是“另存为新”按钮上的下拉菜单,其中包含以下菜单项:
最后一项是棘手的。索引位置需要由用户输入,我想避免弹出窗口只要求单个值。
我的想法是:将文本框嵌入到菜单项中。
这种方法在 QT 或 wxWidgets 中可行吗?您对 GUI 设计有何看法?
问候,阿恩
PS:请注意,这一切都处于概念阶段。该小组甚至还没有决定使用哪种 GUI 框架:Qt 或 wxWidgets。
对于客户端和服务器之间交换的UDP包,我想支持两种字符串字段:
cstringuint8_tsize-field的字符串vstring要自我记录我们的包的布局,我想使用简单的结构声明:
struct ABC {
vstring a;
cstring b;
}
Run Code Online (Sandbox Code Playgroud)
并调用重载函数get(char*, vstring& v)和get(char*, cstring&)内部de /序列化函数,如下所示:
void deserialize(const char* bytes, ABC& msg) {
get(msg.a);
get(msg.b);
}
void serialize(char* bytes, const ABC& msg) {
put(msg.a);
put(msg.b);
}
Run Code Online (Sandbox Code Playgroud)
但是,对于用户而言vstring,cstring理想情况下应该像正常一样std::string.
我的第一个想法是简单地进行std::string的民意基础vstring,并cstring使得两个类可以超载解析期间,disriminated而是表现为用户相同.但由于std::string劝阻,我不确定该怎么办.
我正在编写一个模拟程序,并想知道在存储中间结果时是否使用const double是有用的.请考虑以下代码段:
double DoSomeCalculation(const AcModel &model) {
(...)
const double V = model.GetVelocity();
const double m = model.GetMass();
const double cos_gamma = cos(model.GetFlightPathAngleRad());
(...)
return m*V*cos_gamma*Chi_dot;
}
Run Code Online (Sandbox Code Playgroud)
请注意,样本仅用于说明 - 从工程方面来看,它可能没有多大意义.在变量中存储例如cos_gamma的动机是这个余弦在(...)覆盖的其他表达式中多次使用,我觉得代码在使用时更易读
cos_gamma
Run Code Online (Sandbox Code Playgroud)
而不是
cos(model.GetFlightPathAngleRad())
Run Code Online (Sandbox Code Playgroud)
用各种表达方式.现在问题是这样的:因为我希望余弦在代码部分是相同的,我实际上只是作为占位符创建了东西,为了方便起见,我倾向于将它声明为const.是否有关于这是好还是坏的实际意见,或者它最终是否会咬我?编译器是否使用了这些附加信息,或者我是否真的阻碍了编译器执行有用的优化?
阿恩
我正在使用模板来实现从int到enum的范围检查转换。看起来像这样:
template<typename E>
E enum_cast(const int &source);
Run Code Online (Sandbox Code Playgroud)
模板功能或多或少地位于项目的根目录中。当定义一个新的枚举时,可以像这样从配置文件中分配值:
enum ConfigEnum {
ConfigEnumOption1 = 'A'
, ConfigEnumOption2 = 'B'
, ConfigEnumInvalid };
ConfigEnum option = XmlNode.iAttribute("option");
Run Code Online (Sandbox Code Playgroud)
我在使用此枚举的模块的.cpp文件中为此特定枚举类型定义了模板专用化。
template<>
ConfigEnum enum_cast(const int &source) {
switch(source) {
case ConfigEnumOption1 : return ConfigEnumOption1;
case ConfigEnumOption2 : return ConfigEnumOption2;
default return ConfigEnumInvalid;
}
Run Code Online (Sandbox Code Playgroud)
现在,将int分配给枚举变为:
ConfigEnum option = enum_cast<ConfigEnum>(XmlNode.iAttribute("option"));
Run Code Online (Sandbox Code Playgroud)
这样可以确保枚举始终在有效范围内。请注意,我没有始终控制这些枚举,因此这似乎是一个合理且易于配置的解决方案。
无论如何,这一切都很好(尽管我不能保证这里给出的所有代码都是正确的,因为我现在只是从内存中调用它)
问题源于这样一个事实,即在将in分配给枚举时可能不希望在代码库中使用此“ enum_cast”构造。毕竟,这可以通过简单的搜索和替换操作来实施。当然,我不想为所有枚举定义这些专业化知识,而只是为那些目前需要范围检查的人定义。我宁愿在需要时为枚举类型添加模板专业化,而在未定义专业化时使用赋值运算符。
从而:
InternalEnum internal = enum_cast<InternalEnum>(internal_integer);
Run Code Online (Sandbox Code Playgroud)
有效地调用internal = internal_integer。我认为我需要告诉编译器对所有没有专门化的枚举类型使用某种“默认”实现。
我的第一个选择是给原始模板函数一个这样的实现:
template<typename E>
E enum_cast(const int &source) {
E copy = source;
return copy;
}; …Run Code Online (Sandbox Code Playgroud) 这可能是单行答案的候选人.无论如何我想知道..
我正在编写一个简单的循环缓冲区,由于某些原因,这对于我需要使用双精度数组实现它的问题并不重要.事实上,我没有研究其他方法,但是因为无论如何都需要阵列,所以我没有花太多时间寻找替代方案.
template<typename T>
class CircularBuffer
{
public:
CircularBuffer(unsigned int size);
~CircularBuffer();
void Resize(unsigned int new_size);
...
private:
T* buffer;
unsigned int buffer_size;
};
Run Code Online (Sandbox Code Playgroud)
由于我需要动态调整缓冲区大小,因此buffer_size既不const是模板参数也不是模板参数.现在的问题是:
在构造和功能期间,Resize(int)我只要求大小至少为1,尽管大小为1的缓冲区实际上不再是缓冲区.当然,使用简单的双重替代会更合适,但无论如何.
现在当在析构函数中删除内部缓冲区时 - 或者在函数调整大小时 - 我需要删除分配的内存.问题是,怎么样?第一个候选者当然是delete[] buffer;然后再次,如果我已经分配了一个大小为1的缓冲区,即如果指针被获取buffer = new T[0],是否仍然适合调用delete[]指针或我是否需要调用delete buffer;(没有括号)?
谢谢,阿恩
我在执行上的闪存一个STM32微处理器仿真EEPROM,主要是由ST基础上,应用笔记(AN2594 - 在STM32F10x微控制器EEPROM仿真).
其中的基本概述以及相应的数据手册和编程手册(PM0075)非常清楚.但是,我不确定电源输出/系统复位对闪存编程和页面擦除操作的影响.AppNote也考虑了这种情况,但没有说明编程(写)操作中断时到底发生了什么:
0xFF吗?感谢您提供相关文档的提示或指示.
阿恩