2014-12-03 4 views
1

저는 C로 배열 된 프로그래밍 및 학습 포인터를 처음 사용합니다. 아래 프로그램을 살펴보십시오.* p와 (* p) [3]의 차이점은 무엇입니까?

1 프로그램

#include<stdio.h> 
    int fun(); 
    int main() 
    { 
    int num[3][3]={21,325,524,52,0,6514,61,33,85}; 
    fun(num); 
    printf("%d",*(*(num+1)+1)); 
    *(*(num+1)+1)=0; 
    printf("%d",*(*(num+1)+1)); 
    return 0; 
    } 
    int fun(int **p) 
    { 
    *(*(p+1)+1)=2135; 
    return 0; 
    } 

2 프로그램

#include<stdio.h> 
    int fun(); 
    int main() 
    { 
    int num[3][3]={21,325,524,52,0,6514,61,33,85}; 
    fun(num); 
    printf("%d",*(*(num+1)+1)); 
    *(*(num+1)+1)=0; 
    printf("%d",*(*(num+1)+1)); 
    return 0; 
    } 
    int fun(int *p) 
    { 
    *((p+1)+1)=2135; 
    return 0; 
    } 

3 프로그램

 #include<stdio.h> 
    int fun(); 
    int main() 
    { 
    int num[3][3]={21,325,524,52,0,6514,61,33,85}; 
    fun(num); 
    printf("%d",*(*(num+1)+1)); 
    *(*(num+1)+1)=0; 
    printf("%d",*(*(num+1)+1)); 
    return 0; 
    } 
    int fun(int (*p)[3]) 
    { 
    *(*(p+1)+1)=2135; 
    return 0; 
    } 
  1. 첫 번째 프로그램에서 **pfun() 함수에서 사용되었습니다.이 함수는 올바른 것으로 생각하고 함수의 첫 번째 배열의 첫 번째 요소를 변경하려면 *(*(p+1)+1)을 작성했습니다. 그러나이 프로그램을 컴파일하면 error: invalid type argument of unary '*' (have 'int')이 표시됩니다. 내가 아는 한 num은 배열을 가리키는 포인터이고, 다시 num[1][0]의 주소를 가지고있는 num[1]의 주소를 보유하고있다.
  2. 두 번째 프로그램 컴파일러를 컴파일하는 중에 오류가 표시되지 않습니다. *((p+1)+1)=0은 첫 번째 배열의 두 번째 요소 값을 변경합니다. 왜 첫 번째 배열의 첫 번째 요소의 값이 아닌 0 번째 배열의 두 번째 요소의 값을 변경하고 있습니까? 그리고 어떻게? *(*(p+1)+1)=0이어야합니다.
  3. 세 번째 프로그램에서 컴파일러에 오류가 표시되지 않고 올바른 결과가 표시됩니다. 방법?. *(p)[3]의 의미는 무엇입니까?

나는 이것에 대해서 조사했지만 만족스러운 결과를 찾을 수 없었다.

+1

"+0"의 모든 항목을 제거한 다음 불필요한 중괄호를 모두 제거하십시오. 그들은 아무 쓸모가없고 심한 두통을 일으킨다. – fjf2002

+0

배열의 이름은 배열의 첫 번째 요소에 대한 포인터입니다. 내부적으로는 실제로는 같지 않지만 포인터로 사용할 수 있습니다. – Joachim

+0

나는 질문을 편집했다. :) –

답변

1

는 당신이 요구하는 생각 :

int fun(int *p) 

int fun(int (*p)[3]) 

첫 번째 차이는 int에 대한 포인터 기대한다 무엇. 두 번째 포인터는 3 int 배열에 대한 포인터를 기대합니다. 당신은 그들이 정의처럼, 당신은 첫 번째 버전에 대한 경고/컴파일러 오류가 발생합니다 기능을 선언 할 경우

int fun(); 

등의 기능을 선언 한 이후

당신은 num를 사용하여이 두 함수를 호출 할 수 있습니다.

다음은 gcc 및 컴파일러 플래그 -Wall을 사용하는 코드의 업데이트 된 버전과 컴파일러 경고입니다. 프로그램의

#include <stdio.h> 

int fun(int *p); 

int main() 
{ 
    int num[3][3]={21,325,524,52,0,6514,61,33,85}; 
    fun(num); 
    return 0; 
} 

int fun(int *p) 
{ 
    *(p+0)=2135; 
    return 0; 
} 
test.c: In function ‘main’: 
test.c:7:4: warning: missing braces around initializer [-Wmissing-braces] 
test.c:7:4: warning: (near initialization for ‘num[0]’) [-Wmissing-braces] 
test.c:8:4: warning: passing argument 1 of ‘fun’ from incompatible pointer type [enabled by default] 
test.c:3:5: note: expected ‘int *’ but argument is of type ‘int (*)[3]’ 
+0

감사합니다. :)하지만 ** function에 ** p를 쓰면 어떨까요? –

+0

@ user3788135, 두 번째 버전에는'** p'를 사용할 수 있지만 첫 번째 버전에는 사용할 수 없습니다. 첫번째 버전에서'* p'는'int' 타입입니다. ** p는 유효한 유형이 아닙니다. –

+0

죄송합니다. 당신이 나에게 설명하고 싶은 것을 얻지 못했습니다. 내가 말하고자하는 것은 num이 배열에 대한 포인터라면 ** p를 쓸 수 없다는 것입니다. –

1

모든 잘못이 형성되어있다. 컴파일러는 경고 또는 오류 메시지를 생성해야하며 생성 된 실행 파일의 출력은 의미가 없습니다.

int[3][3]int **과 호환되지 않으며 int * 또는 int *[3]과 호환되지 않으므로 형식이 잘못되었습니다.

int[3][3]을 함수에 전달하려면 함수에 int (*)[3]을 받아 들여야하며 그 외에는 아무 것도 허용하지 말아야합니다 (물론 void * 제외).

이것은 배열이 배열의 첫 번째 요소에 대한 포인터로 변환 될 수 있기 때문입니다. (C 문법에서는 num을 사용하여 &num[0]을 의미 할 수 있음).

C에는 진정한 1 차원 배열 만 있습니다. int[3][3] 유형의 배열은 3 개의 요소로 이루어진 배열로 간주되며, 각 배열은 3 개의 정수로 구성됩니다.

num의 첫 번째 요소에 대한 포인터는 int (*p)[3]으로 작성된 3 개의 int 배열에 대한 포인터입니다. 당신은 쓸 수 :

int (*p)[3] = &num[0]; 

또는 같은 일에 대한 속기 :

int (*p)[3] = num; 

NB합니다. 계속 읽기 어려울 수있는 *(*(num+1)+1))을 작성하십시오. 이 대신에 num[1][1] 훨씬 명확하게 보인다.

C에서 x[y]은 항상 정확히 *(x+y)과 같습니다.

+0

내가 할 수있는 건 알지만 포인터를 배우고 있기 때문에 포인터에 모든 코드를 쓰고 싶다. –