语法困难,出乎意料的输出
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
类型。)
你能告诉我为什么 运行 这两个代码我有不同的输出吗?
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
类型。)