포인터변수 질문있습니다

i2ft의 이미지

char *ptr="abcd"; ->포인터변수선언

포인터변수에 포인터값이아닌 문자열 상수값이들어갔다

헌데 컴파일은 정상적으로됨 ->의문

예상)

abcd란값이 메모리 임의의 장소에 저장죄고

그 메모리 주소값을 포인터변수가 참조후 사용할수잇슴

실제)

abcd란값을 불러온순있으나 수정이불가능함

왜그런간가요?

kese111의 이미지


이것은 정답이 아니고 제가 아~~ 그럼 혹시 이거 아닌가? 하는 마음으로 그냥 다는 글입니다.
제 생각에는 abcd 가 code 영역에 그냥 박히고, ptr 이 이를 정적으로 가르키고 있는 상황같네요.
이럴 경우 code영역은 수정이 불가능하고 ptr은 정적주소값을 갖으므로 문자열 상수값을 보여주게 될 것 같습니다.

debugging으로 확인해보시고 아니면 말구요. 헤헤

익명 사용자의 이미지

"abcd"도 다음 경우를 제외하고는 일종의 배열로 취급됩니다.

char str[] = "abcd"; // 문자열 배열의 초기화를 위해 사용된 경우. 이 경우 "abcd"는 배열이 아니다.

따라서 수식 중간에 다음과 같은 코드가 가능합니다.

char c;
...
c = "abcd"[3]; // c에 'd'값 저장

문자열 상수를 왜 수정할 수 없는가는, '현재 C언어의 규칙이 그렇게 정해져 있다'가 가장 직접적인 답입니다. 아주 직접적으로, 다음과 같이 명확하게 써 놨습니다.

If the program attempts to modify such an array, the behavior is undefined.

왜 규칙이 그렇게 정해졌는가에 대해서는, 여러가지 이유를 댈 수가 있겠지만, 하나만 예를 들자면...

어떤 컴퓨터(혹은 마이크로 컨트롤러?)들의 경우에는 ROM과 RAM이 따로 있는 경우가 있는데, 이런 경우 많이 쓰이는 문자열 상수는 ROM에 박아버리면 편리하지요. 이런 환경을 위한 C 컴파일러를 제작한다고 하면, 문자열 상수는 변경을 못하게 만드는 것이 바람직 합니다.

C 언어는 단지 데스크탑을 위한 언어가 아니라, 아래로는 마이크로컨트롤러에서 위로는 슈퍼컴퓨터까지 쓰이는 언어입니다. 그래서 보통의 컴퓨터 환경에서는 상상도 못할 상황을 위한 규칙들이 많이 들어가 있지요. 예를 들자면 2의 보수는 C언어에게는 필수가 아닙니다.

문자열 상수를 const char형 배열로 봐야 할지 아닐지는, 저도 잘 모르겠습니다. 해당 배열의 원소가 char형이라고 쓰여 있을 뿐, 그에 대해서는 구체적인 서술이 없거든요. 그러나 프로그래밍 상의 실수를 방지하기 위해, 문자열 상수는 const char형을 가리키는 포인터로 처리를 하는게 관례입니다.

kese111의 이미지

질문이 다소 흥미로웠기 때문에 몇 가지 테스트를 거치고 제가 내린 결론은 이렇습니다.
질문에서 "abcd" 라는 문자열이 const한 상수로서 text 섹션에 존재시킬지 여부는 변수의 성향에 따라 달라집니다.

위의 답변처럼,
char str[] 로 받았을 경우 문자열은 data 섹션에 저장됩니다. 하지만 char *ptr 로 받았을 경우 문자열은 const한 섹션(text 혹은 rodata)에 저장되게 됩니다.

이는 당연히 C언어의 규칙이겠고, 제가 내린 결론으로는 C언어에서는
pointer 변수의 경우 "stack 혹은 register"를 사용하여 메모리 공간을 가르키는 변수이지 메모리 공간의 할당을 뜻하는 변수가 아니기 때문에 이런 식으로 처리된다고 보입니다.

말하자면,
char *ptr = "abcd";
라는 문장에서 "abcd"는 메모리 적재 공간을 할당받지 못했다는 뜻이지요.
그래서 컴파일러는 이를 상수화 처리하고 임의로 배치하는데 보통 text 섹션 뒷편 혹은 rodata 에 저장되게 됩니다.

다른 경우로
char ptr[] = "abcd";
라는 문장의 경우 초기화 요구를 뜻하므로 abcd를 위한 적절한 메모리 할당이 이뤄지게 되고, 보통 stack이나 heap에 저장되게 됩니다.

klara의 이미지

양쪽 모두 heap에 올라가는 메모리는 없습니다. "abcd"는 데이터 영역에, ptr은 stack에 올라갑니다.
차이는 배열로 선언하면 배열이 통째로 스택에 올라가고 데이터 영역의 값이 배열로 복사되어 초기화되고, 상수 포인터로 선언하면 데이터 영역을 가리키는 포인터 변수만이 스택에 올라간다는 점입니다.
C에서 선언된 변수는 무조건 stack(또는 말씀하신대로 최적화에 따라서는 레지스터)에 올라갑니다. 이는 포인터 변수도 예외가 아닙니다.
heap에 올라가는 것은 malloc등으로 할당된 '메모리 영역'뿐입니다.

익명 사용자의 이미지

말하자면, char *ptr = "abcd"; 라는 문장에서 "abcd"는 메모리 적재 공간을 할당받지 못했다는 뜻이지요.

아닙니다. "abcd"는 정적 기억 수명을 가지는 배열이 됩니다. 따라서 메모리 적재 공간을 할당받습니다(흔히 말하는 stack이나 heap은 아닐수 있어도). 실제로, "abcd"는 배열이기에 l-value입니다. 다만 몇몇 예외상황을 제외하면, 배열의 결과값을 가지는 수식들은 그 자신의 첫번째 원소를 가리키는 포인터 주소값이 되기에, 이걸 실감할 기회는 흔치 않습니다. 하지만 한가지 예를 들자면, 아래 코드는 적법한 수식입니다.

char (*ptr)[5] = &"abcd";

보통 문자열 상수는 말씀하신대로 text섹션 또는 rodata에 저장되지만, 사실 정확한 규칙은, 이 문자열 상수의 수정을 금지하는 것이고, 어디에 저장하는지는 규칙에 정해져 있지 않습니다.

kese111의 이미지

약간의 혼동이 있는 것 같으므로
"메모리 적재 공간을 할당받지 못했다." 는 말을 재정의해야 할 필요가 있는 것 같습니다.

저는 메모리 공간을 할당 받는다는 것은 stack 메모리 혹은 heap 등에 Data를 복사하고 이를 사용할 수 있게 한다는 뜻으로 이해하고 있으며,
위의 경우 문자열이 그대로 text든 rodata든 정적 상수값을 저장하는 공간에 저장되므로 메모리 공간을 할당받지 못한다고 표현했습니다.

프로그램이 로드될때 code 또한 메모리에 올라가지만 이를 메모리 적재 공간을 할당해준다. 라고는 생각해 본 적이 없습니다.
(당연히 메모리에 올라가지긴 하지만... )

어쨌든 제가 말씀드린 메모리 적재 공간 할당에 대한 예는,
char ptr[] = "abcd"; 의 경우 stack 에 abcd를 올리고 이를 사용하게 되죠.
char *ptr = "abcd"; 로 선언하면 ptr은 고정 주소값을 가지므로 사실 text 혹은 code와 함께 프로그램이 로드되었을 뿐
추가적으로 "abcd"를 위한 메모리 적재는 없습니다.

저는 이를 표현한 것이고, 혹시 저로 인해 머리 속이 복잡해지신 분이 있다면 사과드리고 싶습니다. ^^

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.