검색결과 리스트
글
구조체로 할 수있는 연산은 복사하는 것. 저장(assign) 하는것 그리고 &로 구조체의 주소를 찾아서 그 멤버중의 하나를 사용하는 것밖에 없다. 복사와 지정이라 함은 함수로 인자(argument)를 넘기거나 함수로부터 값을 받는 것을 포함해서 하는 말이다.
점과 사각향을 다루기 위한 몇개의 함수를 사용해 봄으로써 구조체를 연구해 보자 여기에는 최소한 세개의 접근방법이 있다. 독립적으로 요소를 보내거나 하나의 구조체를 보내거나 또는 포인터로 보내는 세가지 방법이 있다 각각은 장단점이 있다.
첫번쨰 함수 makepoint는 두 개의 정수를 받아 point 라는 구조체를 리턴해준다.
/* makepoint: make a point from x and y components */
struct point makepoint(int x, int y)
{
struct point temp;
temp.x = x;
temp.y = y;
return temp;
}
여기서 변수이름과 똑같은 이름의 멤버이름(x,x.)은 전혀 다른 변수임에 유의하라 makepoint느 ㄴ어떠한 구조체를 초기화 하는데 사용하거나 구조체의 멤버에 어떤값을 넣는 함수로 사용할수 있다
struct rect screen;
struct point middle;
struct point makepoint(int, int);
screen.pt1 = makepoint(0,0);
screen.pt2 = makepoint(XMAX, YMAX);
middle = makepoint((screen.pt1.x + screen.pt2.x)/2,
(screen.pt1.y + screen.pt2.y)/2);
다음으로 점에 관한 산술연산을 해 보자. 즉
/* addpoints: add two points */
struct addpoint(struct point p1, struct point p2)
{
p1.x += p2.x;
p1.y += p2.y;
return p1;
}
여기서는 구조체를 매개변수로 받고 구조체를 리턴해 준다.
다른예로 어느 점이 삭가형 속에 있는지 없는지를 검사하는 ptinrect라는 함수를 보자. 왼쪽과 및변은 사각형에 포함되고 위쪽과 오른쪽 변은 사각형에 포함되지 않는다고 가정한다.
/*ptinrect: return1ifpinr,0ifnot*/
int ptinrect(struct point p, struct rect r)
{
return p.x >= r.pt1.x && p.x < r.pt2.x
&& p.y >= r.pt1.y && p.y < r.pt2.y;
}
이와 같이 두 번의 비교만으로 판단이 가능한 것은 사각형을 나타내는 표준적인 방법이 왼쪽 아래 점을 pt1 오른쪽 위 점을 pt2로 나타내는 것이기 때문이다. 다음하누는 표준적인(canonical)형태로 사각형을 리턴해 준다.
#define min(a, b) ((a) < (b) ? (a) : (b))
#define max(a, b) ((a) > (b) ? (a) : (b))
/* canonrect: canonicalize coordinates of rectangle */
struct rect canonrect(struct rect r)
{
struct rect temp;
temp.pt1.x = min(r.pt1.x, r.pt2.x);
temp.pt1.y = min(r.pt1.y, r.pt2.y);
temp.pt2.x = max(r.pt1.x, r.pt2.x);
temp.pt2.y = max(r.pt1.y, r.pt2.y);
return temp;
}
만일 큰 구조체가 함수로 전달 된다면 그 큰 구조체를 복사하기보다는 포인터를 넘겨주는 것이 일반적으로 더효율적이다 구조체의 포인터는 일반적인 변수의 포인터와 같은 방법으로 사용하면 된다. 선언은 다음과 같다
struct point *pp;
여기서 pp는 struct point 형태의 구조체 포인터이다 *pp는 구조체 이고 (*pp).x와 (*pp).y는 멤버이다. pp를 사용하기 위해서는 다음 예와 같이 해야한다.
struct point origin, *pp;
pp = &origin;
printf("origin is (%d, %d)\n",(*pp).x,*(pp).y);
(*pp).x에서 .의 연산자가*보다 우선순위가 높으므로 괄호가 필요하다 *pp.x라는 표현은 *(pp.x)를 나타내는데 여기서는 x는 포인터가아니므로 문법적으로 틀리다.
구조체의 포인터로서 단축된 표현으로 제공되는 또 다른 표현이 자주 쓰인다. 만일 p가 구조체의 포인터라면
p->멤버
는 그 구조의 멤버를 가리킨다(연산자->는 음수 부호와 >의 두 문자로 있다). 따라서 위의 표현을 다르게 표현할수 있다.
printf("origin is (%d, %d)\n",pp->x,pp->y);
.과 ->는 왼쪽에서 오른쪽으로 적용되며,다음과 같이 주어지면
struct rect r, *rp = &r;
다음의 네 가지 표현은 모두 같은 결과를 가져온다.
r.pt1.x
rp->pt1.x
(r.pt1).x
(rp->pt1).x
구조체 연산자 . 과 ->는 함수를 부르기 위한 () 및 첨자를 위한[]와 함께 우선순위가 가장 높다. 예를들어
struct {
int len;
char *str;
} *p;
위와 같이 선언이 있으면
++p->len
는 ++(p->len)과 같은 의미이므로 포인터 p가 아닌 len을 증가시킨다. 괄호는 결함순서를 바꿀수 있다. 즉 (++p)->len은 len을 엑세스 하기 전에 p를 증가시키지만 (p++)->len은 p를 나중에 증가시킨다(이 경우 괄호는 없어도 된다.)
같은 방법으로 *p->str는 str가 가리키는 것을 가져오며 *p->str++는 (*s++처럼)가리키는 것을 가져온후 str을 증가시킨다(*p->str)++는 str가 가리키는 것을 증가시키지만 *p++->str가 가리키는 것을 가져온후 str을 증가시킨다
'프로그래밍 > C' 카테고리의 다른 글
6.4 구조체에 대한 포인터(Pointers to Structures) (0) | 2014.11.06 |
---|---|
6.3 구조체의 배열(Arrays of Structures) (0) | 2014.11.06 |
6.1 구조체의 기본개념(Basics of Structures) (0) | 2014.11.06 |
5.12 복잡한 선언문(Complicated Declarations) (0) | 2014.11.06 |
5.11 함수의 포인터(Pointers to Functions) (0) | 2014.11.05 |
RECENT COMMENT