programing

문자열 리터럴의 "Life-time" (C)

newsource 2022. 8. 9. 23:04

문자열 리터럴의 "Life-time" (C)

다음 함수에 의해 반환된 포인터에 액세스할 수 없는 것은 아닐까요?

char *foo(int rc)
{
    switch (rc)
    {
        case 1:

            return("one");

        case 2:

            return("two");

        default:

            return("whatever");
    }
}

따라서 C/C++의 로컬 변수의 수명은 사실상 함수 내에서만 유지되는 것입니다., , 뒤에 그가 붙으면 그가 됩니다.char* foo(int)종료하면 포인터는 더 이상 아무 의미도 없는 거죠?

지역 변수의 수명이 좀 헷갈리네요.어떤 것이 좋은 설명입니까?

「 」 , 「 」 )입니다.{ ,}가 생성됩니다.

로컬 변수에는 자동 또는 로컬 저장소가 있습니다.작성 범위가 종료되면 자동으로 파기되기 때문에 자동입니다.

단, 여기에는 구현 정의 읽기 전용 메모리에 할당되어 있는 문자열 리터럴이 있습니다.문자열 리터럴은 로컬 변수와 다르며 프로그램 수명 내내 활성 상태로 유지됩니다.이들은 정적 지속시간을 가집니다.

경고 하나 하지!

단, 문자열 리터럴의 내용을 변경하려고 하면 Undefined Behavior(UB; 정의되지 않은 동작)가 됩니다.사용자 프로그램은 문자열 리터럴의 내용을 수정할 수 없습니다.
항상 '아주 좋다'는 말을 이 좋습니다.const스트링 리터럴을 선언하고 있습니다.

const char*p = "string"; 

대신,

char*p = "string";    

에서는 C++를 사용하지 않고 리터럴을 .constC 니 、 C 、 C 니 、 C 。단,을 ", "로 const는 보통 두 번째 경우 문자열 리터럴을 변경하려고 할 때 컴파일러가 경고를 보낸다는 이점을 제공합니다.

샘플 프로그램:

#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 Uundefined Behavior 
    strcpy(str2,source);    // Compiler issues a warning 
 
    return 0; 
} 

출력:

는 에러 : 에러로 취급되고 있습니다.
'의 경우: prog.c: "main"의 경우:
error: "의 하면 포인터 typeprog:9: "strcpy"의됩니다.

컴파일러는 두 번째 케이스에 대해 경고하지만 첫 번째 케이스에 대해서는 경고하지 않습니다.


몇 명의 사용자가 묻는 질문에 답변하려면 여기를 클릭하십시오.

필수 리터럴은 어떤 거래입니까?

즉, 다음 코드가 유효한가요?

int *foo()
{
    return &(2);
} 

정답은 이 코드가 유효하지 않습니다.포맷이 잘못되어 컴파일러 오류가 발생합니다.

예를 들어 다음과 같습니다.

prog.c:3: error: lvalue required as unary ‘&’ operand
     

문자열 리터럴은 l-값입니다.즉, 문자열 리터럴의 주소는 사용할 수 있지만 내용은 변경할 수 없습니다.
기타 리터럴(「」, 「」)은int ,float ,char, 등)은 r-values(C 표준에서는 이러한 표현식의 값이라는 용어를 사용)이며, 그 주소는 전혀 취득할 수 없습니다.


[참조 1]C99 표준 6.4.5/5 "문자열 리터럴 - 의미론":

변환 단계 7에서는 문자열 리터럴 또는 리터럴에서 생성되는 각 멀티바이트 문자 시퀀스에 값 0의 바이트 또는 코드가 부가됩니다.그런 다음 멀티바이트 문자 시퀀스를 사용하여 시퀀스를 포함하기에 충분한 정적 스토리지 기간길이의 배열을 초기화합니다.문자열 리터럴의 경우 어레이 요소는 type char를 가지며 멀티바이트 문자 시퀀스의 개별 바이트로 초기화됩니다.와이드 문자열 리터럴의 경우 어레이 요소는 type wchar_t이며 와이드 문자 시퀀스로 초기화됩니다.

요소의 값이 적절한 경우 이들 배열이 구별되는지 여부는 지정되지 않았습니다.프로그램이 이러한 배열을 수정하려고 하면 동작은 정의되지 않습니다.

유효합니다.문자열 리터럴에는 정적 저장 기간이 있으므로 포인터가 매달리지 않습니다.

C의 경우, 이는 섹션 6.4.5 단락 6에서 의무화된다.

변환 단계 7에서는 문자열 리터럴 또는 리터럴에서 생성되는 각 멀티바이트 문자 시퀀스에 값 0의 바이트 또는 코드가 부가됩니다.그런 다음 멀티바이트 문자 시퀀스를 사용하여 시퀀스를 포함하기에 충분한 정적 스토리지 기간 및 길이의 배열을 초기화합니다.

섹션 2.14.5의 C++에 대해서는 단락 8-11:

통상의 리터럴은 스트링 리터럴이라고도 .8 의 UTF-8 의 UTF-8 의 경우, UTF-8 의 경우는 좁은 스트링 리터럴이라고 . 배열"입니다.const char여기서 n은 아래에 정의된 문자열 크기로 정적 저장 기간(3.7)을 가집니다.

u로 예:9 u u 로 、 로 、 로 9 that ) 。 예를 들어 다음과 같습니다.u"asdf"는 입니다.char16_tA Achar16_t 리터럴의 n" 이며 "array of n" 입니다.const char16_t여기서 n은 다음에 정의된 문자열 크기입니다.저장기간은 정적이며 지정된 문자로 초기화됩니다.의 c-char를 할 수 .char16_t서로게이트 쌍 형식의 문자.

U로 예: U 작 10 10 。 예를 들어 다음과 같습니다.U"asdf"는 입니다.char32_tA Achar32_t 리터럴의 n" 이며 "array of n" 입니다.const char32_t여기서 n은 다음에 정의된 문자열 크기입니다.저장기간은 정적이며 지정된 문자로 초기화됩니다.

11 L로 시작하는 문자열 리터럴. 예를 들어 다음과 같습니다.L"asdf"는 와이드 문자열 리터럴입니다.와이드 문자열 리터럴의 유형은 "array of n"입니다.const wchar_t여기서 n은 다음에 정의된 문자열 크기입니다.저장기간은 정적이며 지정된 문자로 초기화됩니다.

문자열 리터럴은 프로그램 전체에 유효하기 때문에(스택은 할당되지 않습니다) 유효합니다.

또, 스트링 리터럴은 읽기 전용이므로, (좋은 스타일을 위해) 변경하는 것이 좋을지도 모릅니다.foo로.const char *foo(int)

네, 유효한 코드입니다.아래의 케이스 1을 참조해 주세요.적어도 다음 방법으로 함수에서C 문자열을 안전하게 반환할 수 있습니다.

  • const char*문자열 리터럴로 변환합니다.수정할 수 없으며 호출자가 해제할 수 없습니다.다음에 설명하는 해방 문제 때문에 기본값을 반환할 목적으로는 거의 도움이 되지 않습니다.함수 포인터를 실제로 전달해야 하는 경우에는 문자열을 반환하는 함수가 필요할 수 있습니다.

  • char*또는const char*스태틱 char 버퍼로 이동합니다.발신자에 의해 해방되어서는 안 됩니다.이 값은 (항상적이지 않은 경우 호출자 또는 반환 함수에 의해) 변경할 수 있지만, 이 값을 반환하는 함수는 (쉽게) 여러 버퍼를 가질 수 없기 때문에 스레드 세이프가 아니며, 호출자는 함수를 다시 호출하기 전에 반환된 값을 복사해야 할 수 있습니다.

  • char*할당된 버퍼에malloc변경은 가능하지만 보통 발신자가 명시적으로 해제해야 하며 힙 할당 오버헤드가 있습니다. strdup이 타입입니다.

  • const char*또는char*이는 함수에 인수로 전달되었습니다(반환된 포인터는 인수 버퍼의 첫 번째 요소를 가리킬 필요가 없습니다).버퍼/메모리 관리의 책임은 발신자에게 있습니다.많은 표준 문자열 함수가 이 유형입니다.

한 가지 문제는 이것들을 하나의 기능에 혼합하는 것이 복잡해질 수 있다는 것입니다.호출자는 반환된 포인터를 어떻게 처리해야 하는지, 얼마나 유효하며, 호출자가 포인터를 해방해야 하는지 알아야 하며, 런타임에 이를 결정할 수 있는 (나이스한) 방법이 없습니다.따라서 예를 들어, 발신자가 필요로 하는 힙 할당 버퍼에 포인터를 반환하는 함수를 가질 수 없습니다.free또, 경우에 따라서는, 스트링 리터럴로부터의 디폴트치에의 포인터도 지정할 수 있습니다.이 포인터는 발신자가 사용할 필요가 없습니다. free.

좋은 질문입니다.일반적으로는 당신이 옳지만, 당신의 예는 예외입니다.컴파일러는 문자열 리터럴에 글로벌메모리를 정적으로 할당합니다.따라서 함수에 의해 반환된 주소는 유효합니다.

이것이 C의 편리한 특징인 것 같습니다.이를 통해 프로그래머가 메시지가 저장되는 메모리에 대해 걱정할 필요 없이 함수가 미리 구성된 메시지를 반환할 수 있습니다.

@asaelr의 올바른 관찰 참조const.

로컬 변수는 선언된 범위 내에서만 유효하지만 해당 함수에 로컬 변수를 선언하지 않습니다.

함수에서 문자열 리터럴로 포인터를 반환하는 것은 완전히 유효합니다. 문자열 리터럴은 프로그램의 실행 전체에 걸쳐 존재하기 때문입니다.static또는 글로벌 변수가 될 수 있습니다.

실행 중인 작업이 잘못 정의되어 있지 않은지 우려되는 경우 컴파일러 경고를 높여 실제로 잘못하고 있는 것이 없는지 확인해야 합니다.

str는 문자열 리터럴이 존재하는 정적 주소를 가리키기 때문에 결코 달링 포인터가 되지 않습니다.

로드될 때는 대부분 읽기 전용이며 프로그램에 대해 글로벌합니다.

해방 또는 변경을 시도해도 메모리 보호 기능이 있는 플랫폼세그멘테이션 장애가 발생합니다.

로컬 변수는 스택에 할당됩니다.함수가 완료되면 변수가 범위를 벗어나 코드에서 더 이상 액세스할 수 없습니다.그러나 해당 변수를 가리키도록 할당한 전역(또는 아직 범위를 벗어나지 않은) 포인터가 있는 경우 해당 변수가 있었던 스택의 위치를 가리킵니다.다른 함수가 사용하는 값일 수도 있고 의미가 없는 값일 수도 있습니다.

위의 예에서는 실제로 할당된 포인터를 위에서 호출하는 함수에 되돌리고 있습니다.따라서 로컬 포인터가 되지 않습니다.게다가 반환할 필요가 있는 포인터에 대해서는, 메모리가 글로벌 세그먼트에 할당됩니다.

언급URL : https://stackoverflow.com/questions/9970295/life-time-of-a-string-literal-in-c