【问题标题】:Passing a C string and using it with a local pointer传递 C 字符串并将其与本地指针一起使用
【发布时间】:2019-03-20 21:11:13
【问题描述】:

The Evils of Arduino Strings看这段代码

void PrintString(const char *str) {
    const char *p;
    p = str;
    while (*p) {
        Serial.print(*p);
        p++;
    }
}

我正在考虑减少/压缩它。首先,这似乎是等价的:

void PrintString(const char *str) {
    const char *p;
    p = str;
    while (*p)
        Serial.print(*p++);
}

现在,看前两行,我如何将以下两行结合起来,可以吗?

    const char *p;
    p = str;

我可以这样做吗?

    const char *p = str;

这看起来很可能,但看起来不平衡,因为右侧缺少星号。我试过了,它似乎可以工作,但我想知道它是否正确,并担心我以后会出现一些 hard-to-track-down 运行时错误,进一步向下行。

但是,下面这行显然是错误的(因为它会将指针 p 更改为指向 C 字符串的第一个字符 str 的值给出的位置):

    const char *p = *str;

【问题讨论】:

  • pstr 具有相同的类型。如果类型拼写为“pointer_to_const_char”而不是“const char *”,您是否会有同样的疑问?
  • 如果你想要紧凑:while (*str) Serial.print(*str++);.
  • @Mayur 不,实际上你是对的——我认为这是一个接一个地打印字符串,但那将是一个 ** 输入。 (毕竟看起来Serial.Print 可以从文档中一次性打印一个字符串。)这是一个字符一个字符的打印,所以你的初始版本很好。
  • const char *p = str; ...*看起来不平衡*。您追求的不是平衡的外观,而是类型的正确性。 pchar *str 也是如此。所以没关系。
  • @Greenonline 是的,你不需要局部变量——它可以是整个身体。 (但为了便于阅读,我会将其分成两行。)

标签: c string pointers initialization variable-assignment


【解决方案1】:

这是混淆。原始代码非常清晰,无需更改任何内容。您的更改使其可读性降低。

可以做些什么来稍微增加可读性,这是一个外观上的改变,就是使用 for 循环来代替:

void PrintString (const char *str) 
{
    for(const char* p=str; *p != '\0'; p++)
    {
        Serial.print(*p);
    }
}

或者:

void PrintString (const char *str) 
{
    for(size_t i=0; str[i] != '\0'; i++)
    {
        Serial.print(str[i]);
    }
}

【讨论】:

  • @alk 这个问题使用了一个没有意义的想法。
【解决方案2】:

你可以省略 p 指针的使用,直接使用 str 指针参数,因为它是指向常量内容的指针的副本。

对str指针所做的更改不会影响调用函数时使用的指针,因为指针是按值传递的。

void PrintString(const char *str) {
    while (*str) Serial.print(*str++);
}

【讨论】:

    【解决方案3】:

    如何将while 替换为for。这是我的看法:

    void PrintString(const char *str)
    {
        for(const char* p = str; *p; p++)
            Serial.print(*p);
    }
    

    我认为这也可以:

    void PrintString(const char *str) {
        for(const char* p = str; *p; Serial.print(*(++p)))
            ;
    }
    

    正如其他人所指出的,我们可以将p 替换为str,因为str 是一个本地副本,就像作为函数参数传递的任何其他变量一样。

    void PrintString(const char* str) {
        for( ; *str; Serial.print(*(++str)))
            ;
    }
    

    【讨论】:

      【解决方案4】:
      const char *p = str;
      

      这看起来很可能,但看起来不平衡,因为右侧缺少星号。

      如果您正确分离了上述 sn-p 的元素,它看起来根本不会“不平衡”:

      • const char* 是类型(指向 const 字符的指针)
      • pstr 是变量,都是指针(指向const char

      您可以使用一些非常规的布局来编写上述内容,如下所示:

      const char *  /* Note the lack of a semicolon */
      p = str;
      

      上面的代码最终将p定义为指向char的指针,并带有str的值。

      下面的代码你会得到相同的“结果”

      const char *p;
      p = str;
      

      注意,前者称为“初始化”,而后者称为“赋值”。

      【讨论】:

        猜你喜欢
        • 2023-03-31
        • 1970-01-01
        • 1970-01-01
        • 2013-05-18
        • 1970-01-01
        • 2015-06-03
        • 1970-01-01
        • 2014-11-01
        • 1970-01-01
        相关资源
        最近更新 更多