문자열 포인터 질문

조회수 534회

두 코드의 차이점이 궁금합니다.

1.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void hstrrev(char* str);

int main() {

    char str[100] = "program을 실행하기 전에 compile를 해야 한다.";

    puts(str);

    hstrrev(str);

    puts(str);

    return 0;
}

void hstrrev(char* str) {

    char* pstr;
    char* s = str;

    pstr = (char*)malloc(strlen(str) + 1);
    pstr = pstr + strlen(str);

    *pstr = NULL;
    pstr--;

    while (*s) {
        if (*s & 0x80) {
            *pstr-- = s[1];
            *pstr-- = s[0];
            s += 2;
        }
        else {
            *pstr-- = *s++;
        }
    }
    strcpy(str, pstr);
    free(pstr);
}

2.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void hstrrev(char* str);

int main() {

    char str[100] = "program을 실행하기 전에 compile를 해야 한다.";

    puts(str);

    hstrrev(str);

    puts(str);

    return 0;
}

void hstrrev(char* str) {

    char* pstr, * p;
    char* s = str;

    pstr = (char*)malloc(strlen(str) + 1);
    p = pstr + strlen(s);

    *p-- = NULL;

    while (*s) {
        if (*s & 0x80) {
            *p-- = s[1];
            *p-- = s[0];
            s += 2;
        }
        else {
            *p-- = *s++;
        }
    }

    strcpy(str, pstr);
    free(pstr);
}

문자열을 한글영어 구분 없이 거꾸로 출력하는 함수 hstrrev에서

1.번 코드에서 함수 hstrrev에서 pstr을 str과 크기가 같게 동적 할당을 하게 한 후 pstr=pstr+strlen(str)을 하게 되면 현재 pstr은 메모리상에서 크기가 4인 포인터 변수가 생성 되고(포인터 변수는 항상 크기 4이기때문에) pstr이 이름없는 메모리(크기가str과 같은)의 시작번질를 가리키게 되는데

이미지

그럼 pstr=pstr+strlen(str)이라고 하면 pstr은 pstr이 가리키는 이름없는 메모리의 끝을 가리 키게 되지 안나요?(이게 질문입니다)

이미지

그후엔 그냥 아래 코드대로 실행 되게 되면 문자열이 거꾸로 출력이 될거라고 예상됬는데 이상한 오류가 뜨더라구요...

오류 내용

Debug Assertion Failed!

Expression:_CrtlsValidHeapPointer(block)

for information on how your program can cause an assertion failure, see the Visual C++ documentation on asserts.

(Press Retry to debug the application)

그럼 이제 2.번 코드에선 위처럼 pstr을 동적 할당 하고나서 다른 포인터 변수하나를 만들어서(p) p=pstr+strlen(str) 라고하게 되면 마찬가지로, 동적 할당한 후 str길이와 같은 이름없는 메모리를 pstr이 가리키게 되는데 p=pstr+strlen(str) 이 식에 의해서 포인터 변수 p는 pstr이 가리키는 메모리의 끝을 가리키게 되고 결국 pstr=pstr+strlen(str)과 다를게 없다고 생각 하였습니다.

이미지

하지만 1.번코드는 오류가 생기고 2.코드는 잘 실행이 되더라구요...

두코드에서 차이점은 포인터 변수 p를 만들어서 pstr이 가리키는 메모리의 끝을 읽냐 아니면 바로pstr에 pstr이 가리키는 메모리의 끝을 읽냐 인 것 같은데 즉,

p=pstr+strlen(str)
pstr=pstr+strlen(str)

이 두 식의 차이를 모르겠습니다.

아직 모르는게 너무도 많고 필력도 안좋아서 항상 수준낮은 질문만 하는 것 같은데 항상 답변 해주시는 분들께 진심으로 감사드립니다!

  • 두 식의 차이점은 전혀 없습니다. 다만 오유는 <2>에서 while문이 끝난후에 pstr++을 해주지 않은것으로 하여 pstr가 생성된 위치와 차이나서 free(pstr)에서 발생하는것입니다. 알 수 없는 사용자 2020.1.17 21:55
  • 답변 감사합니다! 우선 오류는 <2>가 아닌 <1>에서 발생하고 있습니다.<1>과 <2>가 헷갈리신 것같아서 바꿔서 이해해 보려고 했지만 그래도 잘 이해가 가지 않네요 ㅠㅠ 알 수 없는 사용자 2020.1.18 05:02
  • 아아!! 이해 됬습니다! 말씀 하신데로 pstr이 생성된 위치와 마지막에pstr의 위치가 달라서 free함수에서 오류를 뿜은 거였네요! 무슨 말씀인지 다시 읽어보고 생각해보니깐 이해가 됬습니다 정말 감사합니다!! 긴글 읽어주셔서 정말 감사하고 답변도 정말 감사합니다! 어제 동적할당 다시 공부했는데도 문제 해결을 못해서 씁슬하게 누웠는데 일어나자마자 답변보고 해결되서 너무 행복합니다 ㅠ 즐거운 주말되세요~:) 알 수 없는 사용자 2020.1.18 05:08

답변을 하려면 로그인이 필요합니다.

프로그래머스 커뮤니티는 개발자들을 위한 Q&A 서비스입니다. 로그인해야 답변을 작성하실 수 있습니다.

(ಠ_ಠ)
(ಠ‿ಠ)