배열과 포인터에 관한 의문이 있습니다.

qprk의 이미지

코딩을 하는데 아래와 같이 사용을 하고 있습니다.

동작은 잘 하는것 같은데 문득 배열로 선언을 하면 메모리공간에 연속적으로 할당이 되는걸로 알고 있고 malloc 으로 할당을 하면 그때 그때 위치가 달라지는걸로 알고 있는데요..

아래와 같이 코딩된 경우 오류는 없는지?
잘 동작을 하는데 그냥 잘 동작 하는것 처럼 보이는지?
지금은 리눅스에서 작업하고 있는데 다른 플랫폼으로 넘어가면 문제는 없을지?

에 대한 의문이 발생하내요..

int **array;
int i;

array = (int **)malloc(sizeof(int *) *10);
for(i=0;i<10;i++){
  array[i] = (int *)malloc(sizeof(int) *10);
}

array[1][2] = 3;  // malloc 으로 공간할당을 한경우 이런 방식으로 접근이 가능한가요?  지금은 문제없이 동작하는것 같습니다.

위의 코드와 아래 코드는 같은 것일까요?

int array[10][10];

array[1][2] = 3;
익명 사용자의 이미지

메모리에서 배열되는 것은 물론 다르겠지만,
내용 자체는 개념적으로 같은 이야기라고 생각하셔도 될 것입니다.

vananamilk의 이미지

qprk wrote:

int **array;
int i;

array = (int **)malloc(sizeof(int *) *10);

assert(array);

for(i=0;i<10;i++){
  array[i] = (int *)malloc(sizeof(int) *10);

  assert(array[i]);
}

둘다 맞는 표현이구요. 동적할당할때는 assert를 사용해 주면
더 낫죠~

bugiii의 이미지

배열을 char a[5][10]; 이라고 선언했다면 이것은 10개짜리 char 가 5개 있고 이것이 연속적 붙어 있다고 생각하시면 됩니다.

만약 제시하신 코드처럼 사용한다면 int 10개짜리가 각각 따로 따로 할당되고 그것의 포인터를 담는 것을 10개 만드신 것이고 각 10개짜리끼리는 연속적이지 않습니다.

bugiii의 이미지

vananamilk wrote:
qprk wrote:

int **array;
int i;

array = (int **)malloc(sizeof(int *) *10);

assert(array);

for(i=0;i<10;i++){
  array[i] = (int *)malloc(sizeof(int) *10);

  assert(array[i]);
}

둘다 맞는 표현이구요. 동적할당할때는 assert를 사용해 주면
더 낫죠~

assert 를 메모리 할당에 사용하시면 최종 배포판에서 문제가 생길 수 있습니다. 에러와 예외에는 assert 를 사용하지 않는 것이 좋습니다.

cinsk의 이미지

assert()는 일어날 수 없는 상황을 쉽게 알 수 있게 해 주는 debug용 툴이기 때문에 위와 같은 상황에서 쓰는 것은 바람직하지 않습니다. 왜냐하면 memory가 부족한 것은 run-time error이기 때문에, (확률은 낮아도) 일어날 가능성이 있기 때문입니다. 비슷한 이유로 파일을 open했을 경우에도 리턴 값에 대해 assert(3)를 수행해서 열렸는지 테스트하는 것도 좋은 방법이 아닙니다.

위와 같은 경우, 에러를 출력하고 리턴하거나, 프로그램을 종료하는 편이 낫습니다.

pynoos의 이미지

assert는 논리적 오류를 찾아내는데 사용하는 것이지,
실행 오류처리를 위해 사용하는 것이 아닙니다.
동적할당 결과는 논리오류가 아니라 실행중 메모리 부족을 나타내는 오류이므로
assert를 사용하지 않는 것이 좋은 것이아니라 사용해서는 안됩니다.

cinsk의 이미지

:wink: 동시에 비슷한 답이 세개가 올라오는 군요.

doldori의 이미지

qprk wrote:
아래와 같이 코딩된 경우 오류는 없는지?
잘 동작을 하는데 그냥 잘 동작 하는것 처럼 보이는지?
지금은 리눅스에서 작업하고 있는데 다른 플랫폼으로 넘어가면 문제는 없을지?

전혀 문제 없습니다. 메모리 배치는 bugiii님이 말씀하신 것과 같이 배열과는 다르지만요.
그런데 루프 내에서 malloc()을 쓰는 것은 별로 좋은 방법이 아니죠. 다음처럼 하는
방법도 있습니다. 전체 메모리를 한 번에 잡고 포인터만 적당히 맞춰주는 식입니다.
이렇게 하면 메모리 배치도 배열과 동일해집니다.
const int row = 5, col = 10;
char** array;
int i;
array = malloc(sizeof(*array) * row);
array[0] = malloc(sizeof(**array) * row * col);
for (i = 1; i < row; ++i)
    array[i] = array[0] + sizeof(**array) * col * i;

// use array[i][j]...

free(array[0]);
free(array);
IsExist의 이미지

포인터, 어레이는 그림으로 그려가면서 생각하는게 훨씬 도움됩니다.

예를 든 코드에서는 타입이 int 였지만 struct 같은 경우가 된다면
배열간 sort 같은 경우가 필요하다면 포인터로 처리하는게 훨씬 빠르겠지요.

---------
간디가 말한 우리를 파괴시키는 7가지 요소

첫째, 노동 없는 부(富)/둘째, 양심 없는 쾌락
셋째, 인격 없는 지! 식/넷째, 윤리 없는 비지니스

이익추구를 위해서라면..

다섯째, 인성(人性)없는 과학
여섯째, 희생 없는 종교/일곱째, 신념 없는 정치

익명 사용자의 이미지

doldori wrote:
qprk wrote:
아래와 같이 코딩된 경우 오류는 없는지?
잘 동작을 하는데 그냥 잘 동작 하는것 처럼 보이는지?
지금은 리눅스에서 작업하고 있는데 다른 플랫폼으로 넘어가면 문제는 없을지?

전혀 문제 없습니다. 메모리 배치는 bugiii님이 말씀하신 것과 같이 배열과는 다르지만요.
그런데 루프 내에서 malloc()을 쓰는 것은 별로 좋은 방법이 아니죠. 다음처럼 하는
방법도 있습니다. 전체 메모리를 한 번에 잡고 포인터만 적당히 맞춰주는 식입니다.
이렇게 하면 메모리 배치도 배열과 동일해집니다.
const int row = 5, col = 10;
char** array;
int i;
array = malloc(sizeof(*array) * row);
array[0] = malloc(sizeof(**array) * row * col);
for (i = 1; i < row; ++i)
    array[i] = array[0] + sizeof(**array) * col * i;

// use array[i][j]...

free(array[0]);
free(array);

2차원 배열의 메모리 배치가 C컴파일러 표준으로 정해져 있나요?

doldori의 이미지

Anonymous wrote:
2차원 배열의 메모리 배치가 C컴파일러 표준으로 정해져 있나요?

C 컴파일러 표준은 아니고 C 언어 표준으로 정해져 있습니다. ^^;
복잡한 구절은 생략하고 직접적으로 표현된 문장만 인용하면
Quote:
6.2.5/20
An array type describes a contiguously allocated nonempty set of objects
with a particular member object type, called the element type. [...]

6.5.2.1/3
[...] It follows from this that arrays are stored in row-major order
(last subscript varies fastest).

vananamilk의 이미지

const int row = 5, col = 10; 
char** array; 
int i; 
array = malloc(sizeof(*array) * row); 
array[0] = malloc(sizeof(**array) * row * col); 
for (i = 1; i < row; ++i) 
    array[i] = array[0] + sizeof(**array) * col * i; 

// use array[i][j]... 

free(array[0]); 
free(array); 

전 단지 메모리 할당 오류 났을때 간편하게 테스트할려구... assert
적었구요. 실제 프로그램 작성시는 빼구... 예외처리를 ㅋㅋ
고수님들의 조언 감사드립니다. 위의 코드 잼있네요.
주소를 맞춰주는~ 써 먹어야겠넹~

for (i = 1; i < row; ++i) 
      array[i] = &array[0][col * i];
//    array[i] = array[0] + sizeof(**array) * col * i;

같은 표현이지만 식별하기에 더 나을 것 같기두 하네요. 그거야
갠차지만~
doldori의 이미지

위에 올린 코드에 잘못이 있어 수정합니다.

doldori wrote:

const int row = 5, col = 10;
char** array;
int i;
array = malloc(sizeof(*array) * row);
array[0] = malloc(sizeof(**array) * row * col);
for (i = 1; i < row; ++i)
//  array[i] = array[0] + sizeof(**array) * col * i;
    array[i] = array[0] + col * i;  /*** fixed ***/

// use array[i][j]...

free(array[0]);
free(array);
죠커의 이미지

Anonymous wrote:
doldori wrote:
qprk wrote:
아래와 같이 코딩된 경우 오류는 없는지?
잘 동작을 하는데 그냥 잘 동작 하는것 처럼 보이는지?
지금은 리눅스에서 작업하고 있는데 다른 플랫폼으로 넘어가면 문제는 없을지?

전혀 문제 없습니다. 메모리 배치는 bugiii님이 말씀하신 것과 같이 배열과는 다르지만요.
그런데 루프 내에서 malloc()을 쓰는 것은 별로 좋은 방법이 아니죠. 다음처럼 하는
방법도 있습니다. 전체 메모리를 한 번에 잡고 포인터만 적당히 맞춰주는 식입니다.
이렇게 하면 메모리 배치도 배열과 동일해집니다.
const int row = 5, col = 10;
char** array;
int i;
array = malloc(sizeof(*array) * row);
array[0] = malloc(sizeof(**array) * row * col);
for (i = 1; i < row; ++i)
    array[i] = array[0] + sizeof(**array) * col * i;

// use array[i][j]...

free(array[0]);
free(array);

2차원 배열의 메모리 배치가 C컴파일러 표준으로 정해져 있나요?

2차원 배열이라는 것은 존재하지 않습니다.

배열은 언제나 자료들이 연속으로 존재하는 것이 보장되어 있고 배열의 배열인 경우에도 각 배열이 연속으로 붙어 있는 것이 보장되어 있을 뿐입니다.

댓글 달기

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