저는 c언어 초보자입니다. java를 모국어로 1개 언어만 파는 바보였습니다.
이에 c언어를 잘 몰랐어서, 포인터 part를 따로 공부해야 할 정도였습니다.
아직도 완벽하진 않지만, 그래도 약간이나마 도움이 되고자 이렇게 다시 포인터에 대해서 포스팅 하게 되었습니다.
메모리 상의 주소
&를 사용
한다.&변수명
: 지정된 변수가 컴퓨터의 메모리 상의 어디에 저장되어 있는가를 나타내는 정보(주소)를 계산
&a
의 값을 보면 1768400
으로 출력되어 있는 것을 알 수 있다. 이 경우 변수 a의 값은 그림과 같이 1768400 이라는 메모리의 위치에 저장되어 있는 것을 알 수 있다.메모리 상의 위치
를 나타낼 수 있다는 것입니다.(주소 출력 / 값 출력) 의 차이점을 명확히 구분하기
&a
: 주소 출력a
: 값 출력기호 주소 형태
로 나타낸 것입니다.다른 변수를 가리키는 변수
이며, 주소를 저장하기 위해서 주소 크기만큼 메모리를 사용하는데 주소의 크기는 시스템에 따라 다릅니다.
예) //포인터 선언
정수형 : int *p
문자형 : char *p;
포인터 변수도 일반 변수처럼 변수를 사용하기 전에 선언을 해야한다.
포인터를 선언할 때, 변수 앞에 간접 연산자(*) 를 붙이고, 데이터형은 포인터 변수가 가리키는 메모리에 보관될 데이터형과 일치시킨다.
데이터형 *포인터 변수명;
정수형 포인터 변수는 저장된 기억 장소의 주소를 가질 수 있다.
p1=&a;
-> 변수 a
에 저장된 주소를 포인터 변수 p1
에 저장하라는 명령이며,
따라서 p1의 값은 a의 주소인 30f770이 된다.
b = *p1;
*p1
이란 포인터 변수 p1이 가리키는 기억 장소30f770 번지의 내용
을 의미한다.20
을 정수형 변수 b에 저장한다.#include <stdio.h>
int main(void){
int a,b,c;
int *p1, *p2;
a=0x20, b=0x30, c=0;
p1=&a; p2= &b;
c= *p1 + *p2;
printf("%0x(a)+ %0x(b) = %0x(c)\n",a,b,c);
printf("a의 주소= %0x, b의주소= %0x, c의 주소= %0x\n", &a,&b,&c);
printf("*p1=%0x, *p2=%0x\n", *p1, *p2);
printf("*p1=%0x, *p2=%0x\n", p1, p2);
}
#include <stdio.h>
int main(void){
int a=10;
int *p1;
p1 = &a;
printf("초기값 a = %d\n",a);
*p1= 30 ;
printf("변경후의 값 a=%d\n",a);
}
#include <stdio.h>
int main(void){
char*p1;
p1 ="PAK";
printf("p1의 주소 = %u p1의 내용 = %u\n", &p1, p1);
printf("%u %u %u\n", &(*p1), &(*(p1+1)), &(*(p1+2)));
printf("%c %c %c\n", *p1, *(p1+1), *(p1+2));
printf("%c %c %c\n", p1[0], p1[1], p1[2]);
}
#include <stdio.h>
void main(void){
char*d ="12345";
printf("%c,,%s\n", *d,d);
d= d+1;
printf("%c,,%s\n", *d,d);
printf("%c,,%c\n", *(d-1), *(d+1));
}
포인터와 배열은 밀접한 관계를 가지고 있다. 배열이 기억 장소에 저장될 때 원소들은 연속된 기억 장소에 저장된다.
그리고 배열명은 배열의 첫 번째 원소가 저장된 주소를 가리키는 포인터 변수이며, 배열명을 기준 주소(base adress)로 정하고 여기에 몇 번째 원소인가를 나타내는 숫자를 더하여 배열 원소를 포인터로 나타낼 수 있다.
아래의 그림과 같이 배열의 최초의 요소 a[0]를 *p로 표시했을 때, 다음의 포인터 배열의 요소 a[1]은 *p(+1)로 된다.
-> 정수형 포인터 변수 p에 주소 0x1000__가 저장되었다고 가정하면 다음과 같이 16진수로 a[1]의 주소는 0x1004, a[2]는 0x1008이 된다.
배열 요소의 크기는 데이터형에 따라 달라질 수 있으나 요소의 순서는 일정합니다.
문자형 데이터의 길이는 1바이트이고, 정수형 데이터의 길이는 4바이트, 실수형(float) 데이터의 길이는 4바이트이다.
예)
char c [4] {'a','b','c','d'};
int a [4] {'1','2','3','4'};
float r [4] {'1.1','2.2','3.3','4.4'};
#include<stdio.h>
int main(void)
{
int a[5]= {5,10,15,20,25};
int *p = a;
printf("%d, %d, %d, %d\n", p[0], *p, p[-1], *(p-1));
printf("%d, %d, %d, %d\n", p[1], a[1], *(p+1), *(a+1));
p++;
printf("%d, %d, %d, %d\n", p[0], *p, p[-1], *(p-1));
printf("%d, %d, %d, %d\n", p[1], a[1], *(p+1), *(a+1));
}
#include<stdio.h>
int main(void)
{
int a[]= {1,2,3,4};
int *p;
int i, sum =0;
p=a;
for(i=0;i<4;i++,p++){
sum+=*p;
printf("a[%d]의 주소 =%x\n", i ,p);
// %x 는 16진수임.
}printf("\n배열 원소의 합 =%d\n", sum);
}
%x
는 16진수를 표현함.#include<stdio.h>
int main(void)
{
int *p1, a[2];
float *p2, b[2];
p1=a;
p2=b;
printf("p1의 주소 :%u\n p2 주소 : %u\n", &p1,&p2);
printf("p1의 값 :%u\n p2 주소 : %u\n", p1,p2);
printf("a 주소 : %u\nb 주소 : %u\n", &a,&b);
*p1 =1;
*(p1+1) =2;
*p2=(float)1.5;
*(p2+1)=(float)2.5;
printf("%6d%6d%6.1f%6.1f\n", *p1, *(p1+1),p2,*(p2+1));
printf("%6d%6d%6.1f%6.1f\n", a[0],a[1],b[0],b[1]);
printf("%6d%6d%6.1f%6.1f\n", p1[0],p1[1],p2[0],p2[1]);
}
(해석)
int*p[3];
char *a[10];
과 같이 선언할 수 있다. 여기서 포인터 배열 p는 3개의 요소로 이루어지며 각 원소는 정수형 데이터를 가리키는 포인터이다. 또한 a는 10개의 요소로 이루어지며, 각 원소는 문자형 데이터를 가리키는 포인터이다.
재정리
#include <stdio.h>
struct student{
char name [12];
int kor, math, sum, total;};
int main(){
struct student s[3]={{"홍길동",90,85},{"이순신",88,91},{"아무개",80,75}};
struct student *p;
p = &s[0];
(p+1)-> sum = (p+1)->kor +(p+2)->math;
(p+1)-> total = (p+1)-> sum+p->kor +p->math;
printf("%d\n", (p+1)->sum + (p+1)-> total);
}