我已经编写了操作指向 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 后面的某个字符。
有人可以帮我解释一下发生了什么吗?
最佳答案
您正在数组边界之外读取和写入。
看看这部分:
for (int a = 0; a < 8; a++) {
*ptr++ = *fieldPtr++;
在第一个循环中,您通过
UTC
访问 fieldPtr
。在内存中 UTC
看起来像:'1' '2' '0' '4' '3' '5' '\0'
因此,当
a
是 0
时,您读取 1
,当 a
是 1
时,您读取 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
,您在数组之外读取是非法的(即未定义的 bahvior)。对于写作部分,它或多或少是相同的。除了你有两个额外的
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';
所以一起“未定义的行为”。
当您有未定义的行为时,从语言的角度讨论正在发生的事情是没有意义的。
但是,您可以分析特定系统上发生的情况。可能是当您在第二个循环中写入
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 ....
}
关于c++ - c 操作指向 char 数组的指针,困惑,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/42049969/