c++ 배열의 함수 전달에 관한 질문

gyxor의 이미지

#include<iostream>
using namespace std;

class Matrix
{
  private:
       int data[3][3];

  public:
       Matrix()
       {
           for(int i=0;i<3;i++)
           {
             for(int j=0;j<3;j++)
             {
                 data[i][j] = 0;
             } 
           }
       }
       Matrix( int  **k)
       {
           for(int i=0;i<3;i++)
           {
             for(int j=0;j<3;j++)
             {
                 data[i][j] = k[i][j];
             } 
           }
       }
};

int main()
{
   int p[3][3]={0};
   Matrix k(p);
   return 0;
}

Matrix( int **k) 이런 부분에서 에러가 납니다.

Compiling...
Cpp1.cpp
C:\My Documents\Cpp1.cpp(113) : error C2664: '__thiscall Matrix::Matrix(int ** )' : cannot convert parameter 1 from 'int [3][3]' to 'int ** '
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Error executing cl.exe.

Cpp1.exe - 1 error(s), 0 warning(s)

Matrix( int k[][]) 이런식으로 바꿔도 에러가 납니다.

Compiling...
Cpp1.cpp
C:\My Documents\Cpp1.cpp(20) : error C2087: '<Unknown>' : missing subscript
C:\My Documents\Cpp1.cpp(113) : error C2664: '__thiscall Matrix::Matrix(int [][1])' : cannot convert parameter 1 from 'int [3][3]' to 'int [][1]'
Types pointed to are unrelated; conversion requires reinterpret_cast, C-style cast or function-style cast
Error executing cl.exe.

Cpp1.exe - 2 error(s), 0 warning(s)

Matrix( int **k)
Matrix( int k[][])
파라미터로는 배열이 올수가 없고
k 가 포인터 이므로..
Matrix( int k[3][3]) 이런식의 표현도 숫자 3은 아무의미가 없으며
배열이 아닌 명백한 포인터라고 알고있습니다.
그런데 Matrix( int k[3][3])
이와같이 선언하면 에러가 나질 않습니다.
Matrix( int **k)
Matrix( int k[][])
Matrix( int k[3][3])

이 세가지 모두 형태만 다를뿐 파라미터로 쓰이면 모두 동일한.. 포인터에 불과
하다고 알고있는데요..
세번째의 경우에서만 에러가 나질 않고 제대로 실행되는 이유가 궁금합니다.

고수님들의 답변을 부탁드립니다.

체스맨의 이미지

생성자가 받을 인자는 int** k 가 아니라,
int (*k)[3] 입니다. 즉 2차원 포인터가 아니고, 1차원 포인터입니다.
C 는 다차원 배열을 내부적으로 모두 1차원적으로 다룹니다.

Orion Project : http://orionids.org

gyxor의 이미지

우선 답변감사드립니다.
일차원 포인터로 생각한다면
파라미터를 int *p 로 했을때 에러가 나는 이유가 무엇인가요?
그리고 int *p[3] 로 해도 에러입니다. 포인터들의 일차원 배열로 선언하는것
은.. 파라미터에서는 *p[3] 또한 **p 로 보는것이 아닌가요

체스맨의 이미지

int* p[3] 은 int** p 파라미터로 받습니다. 그래서 안되구요.

말씀드렸듯이 정확한 타입은 int (*p)[3] 입니다. int* 로 안되는
건 컴파일러가 타입을 체크해서 그런 것이고, int a[3][3] 인 경우
a 를 int*로 캐스트하거나, a[0] 을 넘김으로써, int a[9] 배열처럼 사용할 수 있습니다.

Orion Project : http://orionids.org

gyxor의 이미지

#include<iostream>
using namespace std;

void v(int k[][3][3])
{
	cout << &k <<endl;
	cout << &k[0][0][0] << endl;
}

int main()
{
	int data[][3][3]={1,2,3,4,5,6,7,8,9,10,11,12};
	v(data);
	cout <<data << endl;
	cout << &data[0][0][0];
	int (*i)[3][3];
	i=data;
	cout << i[1][1][1];
	return 0;
}


좋은 답변감사드립니다.
님의 답변을 보고 많은 이해가 되었습니다.
미심쩍은 부분이 있어서추가질문드립니다.
위와같은 구문이 맞는것이라는것은 알겠습니다.
char* p[10];
의 파라미터 형태가 char* *i; 가 되는것도 알겠습니다.

그런데 다차원 배열에서
int data[3][3][3];
그냥 생각같아선 data는 *를 세번 붙일수 있는 주소이므로
int ***k;
k=data;
가 가능할것도 같은데요 사실 이날 이때것 이렇게 알고 살아왔었습니다. ^^;
그런데
int k[][3][3];
int (*k)[3][3];
int k[100][3][3];
세가지 모두 가능한데요..
어떤 식으로 정의하던지 1차 이후 부분의 배열의 형태를 맞춰 줘야 한다는것
은 어떠한 이유때문인가요?
그냥 문법상 규정상 약속이라고 이해하면 되는가요?
먼저에서도 말씀드렸고요 위 예문에서도 확인되듯이..
int k[][3][3];
int (*k)[3][3];
int k[100][3][3];

이세가지 모두는 *를 세번 사용할수 있는(표현이 좀 이상한가요?)
포인터 인데요 또한 1차이후의 배열사이즈또한 무의미한 값이고요..
사실이지 않습니까?
그럼에도 이런 원칙이 있는 이유가 궁금합니다.

답변부탁드립니다.

wongi의 이미지

Quote:
그런데 다차원 배열에서
int data[3][3][3];
그냥 생각같아선 data는 *를 세번 붙일수 있는 주소이므로
int ***k;
k=data;
가 가능할것도 같은데요

    int     d3ary[3][3][3]; /* 3d array of int (array of 2d array of int) */
    int     ***p1;          /* pointer to (pointer to (pointer to int)) */
    int     (*p2)[3][3];    /* pointer to 2d array of int */

    p1 = d3ary; /* warnning: incompatable pointer assignment */
    p2 = d3ary; /* it's ok */
    printf("\t\td3ary\t\tp1\t\tp2\n");
    printf("initially: \t%p\t%p\t%p\n", d3ary, p1, p2);
    printf("1 added: \t%p\t%p\t%p\n", d3ary+1, p1+1, p2+1);

result:
d3ary p1 p2
initially: 0xbffffa90 0xbffffa90 0xbffffa90
1 added: 0xbffffab4 0xbffffa94 0xbffffab4

KISS...
Keep It Small and Simple

moonzoo의 이미지

배열의 의미에 대해서 좀더 생각해 보시면 될듯 합니다.

int a[5][10]이란 배열은 , 쉽게 말해 2차원 배열이지만..

결국은 int [10] 의 형태의 배열을

a[0] , a[1] , a[2] , a[3] , a[4] 가

각각 가지고 있는,,달리 말하면 가리키고 있는 형태입니다.

main에서 int a[5][10] 이라는 배열을 선언했을때

파라미터로 받는 부분에서 int (*p)[10] 과 같이 배열의 크기를

명시해 주어야 하는 것입니다..

p가 가리키는 것은 a[0]가 되겠지요.

p+1은 a[1]을 가리키게 되는 것이구여.

int [10]이라고 명시된 크기 만큼의 뒤를

가리키는 것입니다.

gyxor의 이미지

답변감사드립니다. 큰 도움이 되었습니다.

댓글 달기

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