포인터는 이해하는 것이 중요한 것이지 외우는 것이 중요하지는 않습니다.
저 같은 경우는 자주 사용하는 포인터는 항상 머리속에 있지만 그렇지 않은 포인터들은 이렇게 정리해 놓고 보고 쓰곤 합니다.
여러분들도 그렇게 하는 것이 좋지 않을까 생각합니다.
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include <conio.h>
#pragma warning(disable:4101) // C4101 경고 에러 제거
void main( void )
{
/* 기본 포인터 int*/
{
int i;
int* pi1; // 선언 방법 1 (권장)
int *pi2; // 선언 방법 2
int * pi3; // 선언 방법 3
pi2 = &i; // i의 번지값을 대입
// 변수에 값을 대입 (세 문장은 모두 동일)
i = 5; // 직접 대입
*pi2 = 5; // pi2 변수의 값(i의 번지)의 번지에 간접 접근해서 대입
pi2[0] = 5; // pi2 변수의 0번째 배열 요소에 접근해서 대입
}
//*/
//.// 일반 변수의 크기 (각 데이터형이 차지하는 메모리 크기)
printf( "%d \n", sizeof(char) ); // 1 바이트
printf( "%d \n", sizeof(int) ); // 4 바이트
printf( "%d \n", sizeof(long) ); // 4 바이트
printf( "%d \n", sizeof(float) ); // 4 바이트
printf( "%d \n", sizeof(double) ); // 8 바이트
//.// 포인터 변수의 크기 (번지값을 저장하기 위한 변수이므로 모두 4)
printf( "%d \n", sizeof(char*) ); // 4 바이트
printf( "%d \n", sizeof(int*) ); // 4 바이트
printf( "%d \n", sizeof(long*) ); // 4 바이트
printf( "%d \n", sizeof(float*) ); // 4 바이트
printf( "%d \n", sizeof(double*) ); // 4 바이트
/* 문자형 포인터 char*/
{
char ch;
char* pch;
pch = &ch;
ch = 'a'; // 변수에 값을 대입 (세 문장은 모두 동일)
*pch = 'a'; // pi 변수의 값(i의 번지)의 번지에 간접 접근해서 대입
pch[0] = 'a'; // pi 변수의 0번째 배열 요소에 접근해서 대입
}
//*/
/* 문자열형 포인터 char*/
{
char string[10] = "winter";
char* pstr;
pstr = string; // 선두 번지 상수 값
pstr = &string[0]; // 0번째 요소의 번지 값
*pstr = 'W'; // 첫 번째 요소에 'W'를 대입
pstr[0] = 'W'; // 첫 번째 요소에 'W'를 대입
*(pstr+0) = 'W'; // 첫 번째 요소에 'W'를 대입
pstr[1] = 'I'; // 두 번째 요소에 'I'를 대입
*(pstr+1) = 'I'; // 두 번째 요소에 'I'를 대입
pstr++; // 1번지 만큼 증가, ++pstr도 동일
*pstr = 'I'; // 두 번째 요소에 'I'를 대입
pstr[0] = 'I'; // 두 번째 요소에 'I'를 대입, pstr이 1증가했기 때문
*(pstr+0) = 'I'; // 두 번째 요소에 'I'를 대입
pstr--; // 1번지 만큼 감소, --pstr도 동일
strcpy( string , "summer" ); // string과 pstr은 같은 번지 값
strcpy( &string[0], "summer" ); // string과 &string[0]은 같은 번지 값
strcpy( pstr , "summer" ); // strcpy는 같은 번지를 넘겨 받음
strcpy( string+2 , "summer" ); // string+2는 &string[2]와 동일
strcpy( &string[2], "summer" ); //
strcpy( pstr+2 , "summer" ); //
}
//*/
/* 문자열형 포인터 char*의 잘못된 사용 */
{
char* pstr = "winter"; // pstr은 상수 영역 포인터
char* ptmp; // 임시 포인터
*pstr = 'W'; // 상수 영역을 읽기만 가능, 프로그램 다운
pstr[0] = 'W'; // 상수 영역을 읽기만 가능, 프로그램 다운
*(pstr+0) = 'W'; // 상수 영역을 읽기만 가능, 프로그램 다운
ptmp = pstr; // pstr 값과 일치 시킴
*ptmp = 'W'; // pstr과 같은 번지 값을 갖기 때문에 프로그램 다운
ptmp[0] = 'W'; // pstr과 같은 번지 값을 갖기 때문에 프로그램 다운
*(ptmp+0) = 'W'; // pstr과 같은 번지 값을 갖기 때문에 프로그램 다운
printf( "%c", *pstr ); // w가 출력, 읽기는 가능
printf( "%c", pstr[0] ); // w가 출력, 읽기는 가능
pstr++;
printf( "%c", *pstr ); // i가 출력, 읽기는 가능
printf( "%c", pstr[0] ); // i가 출력, pstr++로 pstr의 시작 번지가 1증가됨
pstr--;
strcpy( pstr, "summer" ); // 상수 영역에 summer 복사 불가능
strcpy( ptmp, "summer" ); // pstr == ptmp 이므로 불가능
printf( pstr ); // winter가 출력, 읽기는 가능
printf( ptmp ); // winter가 출력, 일기는 가능
}
//*/
/* 1차원 정수형 배열의 포인터 int*
{
int array[5] = { 1, 2, 3, 4, 5 };
int* p;
p = array; // 배열의 선두 번지
p = &array[0]; // 배열의 선두 번지
p = array + 1; // 배열의 두 번째 번지
p = &array[1]; // 배열의 두 번째 번지
p = array;
*p = 100; // 현재 p가 가리키는 요소에 100을 대입
p[0] = 100; // 현재 p가 가리키는 0번째 요소에 100을 대입
*(p+0) = 100; // 현재 p가 가리키는 0번째 요소에 100을 대입
p++; // int형 데이터 배열이므로 4가 증가 (중요)
p = p + 1; // p++과 동일, 4가 증가
p = p + 2; // 8이 증가, (sizeof(int) * 2) == 8
}
//*/
/* 2차원 정수형 배열의 포인터 int (*)[]
{
int array[2][3] = { 1, 2, 3, 4, 5, 6 };
int (*p)[3];
int **p2;
p = array; // 배열의 선두 번지, int (*)[3]
p = &array[0]; // 배열의 선두 번지
printf( "%#x \n", p[1] ); // 0x12ff34
printf( "%#x \n", p+1 ); // 0x12ff34
printf( "%#x \n", *(p+1) ); // 0x12ff34
printf( "%d \n", **(p+1) ); // 4
printf( "%d \n", *(*(p+1)) ); // 4
printf( "%d \n", *(*(p+1)+0) ); // 4
printf( "%d \n", *(*(p+1)+1) ); // 5
printf( "%d \n", *(*(p+1)+2) ); // 6
//p = &array[0][0]; - 틀림, &array[0][0]은 int *
//p = array[0]; - 틀림, array [0] 은 int *
//p = array [0][0]; - 틀림, array [0][0]은 int
p = array + 1; // 배열의 두 번째 번지
p = &array[1]; // 배열의 두 번째 번지
p = array;
p[0][0] = 100; // 현재 p가 가리키는 [0][0]번째 요소에 100을 대입
*(*(p+0)+0) = 100; // 현재 p가 가리키는 [0][0]번째 요소에 100을 대입
p[1][2] = 200; // 현재 p가 가리키는 [1][2]번째 요소에 100을 대입
*(*(p+1)+2) = 200; // 현재 p가 가리키는 [1][2]번째 요소에 100을 대입
p++; // int(*)[3]형 배열이므로 12가 증가 sizeof(int) * 3
p = p + 1; // p++과 동일, 12가 증가
p = p + 2; // 24가 증가, (sizeof(int) * 3 * 2)
}
//*/
/* 2차원 배열을 int *로 사용
{
int array[2][3] = { 1, 2, 3, 4, 5, 6 };
int *p;
int i;
p = array[0]; // 배열의 선두 번지, int *
for( i=0; i<sizeof(array)/sizeof(int)/2; i++ )
{
printf( "%d \n", *p++ );
}
//p = &array[0]; - 틀림 int (*)[3]
p = &array[0][0]; // 첫 번째 배열의 주소
p = &array[0][1]; // 두 번째 배열의 주소
p = &array[1][0]; // 네 번째 배열의 주소
printf( "%d \n", p[0] ); // 4
printf( "%#x \n", p+0 ); // 0x12ff14
printf( "%d \n", *(p+0) ); // 4
printf( "%d \n", *(p+1) ); // 5
printf( "%d \n", *(p+2) ); // 6
p = array[0]; // 배열의 선두 번지, int *
p[0] = 100; // 현재 p가 가리키는 [0][0]번째 요소에 100을 대입
*(p+0) = 100; // 현재 p가 가리키는 [0][0]번째 요소에 100을 대입
p[1] = 200; // 현재 p가 가리키는 [1][2]번째 요소에 100을 대입
*(p+1) = 200; // 현재 p가 가리키는 [1][2]번째 요소에 100을 대입
p++; // int*형이므로 4만 증가
p = p + 1; // p++과 동일, 4가 증가
p = p + 2; // 8이 증가, sizeof(int) * 2
}
//*/
/* 3차원 정수형 배열의 포인터 int (*)[][]
{
int array[2][3][4] =
{
{ { 1, 2, 3, 4}, { 5, 6, 7, 8}, { 9, 10, 11, 12} },
{ {13, 14, 15, 16}, {17, 18, 19, 20}, {21, 22, 23, 24} }
};
int (*p)[3][4];
int ***p2;
p = array; // 배열의 선두 번지, int (*)[3][4]
p = &array[0]; // 배열의 선두 번지
printf( "%#x \n", p[0] ); // 0x12fea0
printf( "%#x \n", p+0 ); // 0x12fea0
printf( "%#x \n", p+1 ); // 0x12fed0 <-
printf( "%#x \n", *(p+0) ); // 0x12fea0
printf( "%#x \n", **(p+0) ); // 0x12fea0
printf( "%d \n", ***(p+0) ); // 1
printf( "%#x \n", *(*(p+0)) ); // 0x12fea0
printf( "%#x \n", *(*(p+0)+0) ); // 0x12fea0
printf( "%#x \n", *(*(p+0)+1) ); // 0x12feb0 <-
printf( "%#x \n", *(*(p+0)+2) ); // 0x12fec0 <-
printf( "%d \n", *(*(*(p+0)+0)+0) ); // 1 , p[0][0][0] == [0]
printf( "%d \n", *(*(*(p+0)+0)+1) ); // 2 , p[0][0][1] == [1]
printf( "%d \n", *(*(*(p+0)+0)+2) ); // 3 , p[0][0][2] == [2]
printf( "%d \n", *(*(*(p+0)+0)+3) ); // 4 , p[0][0][3] == [3]
printf( "%d \n", *(*(*(p+0)+1)+0) ); // 5 , p[0][1][0] == [4]
printf( "%d \n", *(*(*(p+0)+1)+1) ); // 6 , p[0][1][1] == [5]
printf( "%d \n", *(*(*(p+0)+1)+2) ); // 7 , p[0][1][2] == [6]
printf( "%d \n", *(*(*(p+0)+1)+3) ); // 8 , p[0][1][2] == [7]
printf( "%d \n", *(*(*(p+1)+2)+0) ); // 21 , p[1][2][0] == [20]
printf( "%d \n", *(*(*(p+1)+2)+1) ); // 22 , p[1][2][1] == [21]
printf( "%d \n", *(*(*(p+1)+2)+2) ); // 23 , p[1][2][2] == [22]
printf( "%d \n", *(*(*(p+1)+2)+3) ); // 23 , p[1][2][3] == [23]
p++; // 48이 증가 sizeof(int) * 3 * 4
p = p + 1; // p++과 동일, 48이 증가
p = p + 2; // 96이 증가, sizeof(int) * 3 * 4 * 2
}
//*/
/* 구조체 포인터
{
struct Jusorok
{
int data;
char name[20];
int *p;
struct Jusorok* next;
};
struct Jusorok J;
struct Jusorok* PJ;
//PJ = J; // 타입 불일치 에러
PJ = &J; // 올바른 표현
J.data = 5;
strcpy( J.name, "이상미" );
J.p = (int*) malloc( 500 );
J.next = NULL;
printf( "%d \n", J.data ); // pJ->data 와 동일
printf( "%d \n", PJ->data ); // J.data와 동일
}
//*/
/* 링크드 리스트
{
typedef struct tagList
{
int data;
struct tagList* next;
} LIST, *PLIST;
PLIST p;
PLIST Head, Tail;
p = (PLIST) malloc( sizeof(LIST) );
memset( p, 0, sizeof(LIST) );
p->data = 1;
Head = Tail = p;
printf( "%#x \n", &p ); // 0x12fe70
printf( "%#x \n", p ); // 0x3733e0
printf( "%#x \n", &p->data ); // 0x3733e0
printf( "%d \n", p->data ); // 1
printf( "%#x \n", &p->next ); // 0x3733e4
printf( "%#x \n", p->next ); // 0
p = (PLIST) malloc( sizeof(LIST) );
memset( p, 0, sizeof(LIST) );
p->data = 2;
Tail->next = p;
Tail = p;
printf( "%#x \n", &p ); // 0x12fe70
printf( "%#x \n", p ); // 0x373418
printf( "%#x \n", &p->data ); // 0x373418
printf( "%d \n", p->data ); // 2
printf( "%#x \n", &p->next ); // 0x37341c
printf( "%#x \n", p->next ); // 0
p = Head;
while( p )
{
printf( "%d \n", p->data ); // 1, 2
p = p->next;
}
}
//*/
/* 1차원 구조체 배열
{
typedef struct
{
int data;
} ARRAY;
ARRAY array[10];
ARRAY *p;
int i;
for( i=0; i<sizeof(array)/sizeof(ARRAY); i++ )
{
array[i].data = i;
}
p = array;
for( i=0; i<sizeof(array)/sizeof(ARRAY); i++ )
{
printf( "%d \n", p[i].data );
printf( "%d \n", (*(p+i)).data );
printf( "%d \n", (p+i)->data );
}
}
//*/
/* 함수 포인터
{
int (*LEN) ( const char* );
typedef int(*FLEN) ( const char* );
FLEN l1, l2;
FLEN f[3] = { strlen, strlen, strlen };
LEN = strlen;
l1 = l2 = strlen;
printf( "%d \n", strlen ("12345") ); // 5
printf( "%d \n", LEN ("12345") ); // 5
printf( "%d \n", l1 ("12345") ); // 5
printf( "%d \n", l2 ("12345") ); // 5
printf( "%d \n", f[0] ("12345") ); // 5
printf( "%d \n", (f[1]) ("12345") ); // 5
printf( "%d \n", (*f[2])("12345") ); // 5
}
//*/
/* 표현식
{
int number[] = {0,1,2,3,4,5,6,7,8,9};
char *p;
p = number;
printf( "%d \n", *p++ );
printf( "%d \n", *p-- );
printf( "%d \n", *++p );
printf( "%d \n", ++*p );
printf( "%d \n", (*p)++ );
printf( "%d \n", (*p)-- );
printf( "%d \n", *(p+1) );
printf( "%d \n", *(1+p) );
}
//*/
}
[프로그래밍/C언어] 정수, 실수 데이터형 (0) | 2016.11.21 |
---|---|
C언어, C++, C#, JAVA, Visual C++, MFC, Direct X? (0) | 2016.11.16 |
[프로그래밍/C] scanf()로 공백도(정규식) 입력 받자! (0) | 2016.11.16 |
[프로그래밍/C] 함수 return 에서의 실수 (0) | 2016.10.14 |
The Top 10 Ways to get screwed by the "C" programming language (0) | 2016.10.12 |