c操纵指向char数组的指针,混乱

时间:2017-02-05 08:27:30

标签: c++ arduino

我编写了一些代码来操作指向char数组的指针,用于格式化arduino pro mini的NMEA RMC句子的时间和日期,如下所示:

char *UTC = "120435";
char *DATE = "050117";

char TIME[9];
char *ptr = TIME;
char *fieldPtr = UTC;
for (int a = 0; a < 8; a++) {
    *ptr++ = *fieldPtr++;
    if (a == 1 || a == 3) {
        *ptr = ':';
        ptr++;
    }
}
*ptr = '\0';
Serial.print("TIME: ");   
Serial.println(TIME);     //output: "12:04:35"  //-OK

char date[9];
ptr = date;
fieldPtr = DATE;
for (int a = 0; a < 8; a++) {
    *ptr++ = *fieldPtr++;
    if (a == 1 || a == 3) {
        *ptr = '.';
        ptr++;
    }
}
*ptr = '\0';
Serial.print("TIME: ");
Serial.println(TIME);        //output: "d"  //whatever follows DATE
Serial.print("date: ");
Serial.println(date);        //output: "05.01.17"  //-OK

第二轮中TIME的输出似乎是内存中DATE之后的某个字符。

有人可以帮我解释一下发生了什么吗?

2 个答案:

答案 0 :(得分:3)

你的循环迭代太多了。它必须复制长度为6的输入字符串,并插入两个附加字符。但这并没有改变输入长度。将您的循环更改为:

for (int a = 0; a < 6; a++) {
   ...

答案 1 :(得分:3)

您正在数组边界之外进行读写。

看看这部分:

for (int a = 0; a < 8; a++) {
    *ptr++ = *fieldPtr++;

在第一个循环中,您可以通过UTC访问fieldPtr。内存UTC看起来像:

'1' '2' '0' '4' '3' '5' '\0'

因此当a0时,您阅读1,当a1时,您会阅读2,依此类推。像:

'1' '2' '0' '4' '3' '5' '\0' 
 ^   ^   ^   ^   ^   ^   ^   ^
a=0 a=1 a=2 a=3 a=4 a=5 a=6 a=7

对于a=7,您在数组外读取这是非法的(即未定义的行为)。

对于书写部分,它或多或少是相同的。除了你有两个额外的ptr增量。所以写作是:

TIME[0] TIME[1] TIME[2] TIME[3] TIME[4] TIME[5] TIME[6] TIME[7] TIME[8]
 ^       ^       ^       ^       ^       ^       ^       ^       ^       ^
a=0     a=1     a=1     a=2     a=3     a=3     a=4     a=5     a=6     a=7

再次 - 当你在a=7之外写TIME时。事实上,你在循环之后再写一次:*ptr = '\0';

所有在一起&#34;未定义的行为&#34;。

当你有未定义的行为时,从语言的角度来看,讨论发生的事情是没有意义的。

但是,您可以分析特定系统上发生的情况。可能是当您在第二个循环中写入DATE并在DATE数组外写入时,写入的数据可能会以TIME结尾,从而破坏原始值,从而获得打印错误。再次 - 注意这将是系统特定的。在我的系统上,尽管存在未定义的行为,但您的代码会产生预期的输出。

要解决问题,请参阅@PaulOgilvie的答案

由于您正在处理小的固定大小的输入字符串,避免所有指针内容的替代解决方案可能是:

  char *UTC = "120435";
  char TIME[9];
  if (strlen(UTC) == 6)
  {
      sprintf(TIME, "%c%c:%c%c:%c%c", UTC[0], UTC[1], UTC[2], UTC[3], UTC[4], UTC[5]);
      printf("%s\n", TIME);
  }
  else
  {
    printf("wrong format\n");

    // .... add error handling here ....
  }