C에서 포인터 질문입니다.

나그네나그네의 이미지

이제 C를 배워가고 있는 왕초보입니다.

int a[100];
int * a = new int[100];

이 두 개의 명확한 차이점이 뭔가요? 그리고, 첫번째 것은 되고 두번째 것은 안되고 이런 것이 있는가요?

kaje0105의 이미지

메모리 동적 할당과 정적 할당에 대한 질문이라 생각하고 답변드리겠습니다
이해를 돕기 위해 질문을 약간 수정하겠습니다.
int a[100];
int * a = new int[100];
100개의 int형 메모리 공간을 100개 만든다는 점에선 같습니다. 다만,
>>
int a[SIZE];
int * a = new int[SIZE];
이런식으로 정확한 크기를 명시 하지 않고 일정 계산등 의해 크기가 정해 지는
메모리 공간의 경우에는 2번째의 방법을 써야 합니다.
첫번째 방식으로는 컴파일시 에러가 나게 되죠.
되고 안되고를 질문하신 것은 아무래도 이 대답이 될거 같네요..

메모리의 효율적인 사용을 위해 많은 프로그램에서 메모리 동적할당을 사용합니다.

나그네나그네의 이미지

int a[SIZE]를 C에서 막아놓은 이유가 뭔가요?

----------------
agidari.wordpress.com

klyx의 이미지

C가 태어난지 오래되었기 때문입니다.
예를 들어 초기의 C는 변수 선언을 반드시 블록의 처음에 해야한다는 규칙이 있었습니다.
아래쪽에 다른 분이 적으셨듯이 그냥 선언된 변수들은 다 stack에서 할당됩니다.
정확하겐 모르겠지만, 아마도 당시엔 stack상에서 동적으로 할당할 방법이 없었거나 블록 중간에 변수선언이 될때 컴파일시에 메모리 계산이 불가능했던것 같습니다.
그래서 stack에서 할당될 변수들은 다 블록의 처음에 적도록 한것이지요.
하지만 요즘 C99(C89일지도?)에서부터는 C++ 처럼 중간에서 선언해도 되게 바뀌었습니다.

배열 선언도 마찬가지입니다.
예로써 다음과 같은 코드를 생각해봅니다.

void f(int size) {
...
int n[size];
...
}

여기서 int n[size]는 컴파일 시엔 그 크기를 알수가 없습니다.(함수 f가 프로그램 내에서만 호출된다면 모르지만 예를 들어 외부로부터 size를 입력받아서 실행한다면 절대 알수 없겠지요)
그렇기 때문에 컴파일할때 stack에 할당될 메모리를 알수 없기 때문에 초기의 C에선 변수로 배열의 크기를 지정할수 없었습니다.
하지만 이역시 (아마도 stack에서도 동적할당이 가능해져서) C99에선 문법적으로 문제없는 구문입니다.
그러므로 이러한 구문을 쓰고 싶으시면 C99를 지원하는 컴파일러를 이용하시면 됩니다.

klyx의 이미지

그외에 변수가 유지되는 범위도 다릅니다.
int a[100]의 경우는 그것이 선언된 범위(함수나 {}블록 등)에서만 유효하며, 그 범위를 벗어나면 자동으로 소멸됩니다.
그에 반해 int *a = new int[100]의 경우는 선언된 범위를 벗어나도 '프로그램이 종료되서 운영체제에서 메모리를 회수하거나 delete를 이용해서 해제'해주지 않는 한 소멸되지 않습니다.
그렇기 때문에 장시간에 걸쳐서 반복해서 동적 할당을 하는 프로그램의 경우 메모리 해제를 제대로 해주지 않으면 문제가 생길수 있습니다.

나그네나그네의 이미지

왜 a[100]은 사라지는데 *a는 사라지지 않는건가요?

만약 컴파일 할 때 a[100]을 해제하도록 특별한 처리를 해준다면 *a의 경우는 왜 그 처리를 해주지 않나요?

----------------
agidari.wordpress.com

d3m3vilurr의 이미지

컴파일을 할 때 사라지는 것이 아닙니다.

int* foo1() {
int a[100];
return a;
}

int* foo2() {
int *a;
a = malloc(sizeof(int) * 100); // a = new int[100];

return a;
}

위 두 함수를 놓고 볼때, 메모리가 할당되는 영역이 두가지는 차이가 있습니다.
foo1함수에서는 a에 해당하는 위치가 stack에 형성되고, a는 stack에 만들어진 배열의 첫 위치가 되게 됩니다.

반면 foo2 함수에서는 a 포인터만이 stack에 형성되고, a가 가르키는 공간은 heap에 할당됩니다.
heap에 할당된 메모리 영역은 명시적으로 free를 하기 전까지 사라지지 않습니다.


int *a = foo1();
int *b = foo2();

를 했을때, a의 접근은 세그 폴트를 낼 수 있지만, b의 접근은 가능합니다.

klyx의 이미지

일단 범위를 벗어나면 해제되버리면 heap에 할당된다는 점외에 동적할당은 지역변수선언과 다를바없게 되므로 아무런 의미를 가지지 않으므로 이경우는 제외하고, 어째서 범위를 벗어나서 살아있다가도 필요가 없어지면 자동으로 해제되지 않느냐는 질문으로 생각하겠습니다.

이러한 일을 하는 것이 바로 Java나 Python등 C/C++외의 여러언어에서 제공하는 Garbage Collection입니다.

일단 C가 만들어졌을땐 GC란 것이 없었기도 하거니와, 무조건 GC가 좋기만 한것은 아니기 때문에 GC가 없으니까 나쁘다 라기 보다는 언어의 특성으로 보는게 좋다고 생각합니다.

예를 들어 GC를 도입하면 퍼포먼스면에서 문제가 있을수도 있고, 반대로 GC가 없으면 그 유명한 dangling pointer의 문제가 발생할수도 있습니다.

참고로 C++에서는 필요없어진 포인터를 자동으로 해제해주는 smart pointer라고 불리는 클래스들도 존재합니다.

kane의 이미지

사소한 태클 하나.

C보다 오래된 lisp에도 GC가 있으니, 그 당시에 GC가 없었다고 보긴 어렵죠. 다만 당시에는 GC의 성능이 안 좋았을 뿐이라고나 할까요. 아니면 그런 호화로운 기능을 쓸만한 상황은 아니었다고 할까요. ^^

d3m3vilurr의 이미지

C언어가 만들어질 당시엔 GC를 일부러 고려 안했을 가능성이 높습니다. 또한 레퍼런스 기능이 없는 C언어에서 GC를 사용하기는 복잡하기도 합니다.

중간에 포인터를 하나 더 두는 것과 메모리가 언제 해제될지 장담받지 못한다는 것은 당시 시스템 퍼포먼스 상 문제가 될 수 있기 때문이죠.
또한 GC가 계속 모니터링도 하고 있어야 되고요.
사실 C도 그렇고 C++도 그렇고 시스템 프로그래밍을 목표로 처음 설계된 언어인 만큼 메모리 관리를 직접하게 하는 것이 이득을 얻게 되기도 합니다.

kaeri17의 이미지

글고 C99표준에서는 int a[size]같은것도 허용한답니다. 스택사이즈도 동적으로 할당할수 있는 방법이 있으니까요

댓글 달기

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
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.