문제

다음 코드가 있습니다.

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    cout << a << ", " << b << endl;
    return 0;
}

이것은 컴파일하고 작동합니다. 인쇄물 bar, bar. 이제 여기서 일어나는 일은 문자열을 복사하지 않는다는 것을 보여주고 싶습니다. 나는 바꾸고 싶다 b 그리고 그것을 보여줍니다 a 또한 변경됩니다. 이 간단한 코드를 생각해 냈습니다.

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;
    b[1] = 'u'; // ← just this line added
    cout << a << ", " << b << endl;
    return 0;
}

… 그러나 그것은 segfaults. 왜요? 흥미로운 점은 다음 수정이 잘 실행된다는 것입니다.

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char b[] = "bar"; // ← declaration changed here
    a = b;
    b[1] = 'u';
    cout << a << ", " << b << endl;
    return 0;
}

왜 이전 것과 같이 segfault가 아닌가? 포인터 스타일과 배열 스타일 문자열 초기화 사이의 중요한 차이가 누락 된 것 같습니다.

도움이 되었습니까?

해결책

문자열 상수를 변경할 수 없습니다. 첫 번째 코드 샘플에서와 같이 포인터 투리어 문자 구문을 사용할 때 얻을 수 있습니다.

이 질문도 참조하십시오. C ++의 문자열 문자가 정적 메모리로 생성됩니까?.

다른 팁

이것을 쓸 때 :

char *b = "bar";

컴파일러는 익명 (이름이없는) 메모리 영역을 할당하여 문자열 문자 "막대"를 저장합니다. 문자열 리터럴을 수정할 수 없으므로 컴파일러 (링커 및 운영 체제의 도움으로)는 문자열을 쓰기로 보호되는 실행 프로그램의 메모리 공간의 일부에 문자열을 놓습니다. 이를 수정하려고하면 운영 체제가이를 잡아 프로그램을 세분화 오류로 만듭니다.

(코드는 C가 아닌 C ++이지만이 질문과 관련이 없습니다.)

당신이 쓸 때 :

char *foo = "bar";

실제로 발생하는 것은 "막대"가 메모리의 읽기 전용 세그먼트에 저장된다는 것입니다. 그러므로 그것은 불변입니다. 읽기 전용 세그먼트를 수정하려고하므로 segfault를 얻습니다.

또한 포인터의 값을 인쇄하여 'A'가 변경되었음을 보여줄 수 있습니다.

#include <iostream>
using namespace std;
int main()
{
    char* a = "foo";
    char* b = "bar";
    a = b;

    cout << (void*)a << ", " << (void*)b << endl;
}

이것은 'a'와 'b'가 지적한 주소를 인쇄합니다.
연산자 <<이 'char*'에 과부하되어 다른 포인터가 주소를 인쇄 할 수 있도록 'char*'가 과부하되므로 'void*'로 캐스트해야합니다.

이론적으로 문자열 문자는 숯*에 할당 할 수 없으며 'const char*'만 할당 할 수 없어야합니다. 그런 다음 Seg Faulting 코드를 작성하기 전에 컴파일러가 중지됩니다.

이 차이는 아마도 컴파일러에 따라 다릅니다. 포인트를 시연하려면 Malloc을 사용하여 버퍼를 할당 한 다음이 버퍼에 문자열을 복사하고 더 이상 문자열이 필요하지 않을 때 무료 사용을 잊지 마십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top