공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다.
sizeof(sizeof(포인터), sizeof(자료형 *))
로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p
를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit
시스템에서는 주소 값을 32bit
로 표현하기 때문에 포인터 변수의 크기가 4byte
인 반면, 64bit
시스템에서는 주소 값을 64bit
로 표현하기 때문에 포인터 변수의 크기가 8byte
이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 64bit
시스템에서 동작하는 컴파일러의 경우 64bit
로 컴파일을 하지만 32bit
로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 sizeof
연산의 결과로 8
을 확인하려면 64bit
시스템상에서 64bit
로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *
, char *
, double *
등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int *
형 포인터 변수가 double
형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&
연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 *
연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
*
연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum
은 포인터 변수 pnum
이 가리키는 변수 num
을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값
0
을 널 포인터라고 하는데,0
번지가 아닌 아무 데도 가리키지 않는다는 의미이다. - 키워드
NULL
도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수0
으로 정의되어 있다. - 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 *
연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const
를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const
를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr
을 이용해 ptr
이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 ptr
이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40;
문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const
가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const
를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다.
sizeof(sizeof(포인터), sizeof(자료형 *))
로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p
를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit
시스템에서는 주소 값을 32bit
로 표현하기 때문에 포인터 변수의 크기가 4byte
인 반면, 64bit
시스템에서는 주소 값을 64bit
로 표현하기 때문에 포인터 변수의 크기가 8byte
이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 64bit
시스템에서 동작하는 컴파일러의 경우 64bit
로 컴파일을 하지만 32bit
로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 sizeof
연산의 결과로 8
을 확인하려면 64bit
시스템상에서 64bit
로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *
, char *
, double *
등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int *
형 포인터 변수가 double
형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&
연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 *
연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
*
연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum
은 포인터 변수 pnum
이 가리키는 변수 num
을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값
0
을 널 포인터라고 하는데,0
번지가 아닌 아무 데도 가리키지 않는다는 의미이다. - 키워드
NULL
도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수0
으로 정의되어 있다. - 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 *
연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const
를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const
를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr
을 이용해 ptr
이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 ptr
이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40;
문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const
가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const
를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다. sizeof(sizeof(포인터), sizeof(자료형 *))로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit 시스템에서는 주소 값을 32bit로 표현하기 때문에 포인터 변수의 크기가 4byte인 반면, 64bit 시스템에서는 주소 값을 64bit로 표현하기 때문에 포인터 변수의 크기가 8byte이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 64bit
시스템에서 동작하는 컴파일러의 경우 64bit
로 컴파일을 하지만 32bit
로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 sizeof
연산의 결과로 8
을 확인하려면 64bit
시스템상에서 64bit
로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *, char *, double * 등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int * 형 포인터 변수가 double형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 *
연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
* 연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum은 포인터 변수 pnum이 가리키는 변수 num을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값 0을 널 포인터라고 하는데, 0번지가 아닌 아무 데도 가리키지 않는다는 의미이다.
- 키워드 NULL도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수 0으로 정의되어 있다.
- 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 * 연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr을 이용해 ptr이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 ptr
이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40; 문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다. sizeof(sizeof(포인터), sizeof(자료형 *))로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit 시스템에서는 주소 값을 32bit로 표현하기 때문에 포인터 변수의 크기가 4byte인 반면, 64bit 시스템에서는 주소 값을 64bit로 표현하기 때문에 포인터 변수의 크기가 8byte이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 64bit
시스템에서 동작하는 컴파일러의 경우 64bit
로 컴파일을 하지만 32bit
로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 sizeof
연산의 결과로 8
을 확인하려면 64bit
시스템상에서 64bit
로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *, char *, double * 등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int * 형 포인터 변수가 double형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 *
연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
* 연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum은 포인터 변수 pnum이 가리키는 변수 num을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값 0을 널 포인터라고 하는데, 0번지가 아닌 아무 데도 가리키지 않는다는 의미이다.
- 키워드 NULL도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수 0으로 정의되어 있다.
- 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 * 연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr을 이용해 ptr이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 ptr
이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40; 문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다.
sizeof(sizeof(포인터), sizeof(자료형 *))
로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p
를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit
시스템에서는 주소 값을 32bit
로 표현하기 때문에 포인터 변수의 크기가 4byte
인 반면, 64bit
시스템에서는 주소 값을 64bit
로 표현하기 때문에 포인터 변수의 크기가 8byte
이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 64bit
시스템에서 동작하는 컴파일러의 경우 64bit
로 컴파일을 하지만 32bit
로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 sizeof
연산의 결과로 8
을 확인하려면 64bit
시스템상에서 64bit
로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *
, char *
, double *
등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int *
형 포인터 변수가 double
형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&
연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 *
연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
*
연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum
은 포인터 변수 pnum
이 가리키는 변수 num
을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값
0
을 널 포인터라고 하는데,0
번지가 아닌 아무 데도 가리키지 않는다는 의미이다. - 키워드
NULL
도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수0
으로 정의되어 있다. - 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 *
연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const
를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const
를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr
을 이용해 ptr
이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 @@ptr@@이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40;
문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const
가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const
를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다.
sizeof(sizeof(포인터), sizeof(자료형 *))
로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p
를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit
시스템에서는 주소 값을 32bit
로 표현하기 때문에 포인터 변수의 크기가 4byte
인 반면, 64bit
시스템에서는 주소 값을 64bit
로 표현하기 때문에 포인터 변수의 크기가 8byte
이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 64bit
시스템에서 동작하는 컴파일러의 경우 64bit
로 컴파일을 하지만 32bit
로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 sizeof
연산의 결과로 8
을 확인하려면 64bit
시스템상에서 64bit
로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *
, char *
, double *
등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int *
형 포인터 변수가 double
형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&
연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 *
연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
*
연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum
은 포인터 변수 pnum
이 가리키는 변수 num
을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값
0
을 널 포인터라고 하는데,0
번지가 아닌 아무 데도 가리키지 않는다는 의미이다. - 키워드
NULL
도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수0
으로 정의되어 있다. - 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 *
연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const
를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const
를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr
을 이용해 ptr
이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 @@ptr@@이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40;
문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const
가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const
를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다. sizeof(sizeof(포인터), sizeof(자료형 *))로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit 시스템에서는 주소 값을 32bit로 표현하기 때문에 포인터 변수의 크기가 4byte인 반면, 64bit 시스템에서는 주소 값을 64bit로 표현하기 때문에 포인터 변수의 크기가 8byte이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 64bit
시스템에서 동작하는 컴파일러의 경우 64bit
로 컴파일을 하지만 32bit
로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 sizeof
연산의 결과로 8
을 확인하려면 64bit
시스템상에서 64bit
로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *, char *, double * 등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int * 형 포인터 변수가 double형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 *
연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
* 연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum은 포인터 변수 pnum이 가리키는 변수 num을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값 0을 널 포인터라고 하는데, 0번지가 아닌 아무 데도 가리키지 않는다는 의미이다.
- 키워드 NULL도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수 0으로 정의되어 있다.
- 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 * 연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr을 이용해 ptr이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 @@ptr@@이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40; 문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다. sizeof(sizeof(포인터), sizeof(자료형 *))로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit 시스템에서는 주소 값을 32bit로 표현하기 때문에 포인터 변수의 크기가 4byte인 반면, 64bit 시스템에서는 주소 값을 64bit로 표현하기 때문에 포인터 변수의 크기가 8byte이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 64bit
시스템에서 동작하는 컴파일러의 경우 64bit
로 컴파일을 하지만 32bit
로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 sizeof
연산의 결과로 8
을 확인하려면 64bit
시스템상에서 64bit
로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *, char *, double * 등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int * 형 포인터 변수가 double형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 *
연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
* 연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum은 포인터 변수 pnum이 가리키는 변수 num을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값 0을 널 포인터라고 하는데, 0번지가 아닌 아무 데도 가리키지 않는다는 의미이다.
- 키워드 NULL도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수 0으로 정의되어 있다.
- 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 * 연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr을 이용해 ptr이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 @@ptr@@이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40; 문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다.
sizeof(sizeof(포인터), sizeof(자료형 *))
로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p
를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit
시스템에서는 주소 값을 32bit
로 표현하기 때문에 포인터 변수의 크기가 4byte
인 반면, 64bit
시스템에서는 주소 값을 64bit
로 표현하기 때문에 포인터 변수의 크기가 8byte
이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 ##64bit## 시스템에서 동작하는 컴파일러의 경우 ##64bit##로 컴파일을 하지만 ##32bit##로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 ##sizeof## 연산의 결과로 ##8##을 확인하려면 ##64bit## 시스템상에서 ##64bit##로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *
, char *
, double *
등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int *
형 포인터 변수가 double
형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&
연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 ##*##연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
*
연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum
은 포인터 변수 pnum
이 가리키는 변수 num
을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값
0
을 널 포인터라고 하는데,0
번지가 아닌 아무 데도 가리키지 않는다는 의미이다. - 키워드
NULL
도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수0
으로 정의되어 있다. - 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 *
연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const
를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const
를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr
을 이용해 ptr
이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 ptr
이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40;
문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const
가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const
를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다.
sizeof(sizeof(포인터), sizeof(자료형 *))
로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p
를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit
시스템에서는 주소 값을 32bit
로 표현하기 때문에 포인터 변수의 크기가 4byte
인 반면, 64bit
시스템에서는 주소 값을 64bit
로 표현하기 때문에 포인터 변수의 크기가 8byte
이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 ##64bit## 시스템에서 동작하는 컴파일러의 경우 ##64bit##로 컴파일을 하지만 ##32bit##로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 ##sizeof## 연산의 결과로 ##8##을 확인하려면 ##64bit## 시스템상에서 ##64bit##로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *
, char *
, double *
등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int *
형 포인터 변수가 double
형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&
연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 ##*##연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
*
연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum
은 포인터 변수 pnum
이 가리키는 변수 num
을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값
0
을 널 포인터라고 하는데,0
번지가 아닌 아무 데도 가리키지 않는다는 의미이다. - 키워드
NULL
도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수0
으로 정의되어 있다. - 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 *
연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const
를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const
를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr
을 이용해 ptr
이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 ptr
이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40;
문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const
가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const
를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다. sizeof(sizeof(포인터), sizeof(자료형 *))로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit 시스템에서는 주소 값을 32bit로 표현하기 때문에 포인터 변수의 크기가 4byte인 반면, 64bit 시스템에서는 주소 값을 64bit로 표현하기 때문에 포인터 변수의 크기가 8byte이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 ##64bit## 시스템에서 동작하는 컴파일러의 경우 ##64bit##로 컴파일을 하지만 ##32bit##로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 ##sizeof## 연산의 결과로 ##8##을 확인하려면 ##64bit## 시스템상에서 ##64bit##로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *, char *, double * 등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int * 형 포인터 변수가 double형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 ##*##연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
* 연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum은 포인터 변수 pnum이 가리키는 변수 num을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값 0을 널 포인터라고 하는데, 0번지가 아닌 아무 데도 가리키지 않는다는 의미이다.
- 키워드 NULL도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수 0으로 정의되어 있다.
- 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 * 연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr을 이용해 ptr이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 ptr
이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40; 문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다. sizeof(sizeof(포인터), sizeof(자료형 *))로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit 시스템에서는 주소 값을 32bit로 표현하기 때문에 포인터 변수의 크기가 4byte인 반면, 64bit 시스템에서는 주소 값을 64bit로 표현하기 때문에 포인터 변수의 크기가 8byte이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 ##64bit## 시스템에서 동작하는 컴파일러의 경우 ##64bit##로 컴파일을 하지만 ##32bit##로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 ##sizeof## 연산의 결과로 ##8##을 확인하려면 ##64bit## 시스템상에서 ##64bit##로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *, char *, double * 등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int * 형 포인터 변수가 double형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 ##*##연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
* 연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum은 포인터 변수 pnum이 가리키는 변수 num을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값 0을 널 포인터라고 하는데, 0번지가 아닌 아무 데도 가리키지 않는다는 의미이다.
- 키워드 NULL도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수 0으로 정의되어 있다.
- 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 * 연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr을 이용해 ptr이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 ptr
이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40; 문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다.
sizeof(sizeof(포인터), sizeof(자료형 *))
로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p
를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit
시스템에서는 주소 값을 32bit
로 표현하기 때문에 포인터 변수의 크기가 4byte
인 반면, 64bit
시스템에서는 주소 값을 64bit
로 표현하기 때문에 포인터 변수의 크기가 8byte
이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 ##64bit## 시스템에서 동작하는 컴파일러의 경우 ##64bit##로 컴파일을 하지만 ##32bit##로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 ##sizeof## 연산의 결과로 ##8##을 확인하려면 ##64bit## 시스템상에서 ##64bit##로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *
, char *
, double *
등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int *
형 포인터 변수가 double
형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&
연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 ##*##연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
*
연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum
은 포인터 변수 pnum
이 가리키는 변수 num
을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값
0
을 널 포인터라고 하는데,0
번지가 아닌 아무 데도 가리키지 않는다는 의미이다. - 키워드
NULL
도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수0
으로 정의되어 있다. - 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 *
연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const
를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const
를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr
을 이용해 ptr
이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 @@ptr@@이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40;
문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const
가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const
를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다.
sizeof(sizeof(포인터), sizeof(자료형 *))
로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p
를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit
시스템에서는 주소 값을 32bit
로 표현하기 때문에 포인터 변수의 크기가 4byte
인 반면, 64bit
시스템에서는 주소 값을 64bit
로 표현하기 때문에 포인터 변수의 크기가 8byte
이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 ##64bit## 시스템에서 동작하는 컴파일러의 경우 ##64bit##로 컴파일을 하지만 ##32bit##로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 ##sizeof## 연산의 결과로 ##8##을 확인하려면 ##64bit## 시스템상에서 ##64bit##로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *
, char *
, double *
등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int *
형 포인터 변수가 double
형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&
연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 ##*##연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
*
연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum
은 포인터 변수 pnum
이 가리키는 변수 num
을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값
0
을 널 포인터라고 하는데,0
번지가 아닌 아무 데도 가리키지 않는다는 의미이다. - 키워드
NULL
도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수0
으로 정의되어 있다. - 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 *
연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const
를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const
를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr
을 이용해 ptr
이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 @@ptr@@이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40;
문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const
가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const
를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다. sizeof(sizeof(포인터), sizeof(자료형 *))로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit 시스템에서는 주소 값을 32bit로 표현하기 때문에 포인터 변수의 크기가 4byte인 반면, 64bit 시스템에서는 주소 값을 64bit로 표현하기 때문에 포인터 변수의 크기가 8byte이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 ##64bit## 시스템에서 동작하는 컴파일러의 경우 ##64bit##로 컴파일을 하지만 ##32bit##로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 ##sizeof## 연산의 결과로 ##8##을 확인하려면 ##64bit## 시스템상에서 ##64bit##로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *, char *, double * 등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int * 형 포인터 변수가 double형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 ##*##연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
* 연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum은 포인터 변수 pnum이 가리키는 변수 num을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값 0을 널 포인터라고 하는데, 0번지가 아닌 아무 데도 가리키지 않는다는 의미이다.
- 키워드 NULL도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수 0으로 정의되어 있다.
- 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 * 연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr을 이용해 ptr이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 @@ptr@@이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40; 문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |
공부했던 자료 정리하는 용도입니다.
재배포, 수정하지 마세요.
포인터
- 포인터
- 포인터 변수
- 포인터 변수의 선언
* 포인터 변수의 크기 - 포인터 형(type)
- 포인터 변수와 관련된 연산자
1. & 연산자
2. * 연산자 - null 포인터
- 포인터 대상의 const 선언
* 상수를 가리키는 포인터인 경우
* 포인터 자체가 상수인 경우
* 포인터가 상수이면서 상수를 가리키는 경우
- 포인터와 배열
- 포인터 연산
- 문자열의 선언방식
- 포인터 배열
* 문자열 배열
- 포인터와 함수
- 함수의 호출 방식
* Call-by-value
* Call-by-reference - 함수의 인자로 배열 전달
* 인자로 배열 전달 시 배열의 크기
- 함수의 호출 방식
- 이중 포인터(더블 포인터)
- 이중 포인터 선언과 사용
- 포인터 변수 대상의 Call-by-reference
- 포인터 배열과 포인터 배열의 포인터 type
- 다중 포인터 변수
- 다차원 배열과 포인터
- 2차원 배열의 이름과, 2차원 배열의 첫 번째 행
- 2차원 배열의 증감 연산
- 2차원 배열의 포인터
- 함수 인자로 2차원 배열 전달
- 다차원 배열에서 arr[i]와 *(arr + i)
- 배열 포인터와 포인터 배열
- main 함수의 인자
* 인자의 형성 과정
* char * argv[ ]
- 함수 포인터
- 함수 포인터 변수 선언
- void 포인터
포인터
- 포인터를 이용하면 메모리에 직접 접근이 가능하다. 그래서 C언어가 Low 레벨 언어의 특성을 지닌다고 말한다.
- 시스템이 몇 비트인지에 따라 메모리 주소의 범위도 달라진다. sizeof(sizeof(포인터), sizeof(자료형 *))로 포인터의 크기를 구해보면 32 bit에서는 4 byte, 64 bit에서는 8 byte가 나온다.
32 bit : 16진수 8자리
0x00000000 ~ 0xFFFFFFFF
64 bit : 16진수 16자리
8자리씩 끊어서 백틱을 붙이기도 한다. ex) 0x00000000`00000000
0x0000000000000000 ~ 0xFFFFFFFFFFFFFFFF
■ 리눅스, OS X에서 %p
리눅스나 OS X에서 서식 지정자 %p를 사용하면 메모리 주소 앞에 0x가 붙고 A~F는 소문자로 출력된다. 또한 높은 자리수의 0은 생략된다.
ex) 008AF7FC → 0x8af7fc
포인터 변수
- 포인터 변수는 메모리의 주소 값을 저장하기 위한 변수이다.
C언어는 시작 번지만을 가지고 위치를 표현한다. (자료형에 따라 끝 위치가 어딘지 계산이 가능하기 때문) - 포인터는 '변수 형태의 포인터'와 '상수 형태의 포인터'를 어우르는 표현이다. (대부분의 경우 포인터 변수를 의미)
포인터 변수 선언
int * pnum1; // int형 변수를 가리키는 pnum1 선언
unsigned int * pnum2; // unsigned int형 변수를 가리키는 pnum2 선언
// *의 위치는 상관 X (아래 3문장은 모두 동일한 의미)
double * ptr;
double* ptr;
double *ptr;
(주소 값은 동일한 시스템에서 그 크기가 동일하며 모두 정수의 형태를 띄지만) 가리키는 변수의 자료형에 따라서 선언하는 방법이 달라진다.
■ 포인터 변수의 크기

포인터 변수의 크기는 운영체제마다 다르다. 32bit 시스템에서는 주소 값을 32bit로 표현하기 때문에 포인터 변수의 크기가 4byte인 반면, 64bit 시스템에서는 주소 값을 64bit로 표현하기 때문에 포인터 변수의 크기가 8byte이다.(주소 값의 크기와 포인터 변수의 크기는 같다.) 그러나 ##64bit## 시스템에서 동작하는 컴파일러의 경우 ##64bit##로 컴파일을 하지만 ##32bit##로도 컴파일을 할 수 있다. 따라서 포인터 변수 대상의 ##sizeof## 연산의 결과로 ##8##을 확인하려면 ##64bit## 시스템상에서 ##64bit##로 컴파일해야 한다.
포인터 형(type)
포인터 변수의 선언 및 구분에 사용되는 int *, char *, double * 등을 가리켜 포인터 형(type)이라고 한다. 포인터 변수도 값을 저장하는 변수이기 때문에 포인터 형도 자료형의 범주에 포함시키기도 한다. 포인터형은 메모리 공간을 참조하는 기준이 되기 때문에 포인터 형에 맞지 않는 자료형의 변수를 참조(int * 형 포인터 변수가 double형 변수를 참조한다던지)하면 안 된다(경고 메시지는 출력되지만 컴파일 에러가 발생하지는 X)
포인터 변수와 관련된 연산자
■ & 연산자
int num = 6;
int * pnum = # // num의 주소값을 반환해서 포인터 변수 pnum을 초기화
&연산자는 오른쪽에 등장하는 피연산자의 주소 값을 반환하는 연산자이다. 피연산자는 변수여야 하며, 상수는 피연산자가 될 수 없다. 또한 변수의 자료형에 맞지 않는 포인터 변수의 선언은 문제가 될 수 있다.(컴파일 에러는 발생하지 않지만 경고 메시지는 발생하며 포인터 관련 ##*##연산 시 문제가 발생한다.)
■ * 연산자(역참조 연산자)
int num = 10;
int * pnum = # // 포인터 변수 pnum이 변수 num을 가리키게 하는 문장
*pnum = 20; // pnum이 가리키는 변수에 20을 저장
printf("%d", *pnum); // pnum이 가리키는 변수를 출력
* 연산자는 포인터가 가리키는 메모리 공간에 접근할 때 사용하는 연산자이다.
위의 경우 사실상 *pnum은 포인터 변수 pnum이 가리키는 변수 num을 의미한다.
- 포인터의 자료형과 역참조
char *cPtr; // char형 포인터
*cPtra = 'a'; // 1 byte(char의 크기)만큼 역참조하여 값을 저장
short *sPtr; // short형 포인터
*sPtr1 = 100; // 2 byte(short의 크기)만큼 역참조하여 값을 저장
int *iPtr; // int형 포인터
*nPtr = 100; // 4 byte(int의 크기)만큼 역참조하여 값을 저장
long long *lPtr; // long long형 포인터 선언
*lPtr = 100; // 8 byte(long long의 크기)만큼 역참조하여 값을 저장
포인터는 포인터를 선언한 자료형의 크기만큼 역참조 하는 크기가 결정된다.
null 포인터
// 아래 두 문장은 같은의미이다.
int * ptr1 = 0;
int * ptr2 = NULL: // NULL 은 0을 의미
- 값 0을 널 포인터라고 하는데, 0번지가 아닌 아무 데도 가리키지 않는다는 의미이다.
- 키워드 NULL도 마찬가지로 널 포인터를 의미하며, 실제로 이는 상수 0으로 정의되어 있다.
- 아무것도 가리키지 않는 상태이기 때문에 역참조는 할 수 없다.
포인터 변수는 선언만 하고 초기화하지 않으면 쓰레기 값으로 초기화된다. 우선 선언만 해놓고 이후에 주소를 가리키게 하려면 위와 같이 초기화하면 된다. null 포인터를 이용한 * 연산은 메모리 공간에 어떠한 영향도 미치지 않으며, 프로그램이 멈추는 현상은 동일하게 일어나지만, 잘못된 메모리 접근에 대해 보호장치가 없는 운영체제에서도 시스템에 치명적인 영향을 주지 않는다.
포인터 대상의 const 선언
//1. 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
const int num = 10;
const int *numPtr; // int형 상수를 가리키는 포인터. int const *numPtr도 같음
numPtr = &num1;
*numPtr = 20; // error. num1이 상수이므로 역참조로 값 변경 불가
//2. 포인터 자체가 상수(constant pointer)인 경우: 메모리 주소를 변경할 수 없다는 의미
int num1 = 10;
int num2 = 20;
int * const numPtr = &num1; // int형 포인터 상수
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
//3. 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 모두 변경할 수 없다는 의미
const int num1 = 10;
const int num2 = 20;
const int * const numPtr = &num1; // int형 상수를 가리키는 포인터 상수. int const * const numPtr도 같음
*numPtr = 30; // error. num1이 상수이므로 역참조로 값 변경 불가
numPtr = &num2; // error. 포인터(메모리 주소) 변경 불가
포인터에도 const를 붙일 수 있는데, 위치에 따라 특성이 달라진다.
- 상수를 가리키는 포인터(pointer to constant)인 경우 : 메모리 주소에 저장된 값을 변경할 수 없다는 의미
- 포인터 자체가 상수인 경우(constant pointer)인 경우 : 메모리 주소를 변경할 수 없다는 의미
- 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant) : 메모리 주소에 저장된 값과 메모리 주소 둘 다 변경할 수 없다는 의미
■ 상수를 가리키는 포인터(pointer to constant)인 경우
int num = 20;
const int * ptr = #
*ptr = 30 // error
num = 40; // 가능
const를 맨 앞에 선언하면 '포인터 변수를 이용해 포인터 변수가 가리키는 값의 변경을 허용하지 않겠다'라는 의미이다. (값의 변경 방법 제한) 위의 예시의 경우 ptr을 이용해 ptr이 가리키는 변수의 값을 변경할 수 없다. 그러나 포인터 변수 @@ptr@@이 가리키는 변수가 상수화 되는 것은 아니다. 위의 예시처럼 포인터 변수를 이용하지 않는 num = 40; 문장은 허용된다.
■ 포인터 자체가 상수(constant pointer)인 경우
int num1 = 20;
int num2 = 30;
int * const ptr = &num1;
ptr = &num2; // error
*ptr = 40; // 가능
포인터 변수 앞에 const가 오면 포인터 변수가 상수가 된다. (한번 주소 값이 저장되면 변경 불가) 포인터 변수가 상수가 되는 것이라 포인터가 가리키는 대상에 저장된 값을 변경하는 것은 가능하다.
■ 포인터가 상수이면서 상수를 가리키는 상황(constant pointer to constant)인 경우
const int * const ptr = #
앞서 말한 두 가지 형태의 const를 동시에 선언하는 것도 가능하다. 동시에 선언하면 해당 포인터 변수로 포인터 변수가 참조하는 변수의 값도 변경할 수 없고, 포인터 변수를 변경하는 것도 불가능하다.
'기타 > C' 카테고리의 다른 글
[C]이중 포인터(더블 포인터) (0) | 2020.05.12 |
---|---|
[C] 포인터와 배열, 함수 (0) | 2020.05.07 |
[C] 배열 (1차원 배열, 다차원 배열, 가변 길이 배열) (1) | 2020.04.28 |
[C] 함수 (0) | 2020.04.27 |
[C] 조건문, 반복문 (0) | 2020.04.16 |