语法困难,出乎意料的输出

grammatical difficulties, unsuspected output

你能告诉我为什么 运行 这两个代码我有不同的输出吗?

    void UART_OutString(unsigned char buffer[]){
    int i;
    while(buffer[i]){
        UART_OutChar(buffer[i]);
        i++;
    }
}

    void UART_OutString(unsigned char buffer[]){
  int i = 0;
  while(buffer[i]){
     UART_OutChar(buffer[i++]);
  }
}

问候,Genadi

为了它的价值,我将其实现为

void UART_OutChar(unsigned char c);

void UART_OutString(unsigned char buffer[]){
    for(unsigned char *p = buffer; *p; p++) {
        UART_OutChar(*p);
    }
}

完全避免单独的计数器变量。

初始化局部变量总是一个好主意,尤其是在 C 语言中,您应该假设没有为您做任何事情(因为通常情况就是这样)。受管制的语言不允许您这样做是有原因的。

我相信读取未分配的变量会导致未指定的行为(实际上 C 不知道那里没有任何东西,只会抓住任何东西),这意味着它是完全不可预测的。

这也可能导致各种问题,因为你随后用它索引一个数组,C 不会阻止你索引一个超出范围的数组,所以如果随机 i 值 C 恰好抓取更大比数组的大小那么你将在 buffer[i] return 中遇到未定义的行为。这一个可能特别讨厌,因为它可能导致任何类型的内存读取/分段错误使您的程序崩溃,具体取决于它决定读取的内容。

因此未分配 i = 随机行为,然后您可以通过使用该 i 值来索引您的数组来获得更多随机行为。

我相信这是一个坏主意的所有原因。在 C 中,特别要注意这样的事情,因为它通常允许您编译和 运行 您的代码。

初始化 i 和使用@AKX 的答案中的解决方案都是很好的解决方案,尽管我认为这会更好地回答你为什么 return 不同的问题。真正的答案是第一种方法 returns 完全随机

您没有在第一种情况下初始化 i 变量,因此这是一个无趣的打字错误,您的编译器应该警告您...


话虽如此,我们可以应用 KISS principle 并以尽可能最易读的方式重写整个代码,一个 for 循环,其本质使得很难忘记初始化循环迭代器:

void UART_OutString(const char* buf[]){
  for(int i=0; buf[i]!='[=10=]'; i++){
     UART_OutChar(buffer[i]);
  }
}

事实证明,最易读的方式通常也是最快的方式。

(但是,int 在某些低端系统上可能效率低下,因此如果您只使用长度为 255 或更短的字符串没问题,uint8_t i 将是更好的选择。嵌入式系统不应该使用 int 并且总是使用 stdint.h 类型。)