게시판

검색 결과: 17

 

Dev C++은 사용하지 마세요.

Dev C++은 더 이상 개발되지 않습니다. 2015년 4월 5.11 이후로는 개발되지 않고 있습니다. C 언어에 대한 지원도 낮은 수준입니다.

따라서 해당 코드로는 정확하게 알 수 없습니다.

경고가 표시되지만, 코드의 문제인지 C 표준을 덜 지원해서인지 모릅니다.


포럼 오른쪽 상단에 63.7로 검색하면

https://dojang.io/mod/forum/search.php?id=2&search=63.7

이전 질문과 답변을 참고할 수 있습니다.


온라인 컴파일러에서 연습해도 아무 문제도 없습니다.

https://glot.io/snippets/fzkfl7flnm

glot.io에서는 clang을 사용합니다.



, 김 HM님이 작성
 
제가 사용하는 컴파일러는 Dev C++ Ver. 5.11입니다.

Unit 63.7 연습문제를 

c언어로 코딩해서 컴파일하면

[warning] passing argument 1 of 'allocMatrix' from incompatibel pointer type

이 왜 발생하는지 궁금합니다.

그리고

cpp로 코딩해서 컴파이하면

alloc_matrix(void*** ptr, int....) 함수 내의

*ptr = malloc(sizeof(void *) ...)에서

[Error] invalid conversion from 'void*' to 'void**' [-fpermissive]

오류가 발생하네요.

이 오류는 왜 발생하고 어떻게 수정해야 하나요?

좋은 책에 감사하고

이렇게 질문을 할 수 있는 곳이 있어 또 감사하고

읽어 주셔서 또 감사합니다.


 

네, 한 개가 지워졌다고 이해하면 됩니다.


 

*ptr = malloc(sizeof(void *) * m);
그렇다면 여기서 ptr은 인자로 matrix&를 받으므로 address of pointer to pointer to short가 되고 이는 pointer to pointer to pointer to short와 같으므로 *로 인해 pointer to 한 개가 지워졌다고 이해하면 될까요??

 

그림 38-3을 보고 포인터를 다시 이해하는 게 좋을 것 같습니다.

지금 타입을 이해한 게 아니라 *ptr 같은 모양으로 이해하려는 오류를 저지르고 있습니다.

    short **matrix;

    // m: 3, n: 3, 요소의 자료형 short
    allocMatrix(&matrix, 3, 3, sizeof(short));

여기서 matrix의 정확한 타입 명칭은

pointer to pointer to short입니다.

allocMactrix에서는 &matrix로 썼습니다.

이는

address of pointer to pointer to short

입니다.

address of와 pointer to는 모두 주솟값을 뜻합니다. 그래서 둘은 호환됩니다.

pointer to pointer to pointer to short와 호환이 됩니다.

따라서 allocMatrix 함수 정의는 다음과 같이 됩니다.

void allocMatrix(void ***ptr, int m, int n, int elementSize)

여기서 ptr의 타입은

pointer to pointer to pointer to short

입니다.

allocMatrix 안에서의 코드는

    *ptr = malloc(sizeof(void *) * m);

이렇게 되어 있습니다.

*ptr로 역참조했을 때 역참조의 대상은

pointer to pointer to short

입니다.

*ptr의 모양만 보고 "pointer to"로 이해하면 곤란합니다. 타입이 맞지 않습니다.

실제로

short *error를 선언해보고

    short = malloc(sizeof(void *) * m);
이렇게 하면 오류 발생합니다. 타입 미스매치.

2차원 배열을 위한 메모리를 할당해야 합니다. 2차원 배열의 주소를 전달해야 하죠. 그래서 & 연산자를 사용한 것입니다.

2차원 배열이 short **matrix처럼 포인터 형태로 표현되어 있을 뿐이죠.

어쨌든 함수에 전달해서 메모리를 할당하려면 matrix 자체의 주소를 보내야 하니까 &matrix를 써야 합니다.

참고하세요.



, 김 민석님이 작성
 

void allocMemory(void **ptr, int size)    // 반환값 없음, void 이중 포인터 매개변수 지정
{
    *ptr = malloc(size);    // void **ptr을 역참조하여 void *ptr에 메모리 할당
}
66.3의 내용입니다. 꼭 역참조 연산자가 더해져야 역참조가 되는 것이 아닌가요?? 

만약 그렇다면 *를 하나 제거할 경우 void **ptr에 해당하는 주소를 역참조하여 void *ptr의 주소에 malloc한다고 생각하면 되는건가요??

void allocMatrix(void ***ptr, int m, int n, int elementSize)
{
    *ptr = malloc(sizeof(void *) * m);       // ptr을 역참조한 뒤 메모리 할당

    for (int i = 0; i < m; i++)
    {
        (*ptr)[i] = malloc(elementSize * n); // ptr을 먼저 역참조한 뒤 인덱스로 접근
    }
}
여기서는 void ***ptr를 역참조 하였을 때 왜 **ptr가 아닌 *ptr가 되는것인가요??

*ptr을 먼저 할당하여 단일포인터를 만들고 (*ptr)[i]를 통해 이중포인터를 만드는것인가요??

, 도장_ 관리자님이 작성
 

38.3은 호출 없이 생성했고,

63.7은 호출한 함수 안에서 생성합니다.

38.3에서

int **m = malloc(sizeof(int *) * 3);    

이는 2차원 배열을 선언하면서 할당한 것입니다. 그러니까 **m이 맞습니다.

세로 배열 생성할때는 **ptr = malloc(sizeof(void *) * m);

네, 맞습니다.

단, 선언과 함께 생성할 때입니다.

int **ptr = malloc(sizeof(void *) * m);

이렇게 되어야 합니다.

한 줄에 하지 않고 두 줄로 풀면

int **ptr;
ptr = malloc(sizeof(void *) * m);

이렇게 되겠죠.

UNIT 63.7에서는 2중 포인터를 함수로 전달 받았습니다.

따라서 2중 포인터를 다시 주소로 전달하기 위해 3중 포인터 ***ptr를 썼습니다.

위에 두 줄로 나눈 것처럼 생각해야 합니다. 생성은 함수 생성전에 했고, 함수 안에서는 생성된 포인터에 메모리를 할당해야 하죠.

단, 2중 포인터를 함수에 전달하기 위해 3중 포인터로 했으니

ptr = ...

이렇게 쓰면 3중 포인터에 할당하는 게 됩니다.

역참조를 해서 *ptr로 써야 2중 포인터, 즉 2차원 배열의 세로에 할당하는 게 됩니다. 선언할 때의 포인터 *과 역참조할 때의 *를 혼동한 것 같습니다.


, 이 동욱님이 작성
 

안녕하세요


38.3에서 다중포인터로 배열형식을 만들때 하기와 같이 이중포인터를 사용해서

가로 배열 만들고 세로배열을 만드는거로 배웠습니다


int** m = malloc(sizeof(int*) * 3);                                         

for (int i = 0; i < 3; i++)           
{
    m[i] = malloc(sizeof(int) * 4);   
                                      
}

63.7에 와서 보니 하기와 같이 되어있어서 그 이유를 알고싶습니다

main 함수에 있는 short **matrix; 가 이중포인터라서 void ***ptr 삼중포인터로 

받는건 알겠는데 배열 생성을 하는데 왜 *ptr이 되나요??


void allocMatrix(void ***ptr, int m, int n, int elementSize) 

    *ptr = malloc(sizeof(void *) * m); 

    for (int i = 0; i < m; i++) 

    { 

        (*ptr)[i] = malloc(elementSize * n); 

    } 


세로 배열 생성할때는 **ptr = malloc(sizeof(void *) * m); 

가로 배열 생성할때는 *ptr[i] = malloc(sizeof(elementSize) * n);

이 되어야 되는게 아닌가요 


해설을 봐도 이해가 잘 안되네요.. 

 

포인터 크기는 해당 플랫폼에 따라 달라지고, 자료형과는 상관이 없으니 아무 포인터 타입을 써도 코드 동작에는 문제가 없습니다.

그러나 void *가 일반 포인터(general pointer)이므로 포인터 크기가 필요할 때는 일반 포인터로 구하는 게 일반적입니다.


, 코 딩님이 작성
 
ptr을 한번 역참조해서 동적 메모리를 할당하는 *ptr=malloc(sizeof(void *)*m);부분에서 크기를 void *로 한 이유를 모르겠습니다 . 포인터부분을요