티스토리 뷰
포인터는 c언어가 Low 레벨 언어의 특성을 지닌다고 이야기하게 만든 장본인이다. 왜냐하면 포인터를 이용하면 메모리에 직접 접근이 가능하기 때문이다.
포인터 변수란 메모리의 주소 값을 저장하기 위한 변수이다.
포인터 변수의 크기는 64비트에서는 8바이트(=64비트 시스템에서는 주소 값을 64비트로 표현하니까),
32비트에서는 4바이트
int num=7;
int * pnum; // 포인터 변수 pnum의 선언
pnum = # // num의 주소 값을 포인터 변수 pnum에 저장(변수만 저장가능, 상수x)
변수의 주소 값을 반환하는 & 연산자
포인터가 가리키는 메모리를 참조하는 * 연산자
다양한 포인터 형이 존재하는 이유 : 포인터 형은 메모리 공간을 참조하는 기준이 된다.(형의 일치)
포인터 변수의 값은 0 또는 NULL로 초기화 해야 돼!!(널 포인터 - 아무데도 가리키지 않는다)
int * ptr1=0;
int * ptr2=NULL; // NULL은 사실상 0을 의미
예제
#include <stdio.h>
int main(void)
{
int num1 = 10, num2 = 20;
int * ptr1 = &num1, * ptr2 = &num2;
int* temp;
(*ptr1) += 10;
(*ptr2) -= 10;
temp = ptr1;
ptr1 = ptr2;
ptr2 = temp;
printf("ptr1 %d, ptr2 %d", *ptr1, *ptr2);
return 0;
}
배열
배열의 이름은 포인터이다. 단, 그 값을 바꿀 수 없는 상수 형태의 포인터이다.(포인터 상수라고도 불림)
=> 배열의 이름을 피연산자로 하는 * 연산이 가능
ex)
#include <stdio.h>
int main(void)
{
int arr[3]={0, 1, 2};
printf("배열의 이름: %p \n", arr); //0012FF50
printf("첫 번째 요소: %p \n", &arr[0]); //0012FF50
printf("두 번째 요소: %p \n", &arr[1]); //0012FF54
printf("세 번째 요소: %p \n", &arr[2]); //0012FF58
return 0;
}
=> int형 배열요소간 주소 값의 차는 4바이트, 배열의 이름은 배열의 시작 주소값
int * ptr=arr; // int * ptr=&arr[0]; 과 같음
type형 포인터를 대상으로 n의 크기만큼 값을 증가 및 감소 시, n * sizeof(TYPE)의 크기만큼 증가 및 감소
int * ptr=arr;이라면 ptr+1은 arr[1]
arr[i]==*(arr+i)
두 가지 형태의 문자열 표현
변수 형태의 문자열 : char str1[]="My String";
상수 형태의 문자열 : char * str2="Your String";
str2는 변수형태의 포인터이기 때문에 str2="Change"; 가능
str1[0]='x'; 가능 str2[0]='x'; 불가능(일부 컴파일러는 허용하지만 하면 안돼)
어디서든 선언할 수 있는 상수 형태의 문자열
char * str = "Const String";
=> 문자열이 메모리 공간에 저장 => 메모리의 주소 값이 반환( ex) char * str = 0x1234;)
printf("Show your String"); => printf(0x1234); (위에랑 똑같아)
궁금한거 글자는 1비트인데 왜 100글자여도 8바이트인가???
포인터 배열 : 포인터 변수로 이뤄진 배열, 주소 값의 저장이 가능
ex) int * arr1[20];
#include <stdio.h>
int main(void)
{
int num1=10, num2=20, num3=30;
int* arr[3]={&num1, &num2, &num3};
printf("%d \n", *arr[0]);
printf("%d \n", *arr[1]);
printf("%d \n", *arr[2]);
return 0;
}
함수
함수호출 시 전달되는 인자의 값은 매개변수에 복사가 된다.
매개변수에서는 int param[]과 int *param은 완전히 동일.(배열은 보통 전자사용) (매개변수에서만)
void AddArayElem(int * param, int len, int add)
{
int i;
for(i=0; i<len; i++)
param[i] += add;
}
=> 이런식으로 하면 param의 값을 직접 바꿀 수 있다.
call-by-value vs call-by-reference
call by value : 함수를 호출할 때 단순히 값을 전달하는 형태의 함수호출
call by reference : 메모리의 접근에 사용되는 주소 값을 전달하는 형태의 함수호출
scanf 함수호출 시 & 연산자를 붙이는 이유 알 수 있다.
int main(void){
int num;
scanf("%d", &num);
...
}
=> 변수 num의 주소 값을 알아야 접근을 해서 값을 채워 넣을 수 있기 때문
int main(void)
{
char str[30];
scanf("%s", str); //scanf("%s", &str);은 잘못된 문장 구성
}
=> str은 그 자체로 주소값이기 때문
const : 변수를 상수화, 포인터 변수를 대상으로 상수화
int main(void)
{
int num=20;
const int * ptr=#
*ptr=30; //컴파일 에러
num=40; //컴파일 성공
int num1=20;
int num2=30;
int * const ptr=&num1;
ptr=&num2; //컴파일 에러
*ptr=40; //컴파일 성공
}
포인터 배열 : 포인터 변수로 이뤄진, 그래서 주소값의 저장이 가능한 배열
ex)
#include <stdio.h>
int main(void)
{
int num1=10, num2=20, num3=30;
int* arr[3]={&num1, &num2, &num3};
return 0;
}
'책 > 윤성우 열혈 C 프로그래밍' 카테고리의 다른 글
달팽이 배열 (0) | 2020.09.19 |
---|---|
포인터2 (0) | 2020.09.16 |
유클리드 호제법(최대공약수, 최소공배수) (0) | 2020.09.13 |
c언어 정리(개인용) (0) | 2020.09.11 |
정수와 실수의 표현 방식 (0) | 2020.09.11 |