2017-02-05 1 views
3

내가 아두 이노 프로 미니의 NMEA RMC 문장에서 시간과 날짜를 포맷에 대한 char 배열에 대한 포인터를 조작 작성된 코드, 그래서 같은이 :의C, 혼란

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 다음에 오는 문자로 보입니다.

아무도 내가 무슨 일이 일어나는지 설명해 주시겠습니까?

+0

의'를 < 8 '오버런이 발생합니다.->'a <6' – BLUEPIXY

+0

@BLUEPIXY,'a <7'은 후행'\ 0'을 포함합니다. –

+0

@KeineLust'* ptr = '\ 0'; '외부 루프. – BLUEPIXY

답변

3

배열 경계 밖에서 읽고 쓰고 있습니다. 이 부분에서

봐 : 당신이 fieldPtr 통해 UTC 액세스 첫 번째 루프에서

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

. a1 당신이 등등 2 등을 읽을 때,

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

그래서 a01을 읽어 메모리에 UTC는 것 같습니다. 같은

'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 

그래서 다시 - 당신이 외부 TIME을 쓸 때 a=7. 실제로 루프 이후에 다시 한 번 작성하십시오. *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 .... 
    } 
+0

고맙습니다 : 나는 명백한 것을 보지 못했습니다! –

3

루프의 반복 횟수가 너무 많습니다. 길이 6 인 입력. 자열을 복사하고 두 개의 추가.자를 삽입해야합니다. 그러나 그것은 입력 길이를 변경하지 않습니다. 루프를 다음으로 변경하십시오.

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