함수에서 char*를 반환하는 것과 char[]를 반환하는 것의 차이점은 무엇입니까?
첫 번째 함수는 "Hello, World" 문자열을 반환하고 두 번째 함수는 아무것도 반환하지 않는 이유는 무엇입니까?두 함수의 반환값은 범위 밖의 데이터를 반환하기 때문에 정의되지 않을 것으로 생각했습니다.
#include <stdio.h>
// This successfully returns "Hello, World"
char* function1()
{
char* string = "Hello, World!";
return string;
}
// This returns nothing
char* function2()
{
char string[] = "Hello, World!";
return string;
}
int main()
{
char* foo1 = function1();
printf("%s\n", foo1); // Prints "Hello, World"
printf("------------\n");
char* foo2 = function2(); // Prints nothing
printf("%s\n", foo2);
return 0;
}
두 번째 함수는 아무것도 반환하지 않습니다.
string
: "배열":
char string[] = "Hello, World!";
에는 자동 저장 기간이 있습니다.제어 플로우가 함수에서 돌아온 후에는 존재하지 않습니다.
반에 whereas whereas.string
기능 in in 、 in in in:
char* string = "Hello, World!";
는 정적 저장 기간을 갖는 리터럴 문자열을 가리킵니다.즉, 함수에서 돌아온 후에도 문자열이 계속 존재함을 의미합니다.함수에서 반환되는 것은 이 리터럴 문자열에 대한 포인터입니다.
문자열에 대해 가장 먼저 알아야 할 것은 문자열 리터럴은 실제로 전체 프로그램의 수명을 가진 읽기 전용 문자의 배열이라는 것입니다.즉, 프로그램 실행 내내 항상 존재하기 때문에 범위를 벗어나지 않습니다.
번째 기능예: 째번 ( ( ( ( ( ( ( ( ( ( function1
의 첫 는 이러한 배열의 첫 번째 요소에 포인터를 반환합니다.
기능 「 」 「 」 「 」 )을 사용합니다.function2
는 조금 는 조금 다릅니다. '''는string
는 함수 내의 로컬 변수입니다.따라서 이 기능은 범위를 벗어나 기능이 돌아오면 더 이상 존재하지 않게 됩니다.이 기능을 사용하면 해당 배열의 첫 번째 요소에 포인터를 반환할 수 있지만 해당 포인터는 더 이상 존재하지 않는 무언가를 가리키기 때문에 즉시 비활성화됩니다.참조 해제(전송할 때 발생)printf
)는 정의되지 않은 동작을 일으킵니다.
C 또는 기타 스택 기반 언어로 코딩할 때 기억해야 할 매우 중요한 것은 함수가 반환될 때 함수와 해당 로컬 스토리지가 모두 사라졌다는 것입니다.즉, 다른 사람이 열심히 작업한 메서드의 결과를 볼 수 있도록 하려면 메서드가 종료된 후에도 남아 있는 장소에 보관해야 하며, 그러기 위해서는 C가 어디에 어떻게 물건을 보관하고 있는지를 파악해야 합니다.
C에서는 어레이가 어떻게 동작하는지 이미 알고 있을 것입니다.오브젝트의 사이즈에 따라 증가하는 메모리주소일 뿐이며, C는 경계체크를 하지 않기 때문에 10 요소 배열의 11번째 요소에 액세스 하고 싶어도 아무도 제지하지 않습니다.또, 아무것도 기입하려고 하지 않는 한, 해를 끼치지 않습니다.C는 이 아이디어를 함수 및 변수를 사용하는 방식으로 확장한다는 사실을 모를 수도 있습니다.함수는 필요에 따라 로드되는 스택의 메모리 영역일 뿐이며, 변수의 저장공간은 해당 위치에서 오프셋되어 있을 뿐입니다.함수에서 로컬 변수, 특히 "Hello World\n\0"의 "H"를 유지하는 스택 상의 위치 주소로 포인터가 반환되었습니다.그러나 다른 함수(인쇄 방식)를 호출했을 때 메모리가 인쇄 방식으로 필요한 작업을 수행하기 위해 재사용되었습니다.이것은 쉽게 알 수 있습니다(제품 코드에서는 사용하지 마십시오!!!)
char* foo2 = function2(); // Prints nothing
ch = foo2[0]; // Do not do this in live code!
printf("%s\n", foo2); // stack used by foo2 now used by print()
printf("ch is %c\n", ch); // will have the value 'H'!
두 함수의 반환값은 범위 밖의 데이터를 반환하기 때문에 정의되지 않을 것으로 생각했습니다.
아니, 그렇지 않아
★★★★function1
포인터를 문자열 리터럴로 되돌립니다.문자열 리터럴에는 정적 저장 기간이 있으므로 포인터를 문자열 리터럴로 반환하는 것이 좋습니다.그러나 자동 로컬 변수에서는 그렇지 않습니다.
★★★★function2
string
은 " " " 입니다.
return string;
자동 로컬 변수에 대한 포인터를 반환합니다.돌아오면 " " " " 가 반환됩니다.string
더 이상 존재하지 않습니다.반환된 포인터를 참조 해제하면 정의되지 않은 동작이 발생합니다.
"Hello, World!"
는 스트링 리터럴로, 정적 저장 기간이 있기 때문에 문제는 다른 곳에 있습니다.첫 번째 함수는 다음 값을 반환합니다.string
괜찮아요.그러나 두 번째 함수는 로컬 변수의 주소를 반환합니다(string
is is is is is와 &string[0]
)의 결과, 정의되지 않은 동작이 발생합니다. 번째 ★★★★★★★★★★★★★★.printf
,!!,,,,!!!,, ,,,!! !,!!!!이치내 기계에서 프로그램이 분할 장애를 일으킵니다.
컴파일러가 출력하는 메시지를 항상 살펴보십시오.를 들면, 「」는,gcc
다음과 같은 기능이 있습니다.
file.c:12:12: warning: function returns address of local variable [-Wreturn-local-addr]
return string;
^
그건 거의 자기계발적이죠.
두 함수의 반환값은 범위 밖의 데이터를 반환하기 때문에 정의되지 않을 것으로 생각했습니다.
두 함수 모두 포인터를 반환합니다.중요한 것은 의뢰인의 범위이다.
인function1
참조는 문자열 리터럴입니다."Hello, World!"
정적 저장 기간이 있습니다. string
는 해당 문자열을 가리키는 로컬 변수이며 개념적으로 해당 포인터의 복사본이 반환됩니다(실제로 컴파일러는 불필요한 값 복사를 방지합니다).
인function2
개념적으로 참조는 로컬 어레이입니다.string
(컴파일 시) 스트링 리터럴(물론 늘 터미네이터 포함)을 유지할 수 있는 크기로 자동 사이징되어 스트링의 복사본으로 초기화되었습니다.이 함수는 어레이에 포인터를 반환합니다.단, 어레이는 자동 스토리지 지속 시간이 있기 때문에 기능을 종료한 후에는 더 이상 존재하지 않습니다(좀 더 친숙한 용어로는 "범위 밖"입니다).이것은 정의되지 않은 동작이기 때문에 컴파일러는 실제로 모든 종류의 작업을 수행할 수 있습니다.
말은 모든 것이 다 요?
char*
★★★★★★★★★★★★?
다시 포인터와 참조를 구별해야 합니다.포인터는 데이터를 가리킵니다.데이터 자체를 「포함」하는 것은 아닙니다.
C에 실제로 어떤 배열과 포인터가 있는지 제대로 연구해야 할 지 알게 되었습니다.불행히도 조금 복잡합니다.제가 즉시 제공할 수 있는 가장 좋은 레퍼런스는 Q&A 형식입니다.
언급URL : https://stackoverflow.com/questions/46090597/what-is-the-difference-between-returning-a-char-and-a-char-from-a-function
'sourcecode' 카테고리의 다른 글
@RequestParam 목록 바인딩 (0) | 2022.08.31 |
---|---|
Java Array List는 특정 인덱스로 대체됩니다. (0) | 2022.08.31 |
VueX를 통한 데이터 액세스 (0) | 2022.08.31 |
x == (x = y)가 (x = y) == x와 같지 않은 이유는 무엇입니까? (0) | 2022.08.31 |
플레인 파일을 실행 파일에 링크할 수 있습니까? (0) | 2022.08.31 |