【问题标题】:Difference between char and char*char 和 char* 的区别
【发布时间】:2021-03-25 14:53:10
【问题描述】:

我通过做微控制器项目自学 C++。我目前的项目是使用一对或 Adafruit Feather 数据包无线电。无线电数据包的库函数需要一个 C 风格的字符串(我相信),我理解它是一个字符数组。

我已经设置了一个枚举来反映接收器的各种操作,并希望将该状态发送回发送器。所以我想把一个枚举变成一个字符数组。

在谷歌搜索将枚举转换为字符数组的方法中,最简单的(对我来说理解)是将枚举变量传递给一个带有 switch 语句的函数,该语句将返回一个字符字符串。但是当我尝试将返回值放入我的 char 数组时,我收到错误“从 'char*' 到 'char' [-fpermisive] 的无效转换”。我也一直在努力理解数组和指向数组的指针,这在我的脑海中仍然很模糊。

这是我的代码的一些 sn-ps,我希望它们能充分展示我正在尝试做的事情。

...来自我的主要功能

  BLINKING_RIGHT, //0
  BLINKING_LEFT,  //1
  FLASHING,       //2
  SHOWING_BATTERY,//3
  NONE            //4
};

...以及处理要发送的枚举的两个函数

void SendStatus()
{
  char data[20] {EnumToString(currentAction)};     //This is the line showing the error
  //itoa (data,static_cast<int>(currentAction),10);
  //data[0]=static_cast<uint8_t>(currentAction);
  //data[1]=0;
  rf69.send(data, sizeof(data));
  rf69.waitPacketSent();
  Serial.println("Sent a reply");
}//end_function SendStatus()

char* EnumToString(CurrentAction inputEnum)
{
  char *statusString;
  switch(inputEnum)
  {
    case 0:
      statusString = "BLINKING_RIGHT"; //0
      return statusString;
      break;
    case 1:
      statusString = "BLINKING_LEFT";  //1
      return statusString;
      break;
    case 2:
      statusString = "FLASHING";       //2
      return statusString;
      break;
    case 3:
      statusString = "SHOWING_BATTERY";//3
    case 4:
      statusString = "NONE";           //4
      return statusString;
      break;
    default:
      return "EnumToString: Invalid enum";
  }
}

我想帮助解决这个问题,更重要的是,帮助理解 char* 类型和 char 类型之间的区别。

【问题讨论】:

  • 关键是知道* 的含义。您正试图返回一个指向字符的指针,但这也行不通。这是因为您的指针应该指向的“事物”不再存在。输出参数会更好。
  • 要了解char和char指针的区别,请阅读stackoverflow.com/questions/10186765/… and and stackoverflow.com/questions/5727/…
  • 有一百万个关于 C++ 及其类型的教程和资源。请阅读其中任何一个。如果您不知道 char 和 char* 之间的区别,那么您研究 C++ 指针的时间不会超过 5 分钟。请珍惜我们的时间。
  • 为什么在每个return 之后都放一个break?它完全是多余的,任何好的编译器都会警告你它是死代码。

标签: c++ arrays enums


【解决方案1】:

这一行:

char data[20] {EnumToString(currentAction)};

是错误的,因为它使用数组初始化来用字符串 (char*) 初始化 char 数组的第一个元素(char 类型的第一个元素)。你想做的是这样的:

char data[20];
strcpy(data, EnumToString(currentAction));

或者简单地说:

char *data = EnumToString(currentAction);

后者不涉及任何类型的复制,效率对微控制器很重要。

虽然我们关注的是效率,但将顺序枚举值映射到字符串的规范方法是使用数组,这比重复分支的效率要高几个数量级:

// stored as read-only data in the .hex file
static char *names[] = { "BLINKING_RIGHT", "BLINKING_LEFT", "FLASHING", "SHOWING_BATTERY", "NONE" };

// later
const char *data = names[currentAction];

【讨论】:

  • 我希望一个好的优化器从交换机生成一个跳转表。但即使只是因为简单,数组也更好。
  • 如果你把一个指针指向一个字符串,你最好有办法确保字符串在你需要的时候保持有效。
【解决方案2】:

char和char*的区别

char 是一个字符对象。字符是数字。数字值对一些文本字符进行编码(在固定宽度字符编码中;一个 C++ 字符在可变宽度 unicode 编码中表示一个“代码单元”)。

char* 是一个指针对象。它特别是指向char 对象的指针。指针对象指向内存中的另一个对象 - 如果为 null,则不指向任何对象,如果指针无效,则指向对象所在的内存。指针也是迭代器,递增指针使其指向数组的连续元素。


char data[20] {EnumToString(currentAction)};     //This is the line showing the error

data 是一个包含 20 个 char 类型对象的数组。 {expr} 用表达式初始化数组的第一个元素。在您的情况下,表达式是对EnumToString 的调用。因此,您尝试使用函数返回的char* 对象初始化char 对象。 C++ 的类型系统可以保护你免受这个明显的错误。

假设您可以选择发送少于 20 个字节,一个潜在的简单解决方案是完全避免使用本地数组:

std::string_view str = EnumToString(currentAction);
rf69.send(str.data(), str.size());

char *statusString;
statusString = "BLINKING_RIGHT"; //0

这在 C++ 中是不正确的。字符串字面量是 const char 的数组,它们不能转换为指向非常量 char 的指针(C++11 起)。

简单的解决方法是将变量和返回类型更改为const char*。也就是说,使用std::string_view 可能更可取,因为这样调用者不需要在运行时通过搜索空终止符来计算字符串的长度。

【讨论】:

    【解决方案3】:

    char(或任何 T)是一个值。

    char*(或任何 T*)是一个指针(指向另一个值的值,即地址)。

    请记住指向第 0 个元素的指针所呈现的数组(char[] 或任何 T[])。 char* 的变量可以指向数组的一个元素(在特殊情况下指向第一个元素)。

    【讨论】:

    • 另外注意:指针也是对象。
    猜你喜欢
    • 2013-03-22
    • 2011-11-25
    • 2012-04-07
    • 1970-01-01
    • 2017-04-02
    • 2014-10-28
    • 2011-12-14
    • 1970-01-01
    相关资源
    最近更新 更多