2011-11-23 4 views
4

가능한 중복 :
Are string literals const?ANSI C : 문자열 리터럴에 대한 포인터

은 ANSI C에서 다음과 같은 유효합니까?

#include <stdio.h> 

/* This returns "Hans" if arg != 0, "Gretel" if arg == 0 */ 
char* foo(int arg) 
{ 
    return arg ? "Hans" : "Gretel"; 
} 

int main() 
{ 
    char* p_ch; 

    p_ch = foo(1); 
    printf("%s\n", p_ch); 
    p_ch = foo(0); 
    printf("%s\n", p_ch); 

    return 0; 
} 

코드는 GCC/Linux에서 컴파일되어 실행됩니다.

는 MinGW/윈도우는 말한다 :

invalid conversion from `const char*' to `char*' 

MS 비주얼 C/C++ 2008 코드로 괜찮습니다.

  1. char* 변수를 초기화 시점이 아닌 다른 곳에서 리터럴 문자열에 할당 할 수 있습니까?
  2. 문자열 리터럴에 static 할당 클래스가 있음을 읽었습니다. 그들이 정의 된 기능 밖에서 보이지 않는다는 것을 의미합니까?
  3. const 유형에서 const가 아닌 카운터 파트로의 변환이 언제 유효하지 않습니까?
+0

''const char * '를 반환하는 것으로'foo'를 선언 할 것입니다. C++로 컴파일되면 코드가 무효화됩니다. 나는 정확히 왜 설명 할 수있는 표준 전문가가 아니다 ... 나는 GCC가 약간의 경고를 할 것으로 기대했을 것이다. (그러나'-Wall -Wextra'가있는 gcc 4.6도 그렇지 않다.) gcc가 C 코드를 컴파일하고 있기 때문에 –

+0

@Basile. 이 문제는 C에서 _nothing_ 잘못된 것입니다. g ++로 컴파일하면 다른 문제가 될 수 있습니다. 그러나 gcc는 완벽하게 유효한 C 코드를 컴파일하려고 시도하면 분명히 문제가되는 것으로 간주하지 않습니다. "언젠가 C++ 컴파일러로 이것을 컴파일하려고 할 때"new라는 변수 이름을 사용할 수 없다는 경고는 아주 귀찮을 것입니다 :-) – paxdiablo

+1

@BasileStarynkevitch :'gcc -Wwrite-strings'는 적절한 경고. 이것은 C 라이브러리의 일부가이 기능에 의존 할 수 있기 때문에 아마도'-Wextra'의 일부가 아닙니다. 예를 들어'strerror'는 리턴 타입'char *'을 갖지만 문자열 리터럴 배열을 사용하여 구현 될 수 있습니다. –

답변

5

예, 유효한 표준 C입니다. 그러나 문자열 리터럴의 하위 호환성을 위해 char[] 유형이 있기 때문에 유효합니다. 안전을 위해 foo에서 const char*의 반환 값을 만들어야합니다. foo에 의해 반환 된 문자열 중 하나에 쓰면 정의되지 않은 동작이 발생합니다.

컴파일러에서이 문제에 대해 불평하면 실수로 C++ 컴파일러를 사용했을 수 있습니다. C++에서 문자열 리터럴의 유형은 const char []입니다. (당신이 const char*-char*를 변경하는 경우, 프로그램은 마술 유효한 C++ 프로그램도됩니다.)

내가 초기화의 시점에서보다 다른 곳에서 리터럴 문자열에 char* 변수를 할당 할 수 있습니까? 당신은

char *p; 
// do some other stuff 
p = "literal"; 

을 의미

? 예, 가능합니다.

나는 문자열 리터럴에 정적 할당 클래스가 있다는 것을 읽었습니다. 그들이 정의 된 기능 밖에서 보이지 않는다는 것을 의미합니까?

정적 할당과 static 변수를 혼동스럽게합니다. 다른 번역 단위에서 확실히 foo의 결과를 사용할 수 있습니다.

const 유형에서 해당 const가 아닌 카운터 파트로의 변환이 언제 유효하지 않습니까?

명시 적으로 const 오프를 캐스팅하기 위해 당신은 공식적으로 const는 C.에 도입 된 1989 년 이후.

1

MinGW/Windows 컴파일러에서 가져 오는 오류 메시지는이 코드를 C++로 컴파일하는 것이 좋습니다. C 언어의 문자열 리터럴은 char[N] 유형입니다 (C++에서는 const char[N]과 반대입니다). C 언어에서는이 오류 메시지가 표시되지 않습니다. 그럼에도 불구하고 C 문자열 리터럴도 수정할 수 없으므로 문자열 리터럴을 가리킬 때 const char * 포인터를 사용하는 것이 좋습니다.

귀하의 질문 번호 1은 약간 이상합니다. 문자열 리터럴은 무명 개체입니다. 즉 초기화는 문자열 리터럴을 가리키는 포인터를 직접 만드는 유일한 방법입니다. 다른 방법은 없습니다. 나중에 비 const 포인터를 다른 비 const 포인터에 복사 할 수 있습니다. 이러한 포인터를 통해 문자열 리터럴에 아무 것도 쓸 수 없다는 것을 기억하십시오. 문자열 리터럴은 수정할 수 없습니다.

귀하의 질문 2도 약간의 의미가 있습니다. '공개 설정'은 이름이 인 속성입니다. 문자열 리터럴은 무명 개체입니다. 그들은 어디에도 보이지 않는다. 그들은 이름이 없으므로 보이지 않을 수 있습니다. 이름이 없으므로 문자열 리터럴을 "잡아"붙잡는 유일한 방법은 포인터 초기화 중에 포인터를 연결하는 것입니다 (예제에서와 같이). 시정은 전혀 상관이 없습니다. 문자열 리터럴은 실제로 정적 저장 기간을 가지며, 이는 그들이 "영원히 산다"는 의미입니다. 프로그램이 실행되는 동안 존재합니다. 귀하의 예에서 문자열 리터럴 "Hans""Gretel"foo 종료 후에도 계속 나타나며, 이는 foo에 의해 반환 된 포인터가 유효 함을 의미합니다.

질문 3에 대한 답은 const 포인터에서 C 언어로 존재하지 않는 비 const 상응하는 항목으로의 암시 적 변환입니다. 즉, 항상 유효하지 않습니다. 이러한 변환을 수행하려면 명시 적 형변환을 사용해야합니다.

관련 문제