[문법기초] 이차원 배열 동적 할당이 왜 안되죠?

omando의 이미지

계속 컴파일 에러가 나는데 이유를 도저히 모르겠네요.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int   Scenario_2[2][3] =
{
   {1, 1, 1},
   {2, 2, 2}
};


int   Scenario_3[3][3] =
{
   {1, 1, 1},
   {2, 2, 2},
   {3, 3, 3}
};

int   Scenario_4[4][3] =
{
   {1, 1, 1},
   {2, 2, 2},
   {3, 3, 3},
   {4, 4, 4}
};

int  **p;

void main()
{
    //조건이 1이믄
    p = Scenario_2;
    //조건이 2면 
    p = Scenario_3;
    //조건이 3면 
    p = Scenario_4;

    for(int i =0 ; i< sizeof(p) / (sizeof(int) * 3) ; i++)
    {
       for(int j=0 ; j <3 ; j++ )
          printf("p[i][j] = %d \t", p[i][j] );
       printf("\n");
    }

}

컴파일 환경은 unix임니다.

에러 메시지는 p = Scenario_2; 와 같은 문자이 성립안된다네요??
왜 그렇죠. 단순히 포인터에 지정한것 뿐인데,,
p를 new 이용하여 동적으로 메모리 할당한 후,
memcpy(p, Scenario_2, sizeof(Scenario_2) ) 와 같이 해보아도
에러가 계속 발생하던데요..

단호진의 이미지

포인터 타입이 다를텐데요... p[][]계열과 **p는...
*p[2]식의 최소 몇 줄 짜리 자료인가 정보는 필요할 듯...

:wq

method의 이미지

2차원 배열도 memory에는 연속된 1차원 배열로 잡혀서 그렇지 않을까요?

int *p;

p = (int *)Scenario_2;

라고 하고
c=0;
for( i..... )
{
for( j.... )
printf("%d ", p[c++];
printf("\n")
}
하면 될것같은데요.

leilei의 이미지

혹시나 해서..

 int (*p)[3];

일단 이렇게 하시면...
Scenario_2 ~ Scenario_4까지 쓰실 수 있겠네요.

그런데 sizeof(p)하시면 원하시는 값이 안나올것 같지 않으세요.. :)

youngminny의 이미지

제 짧은 소견으로는 casting에 문제가 있는것 같구요.
sizeof는 원하는 값이 안나올것 같구요.
p[][]식의 접근은 안될것 같구요.
*(int **)(p+1)식은 될 것 같네요. ^^
제 생각엔 p가 pointer이고, 이것에 array를 할당했지만, p 자체는 쓰기가 안되는 const로 인식된다고 알고 있습니다. (맞나??)
그래서 array 접근은 마치 쓰기가 가능한것처럼 인식되므로 안된다고 생각됩니다. 즉, 직접 해당 pointer로 가서 조작을 해야 되지 않을까요?
맞을지는 자신없구요. 개인적인 생각이었습니다. ^^

myway4u의 이미지

int 배열은 포이터 상수로 처리된다고 하는군요... ^^;;
실제 메모리값이 없어 실행타임에 참조를 할수 없죠.
다음 코드를 실행 시켜 보시면 포인터는 메모리값을 가지지만,
배열은 그렇지 않다는것을 아실수 있을겁니다.

void main(void) {
             int ar[3] = { 1, 2, 3 };
             int *ap = ar;
    
             printf("%p %p\n", &ar, ar);
             printf("%p %p\n", &ap, ap);
}         

컴파일 타임에는 컴파일러가 참조를 할수 있을테니 다음 방법을
사용하시면 원하는데로 수행 될겁니다.

omando wrote:
계속 컴파일 에러가 나는데 이유를 도저히 모르겠네요.

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int   Scenario_2[2][3] =
{
   {1, 1, 1},
   {2, 2, 2}
};


int   Scenario_3[3][3] =
{
   {1, 1, 1},
   {2, 2, 2},
   {3, 3, 3}
};

int   Scenario_4[4][3] =
{
   {1, 1, 1},
   {2, 2, 2},
   {3, 3, 3},
   {4, 4, 4}
};

/***************************************************
int **p2 = Scenario_2;
int **p3 = Scenario_3;  <= 추가
int **p4 = Scenario_4;
***************************************************/
int  **p;

void main()
{
    //조건이 1이믄
    p = p2;   // <= 변경
    //조건이 2면 
    p = p3;   // <= 변경
    //조건이 3면 
    p = p4;   // <= 변경

    for(int i =0 ; i< sizeof(p) / (sizeof(int) * 3) ; i++)
    {
       for(int j=0 ; j <3 ; j++ )
          printf("p[i][j] = %d \t", p[i][j] );
       printf("\n");
    }

}

컴파일 환경은 unix임니다.

에러 메시지는 p = Scenario_2; 와 같은 문자이 성립안된다네요??
왜 그렇죠. 단순히 포인터에 지정한것 뿐인데,,
p를 new 이용하여 동적으로 메모리 할당한 후,
memcpy(p, Scenario_2, sizeof(Scenario_2) ) 와 같이 해보아도
에러가 계속 발생하던데요..

전산보안을 생활화 합시다~!

zero0kim의 이미지

이렇게 하시면 될것 같습니다.
우선 대입은 명시적 형변환으로 했구요
프린트는 *p는 1을 가리키지만, *Scenario[0]은 배열의 주소를 가르키기 때문에 좀 다르게 했습니다.
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int Scenario_2[2][3] =
{
{1, 1, 1},
{2, 2, 2}
};

int Scenario_3[3][3] =
{
{1, 1, 1},
{2, 2, 2},
{3, 3, 3}
};

int Scenario_4[4][3] =
{
{1, 1, 1},
{2, 2, 2},
{3, 3, 3},
{4, 4, 4}
};
int **p;

void main()
{
//조건이 1이믄
p = (int**)Scenario_2;
//조건이 2면
p = (int**)Scenario_3;
//조건이 3면
p = (int**)Scenario_4;
int i = 0;
while ( 1 )
{
printf("p[i][j] = %d \t", p[i] );
i++;
if ( p[i] == NULL )
{
break;
}
}
}

leilei의 이미지

2차원배열을 **p에 대입하는건 틀린 방법이라고 생각됩니다.

**p는 포인터의 포인터가 아닌가요?
즉 **p는 1차원 포인터 배열에 대한 변수가 되어야 할것 같은데요..

포인터에 대해서 배웠던게 언제였던가... :?

leilei의 이미지

저라면... :oops:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int   Scenario_2[2][3] =
{
    {1, 1, 1},
    {2, 2, 2}
};


int   Scenario_3[3][3] =
{
    {1, 1, 1},
    {2, 2, 2},
    {3, 3, 3}
};

int   Scenario_4[4][3] =
{
    {1, 1, 1},
    {2, 2, 2},
    {3, 3, 3},
    {4, 4, 4}
};

//int  **p;
int  (*p)[3];

void main()
{
    int i, j, row;

    //조건이 1이믄
    p = Scenario_2;
    row = sizeof(Scenario_2) / (sizeof(int)*3);

    //조건이 2면
    p = Scenario_3;
    row = sizeof(Scenario_3) / (sizeof(int)*3);

    //조건이 3면
    p = Scenario_4;
    row = sizeof(Scenario_4) / (sizeof(int)*3);


    for(i =0 ; i< row ; i++)
    {
        for(j=0 ; j <3 ; j++ )
                 printf("p[i][j] = %d \t", *(*(p+i)+j));
        printf("\n");
    }
}
lsj0713의 이미지

leilei wrote:
저라면... :oops:

#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>

int   Scenario_2[2][3] =
{
    {1, 1, 1},
    {2, 2, 2}
};


int   Scenario_3[3][3] =
{
    {1, 1, 1},
    {2, 2, 2},
    {3, 3, 3}
};

int   Scenario_4[4][3] =
{
    {1, 1, 1},
    {2, 2, 2},
    {3, 3, 3},
    {4, 4, 4}
};

//int  **p;
int  (*p)[3];

void main()
{
    int i, j, row;

    //조건이 1이믄
    p = Scenario_2;
    row = sizeof(Scenario_2) / (sizeof(int)*3);

    //조건이 2면
    p = Scenario_3;
    row = sizeof(Scenario_3) / (sizeof(int)*3);

    //조건이 3면
    p = Scenario_4;
    row = sizeof(Scenario_4) / (sizeof(int)*3);


    for(i =0 ; i< row ; i++)
    {
        for(j=0 ; j <3 ; j++ )
                 printf("p[i][j] = %d \t", *(*(p+i)+j));
        printf("\n");
    }
}

좀 더 고치자면...

...

int main(void)
{
    //...
    row = sizeof(Scenario_2) / sizeof(Scenario_2[0]);
    // ...
    printf("p[i][j] = %d\t", p[i][j]);
    // ...
    return 0;
}
dalekang의 이미지

이부분은

p = Scenario_2;

실제 구현한 시스템 마다 다르기는 하지만
포인트 변화에 따른 경고 메시지 입니다(Warning)
포인터에 대한 충분한 이해가 있으시다면
무시하셔도 됩니다.

그런데 제가 보니 프로그램 로직에 문제가 있습니다.
즉 포인터를 사용하는 부분입니다.
프로그램은 위에서 말씀하신 분처럼
고치시는 것이 좋을 것 같습니다.
(의도하지 않은 Warning은 Error라는 말이 있습니다)

정태영의 이미지

포인터의 포인터를 만들고.. 포인터를 할당하신담에 룹한번 돌리세요.. =3=33
(gd에선 그런식으로 이차원 배열을 할당하더군요 ;) ROW에 포인터를 쫘르륵.. 그담에.. 해당로우 하나하나에.. COL을...)

#define ROW 2
#define COL 2

int** p;
int Sample[3][2][2] = {
	{ 1, 2, 3, 4 },
	{ 5, 6, 7, 8 },
	{ 9, 10, 11, 12 }
}

p = (int**)malloc( sizeof(int*) * ROW );
for( i = 0 ; i < ROW ; i++ ){

	/* 조건이 k면.. */
	p[i] = Sample[k][i];

}

오랫동안 꿈을 그리는 사람은 그 꿈을 닮아간다...

http://mytears.org ~(~_~)~
나 한줄기 바람처럼..

댓글 달기

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