[c] char *와 const char *의 차이점은 무엇입니까?

차이점은 무엇입니까

char* name

상수 문자열 리터럴을 가리키는

const char* name



답변

char*가변 문자 / 문자열에 대한 가변 포인터 입니다.

const char*불변의 문자 / 문자열에 대한 가변 포인터 입니다. 이 포인터가 가리키는 위치의 내용을 변경할 수 없습니다. 또한 컴파일러는 그렇게 할 때 오류 메시지를 표시해야합니다. 같은 이유에서 변환 에이 되지 않습니다.const char *char*

char* const이다 불변 (포인터가 다른 위치를 가리킬 수) 이지만 그 포인트가되는 위치의 내용을 변경할 수는 .

const char* const불변 문자 / 문자열에 대한 불변 포인터 입니다.


답변

char *name

당신이 name가리키는 문자와 그것을 가리키는 문자를 변경할 수 있습니다 .

const char* name

문자를 name가리키는 지점으로 변경할 수 있지만 해당 지점 의 문자를 수정할 수는 없습니다.
수정 : 포인터는 변경할 수 있지만 ( https://msdn.microsoft.com/en-us/library/vstudio/whkd4k6a(v=vs.100).aspx 를 가리키는 문자 는 변경할 수 없습니다 . “예제”참조 ). 이 경우 지정 자는 별표가 아닌에 적용됩니다 .nameconstchar

MSDN 페이지 및 http://en.cppreference.com/w/cpp/language/declarations 에 따르면 constbefore *는 decl 지정자 시퀀스의 일부이고 constafter *는 선언자의 일부입니다.
선언 지정자 시퀀스 뒤에 여러 선언자가 올 수 있으므로 as 및 as을 const char * c1, c2선언합니다 .c1const char *c2const char

편집하다:

주석에서 포인터가 문자열 리터럴을 가리킬 때 두 선언의 차이점에 대해 질문하는 것 같습니다.

이 경우 정의되지 않은 동작을 초래할 수 있는 지점 을 가리키는 문자를 수정 하면 안됩니다 . 문자열 리터럴은 읽기 전용 메모리 영역 (구현 정의)에 할당 될 수 있으며 사용자 프로그램은이를 수정해서는 안됩니다. 이렇게하면 정의되지 않은 동작이 발생합니다. name

따라서이 경우 (문자열 리터럴 사용)의 유일한 차이점은 두 번째 선언이 약간의 이점을 제공한다는 것입니다. 컴파일러는 두 번째 경우에서 문자열 리터럴을 수정하려고 할 때 일반적으로 경고를 표시합니다.

온라인 샘플 예 :

#include <string.h>
int main()
{
    char *str1 = "string Literal";
    const char *str2 = "string Literal";
    char source[] = "Sample string";

    strcpy(str1,source);    //No warning or error, just Undefined Behavior
    strcpy(str2,source);    //Compiler issues a warning

    return 0;
}

산출:

cc1 : 오류로 취급되는 경고
prog.c : 함수 ‘main’에서 :
prog.c : 9 : 오류 : ‘strcpy’의 인수 1을 전달하면 포인터 대상 유형에서 한정자를 버립니다.

컴파일러는 두 번째 경우에는 경고하지만 첫 번째 경우에는 경고하지 않습니다.


답변

char mystring[101] = "My sample string";
const char * constcharp = mystring; // (1)
char const * charconstp = mystring; // (2) the same as (1)
char * const charpconst = mystring; // (3)

constcharp++; // ok
charconstp++; // ok
charpconst++; // compile error

constcharp[3] = '\0'; // compile error
charconstp[3] = '\0'; // compile error
charpconst[3] = '\0'; // ok

// String literals
char * lcharp = "My string literal";
const char * lconstcharp = "My string literal";

lcharp[0] = 'X';      // Segmentation fault (crash) during run-time
lconstcharp[0] = 'X'; // compile error

// *not* a string literal
const char astr[101] = "My mutable string";
astr[0] = 'X';          // compile error
((char*)astr)[0] = 'X'; // ok


답변

어떤 경우에도 해당 문자열 리터럴에 대한 포인터가 char *또는 로 선언되는지 여부에 관계없이 문자열 리터럴을 수정할 수 없습니다 const char *.

그러나 포인터가 포인터이면 const char *지정된 값을 수정하려고하면 컴파일러에서 진단을 제공해야 하지만 포인터가 그렇지 않으면 컴파일러에서 진단을 제공해야합니다 char *.


답변

사례 1 :

char *str = "Hello";
str[0] = 'M'  //Warning may be issued by compiler, and will cause segmentation fault upon running the programme

위의 설정은 메모리의 읽기 전용으로 플래그가 지정된 프로그램의 이진 이미지에 하드 코딩 된 리터럴 값 “Hello”를 가리 키도록 str을 설정합니다.이 문자열 리터럴의 모든 변경은 불법이며 세그먼트 오류를 ​​발생시킵니다.

사례 2 :

const char *str = "Hello";
str[0] = 'M'  //Compile time error

사례 3 :

char str[] = "Hello";
str[0] = 'M'; // legal and change the str = "Mello".


답변

원하는 경우 실제로 변경할 수있는 첫 번째는 변경할 수 없습니다. const정확성 에 대해 읽으십시오 (차이에 대한 좋은 가이드가 있습니다). 다시 char const * name지적 할 수없는 곳도 있습니다.


답변

문제는 차이점은 무엇입니까

char *name

상수 문자열 리터럴을 가리키는

const char *cname

즉 주어진

char *name = "foo";

const char *cname = "foo";

둘 사이에는 큰 차이가 없으며 둘 다 올바른 것으로 볼 수 있습니다. C 코드의 오랜 유산으로 인해 문자열 리터럴의 유형은 char[]not const char[]이며 인수를 수정하지 않은 경우에도 char *대신 대신 허용 하는 이전 코드가 많이 const char *있습니다.

일반적으로 (2)의 주요 차이점이다 *cname또는 cname[n]유형을 평가한다 lvalues const char반면, *name또는 name[n]타입 lvalues으로 평가하게 char하고, 수정 lvalues . 할당 대상이 수정 가능한 lvalue가 아닌 경우 진단 메시지를 생성하려면 적합한 컴파일러가 필요합니다 . 유형의 lvalue에 할당 할 때 경고가 발생하지 않아도됩니다 char.

name[0] = 'x'; // no diagnostics *needed*
cname[0] = 'x'; // a conforming compiler *must* produce a diagnostics message

컴파일러는 두 경우 모두 컴파일을 중지 할 필요 가 없습니다 . 할당에 대한 경고 를 생성하는 것으로 충분합니다 cname[0]. 결과 프로그램이 올바른 프로그램이 아닙니다 . 구성의 동작은 정의되어 있지 않습니다 . 충돌하거나 더 나빠질 수 있으며 메모리에서 문자열 리터럴을 변경할 수 있습니다.