1

我想我失去了我的全部 C++ 知识......

我想要的是以正确(可读)的方式初始化 2D unsigned char 数组:我的方法:

#define RADIO_ONOFF 0
#define RADIO_P1 1
#define RADIO_P2 2
... 

#define NR_OF_CODES = 5
#define CODE_LENGTH = 10

#1:

unsigned char** codes = new unsigned char*[NR_OF_CODES];
codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH]{ 9,180,88,11,33,4,0,255,64,191 }; //     does not work
...

#2:

unsigned char ICODES[NR_OF_CODES][CODE_LENGTH];
ICODES[RADIO_ONOFF] = { 9,180,88,11,33,4,0,255,64,191 };  // same as above
...

#3:

class Test {
  private:
    unsigned char data[CODE_LENGTH];

  public:
    Test(unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10);

    unsigned char* getData(void);
};

Test::Test(unsigned char a1, unsigned char a2, unsigned char a3, unsigned char a4, unsigned char a5, unsigned char a6, unsigned char a7, unsigned char a8, unsigned char a9, unsigned char a10) {
  this->data[0] = a1;
  this->data[1] = a2;
  this->data[2] = a3;
  this->data[3] = a4;
  this->data[4] = a5;
  this->data[5] = a6;
  this->data[6] = a7;
  this->data[7] = a8;
  this->data[8] = a9;
  this->data[9] = a10;
}

unsigned char* Test::getData(void) {
  return data;
}

void setup() {

  test[RADIO_ONOFF] = new Test( 9,180,88,11,33,4,0,255,64,191 );
  test[RADIO_P1] = new Test( 9,180,88,11,33,4,0,255,64,192 );
  ...
}

#4

const unsigned char RADIO_ONOFF[]  = { 9,180,88,11,33,4,0,255,64,191 };
const unsigned char RADIO_P1[]     = { 9,180,88,11,33,4,0,255,64,192 };
...

我收到#1 和#2 的错误消息:(代码应该为 Arduino 编译,它需要一个设置函数)

在函数'void setup()'中:revTest:58:错误:'{'令牌revTest:58之前的预期主表达式:错误:预期';' '{' 标记之前

好的 - 我的问题:

对我来说 - #3 和 #4 很好读。#3 的努力是最高的 - 但我认为如果我想在 switch 语句中使用数组,这是最快的方法。- 真的?

我认为#1和#2中的数组初始化应该这样工作????

非常Arduino特定:

我不确定必须在 setup() 内部定义什么以及应该在 setup() 之外定义什么。静态初始化和全局外部,动态内部还是什么?

我对 Arduino 的 PROGMEM 很感兴趣——我认为在这种情况下不值得付出努力。我是对的?(我想我会有大约 50 个不同的代码......)

谢谢!

4

2 回答 2

2

在回答您的问题之前,让我们看看解决方案 1 和 2 出了什么问题。

解决方案 1 和 2 的问题在于您使用的是初始化程序(即 `{} 语法),而您的编译器需要一个赋值表达式。

初始化语法只能在声明变量的地方使用。粗略地说,初始化应该理解为变量一构造就给它一个值。赋值应该理解为给已经在别处构造的变量赋值。

所以当你这样做时:

unsigned char** codes = new unsigned char*[NR_OF_CODES];

你正在做初始化。您正在将变量初始化codes为新分配的指针数组unsigned char

在下一行,你告诉编译器你正在做一个赋值。您正在使用=符号并分配 to codes,这是在上一行声明的 - 编译器将此视为分配。

codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH] ... 

但是,紧接着,您尝试使用初始化语法。

你的编译器在抱怨,因为它读到了这个:

codes[RADIO_ONOFF] = new unsigned char[CODE_LENGTH] ... 

作为一个完整的表达。当您分配 CODE_LENGTH 字节数组并将其分配RADIO_ONOFFcodes.

它希望你用分号停在那里,但你继续并添加了 initalisation syntax {}。它不明白,因为您将分配和初始化混合在一起 - 这是两件不同的事情。这就是为什么你会从编译器中得到“我期望一个分号”类型错误。

为了回答您的问题,解决方案 3 和 4 都需要很长的路要走。在 C++ 中有更快的方法来初始化二维数组。我也同意之前关于使用uint8_t.

这样的东西会更合适吗?

uint8_t codes[CODE_LENGTH][NR_OF_CODES] = 
                              {{0, 1, 2, 3, 4, 5, 6, 7}, 
                              {0, 1, 2, 3, 4, 5, 6, 7}, 
                              {0, 1, 2, 3, 4, 5, 6, 7}, 
                              {0, 1, 2, 3, 4, 5, 6, 7} };

阅读数组语法的一个好方法是将方括号中的最终(最右边)值[]作为某个数组的大小,然后向后工作。

所以uint8_t codes[CODE_LENGTH][NR_OF_CODES]会解码出一个大小NR_OF_CODES某东西的数组。为了得到那个东西,我们看到uint8_t codes[CODE_LENGTH]了 - 所以它是一个长度NR_OF_CODES为 的数组uint8_t,每个长度为CODE_LENGTH

我希望这会有所帮助。

注意。在回答您关于需要使用命名索引索引数组的评论时 - 没有什么可以阻止您codes通过索引引用单个成员。您可以做的是通过 {0} 初始化整个事物 - 将所有成员初始化为 0 的简写。

您可以单独分配RADIO_ONOFF数组的成员(或任何数组),例如

codes[RADIO_ONOFF][3] = 255;

试试这个例子 - 并注意输出:

  #include <iostream>

  const int NR_OF_CODES = 4;
  const int RADIO_ONOFF = 0;
  const int CODE_LENGTH = 11;

  const unsigned char RADIO_ONOFF_ARR[] = { 180,99,33,11,22,33,55, 22,22,33, 10};

  int main()
  {
    unsigned char codes[CODE_LENGTH][NR_OF_CODES] = {
                                                   {0},
                                                  };
    std::cout << "Before:\n";

    for(int x = 0; x < CODE_LENGTH; x++)
    {
      std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
    }

    codes[RADIO_ONOFF][3] = 3;

    std::cout << "\nAfter:\n";

    for(int x = 0; x < CODE_LENGTH; x++)
    {
      std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
    }

    // or try memcpy 
    memcpy(codes[RADIO_ONOFF], RADIO_ONOFF_ARR, sizeof RADIO_ONOFF_ARR);

    std::cout << "\nAfter Memcpy:\n";

    for(int x = 0; x < CODE_LENGTH; x++)
    {
      std::cout << static_cast<int>(codes[RADIO_ONOFF][x]) << ", ";
    }

    char c;
    std::cin >> c;
    return 0;
  }
于 2013-11-10T11:27:29.683 回答
0

首先,由于这是标记为 C++,我要说没有必要做#define。您现在可以访问具有相同功能但类型安全的静态 const 变量。

以下是 Google C++ 风格指南对大括号列表的看法:

http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Braced_Initializer_Lists

当我不从事已设置样式的项目时,我通常会遵循本指南。另外,我应该提到风格是非常主观的,所以你最终可能会得到各种各样的答案。

另外,不要使用 char,您只想存储字节数据。这就是 uint8_t 的用途。

此外,有关如何初始化数组的所有选项,请参阅此 SO 线程:如何将数组的所有成员初始化为相同的值? 在大多数情况下,由于它们只是保持不变的常量,因此您可以将它们设置为静态常量。

像这样:

static const size_t kMyCodeArraySize = 14;  // an example
static const uint8_t[kMyCodeArraySize] = {1, 2, 3, 4};  // example intialization
于 2013-11-10T10:51:43.713 回答