// 구조체배열 2번째 요소 name에 'asdf' 저장.
strcp(x[1].name, "asdf");
// 구조체배열 3번째 요소 gneder에 'F' 저장.
x[2].gender = 'F';
// 구조체배열 3번째 요소 age 값을 변수 K에 저장.
K = x[2].age;
구조체 배열의 사용 예
#include <stdio.h>
#include <string.h>
struct person // person형 구조체 선언
{
char name[8];
int age;
char gender;
};
void main()
{
// 구조체 배열 초기화.
struct person x[3] =
{
{"qwer", 20, 'M'},
{"asdf", 21, 'F'},
{"zxcv", 22, 'M'}};
int i, sum = 0;
for (i = 0; i < 3; i++)
{
// 구조체 배열의 멤버 참조.
printf("name : %s, age : %d, gender : %c\n", x[i].name, x[i].age, x[i].gender);
sum = sum + x[i].age;
}
printf("SUM OF AGE : %d\n", sum);
}
구조체 포인터
포인터를 사용하여 구조체를 다룰 수 있게 함.
구조체를 보다 쉽게 다를 수 있음.
구조체 변수 선언시 * 를 붙여 포인터로 선언.
구조체 포인터는 포인터와 동일하게 주소값을 갖게 되며, 자료가 있는 곳을 가르킴.
구조체 포인터 선언
형식 : struct 구조체_명 *포인터변수_명;
사용 예 : struct person *pt;
// 구조체 변수 man 선언
struct person man;
// 구조체 포인터 변수 pt 선언
struct person *pt;
// 구조체 포인터 변수의 초기화
pt = &man;
#include <stdio.h>
int main()
{
// char형 포인터 변수 cp의 값은 COMPUTER가 수록된 시작주소.
char *cp = "COMPUTER";
int i = 0;
do
{
printf("*(cp + %d) : %c\n", i, *(cp + i));
} while (*(cp + i++) != 0); // *(cp + i)를 구한 후 1 증가.
return 0;
}
/**
* *(cp + 0) : C
* *(cp + 1) : O
* *(cp + 2) : M
* *(cp + 3) : P
* *(cp + 4) : U
* *(cp + 5) : T
* *(cp + 6) : E
* *(cp + 7) : R
* *(cp + 8) :
*/
포인터와 배열의 관계
포인터를 이용한 1차원 배열의 참조와 예.
포인터를 이용한 1차원 배열의 참조와 예.
#include <stdio.h>
void main()
{
static int a[] = {10, 20, 30, 40, 50};
int *pt, b, c, d;
// 배열명을 사용하여 배열의 시작주소를 할당 -> a[0]
pt = a;
// a[0] + a[3] = 10 + 40 = 50
b = *pt + *(pt + 3);
// 포인터를 1 이동 a[1]
pt++;
// a[1] + a[4] = 20 + 50 = 70
c = *pt + *(pt + 3);
// a[1] + 3 = 23
d = *pt + 3;
printf("b = %d, c = %d, d = %d\n", b, c, d);
// b = 50, c = 70, d = 23
}
포인터를 이용한 2차원 배열의 참조와 예.
포인터를 이용한 2차원 배열의 참조와 예
#include <stdio.h>
void main()
{
static a[3][3] = {
{1, 2, 3}
, {4, 5, 6}
, {7, 8, -9}
};
int *pt;
// pt = a 또는 pa = &a[0][0]과 동일
pt = a[0];
while (*pt != -9)
{
printf("%d ", *pt);
pt++;
}
}
포인터와 배열은 상호 호환적.
int A[] = {1, 2, 3, 4, 5};
int *p, i;
// -->>
A + i == &A[i];
A[i] == *(A + i);
*( p + i ) == p[i];
#include <stdio.h>
void main()
{
char A[] = "ARRAY";
char *p = "POINTER";
int i;
for (i = 0; i < 5; i++)
{
// 배열을 포인터 형식으로 참조.
printf("*(A + %d) : %c\n", i, *(A + i));
}
for (i = 0; i < 7; i++)
{
// 포인터를 배열 형식으로 참조.
printf("p[%d] : %c\n", i, p[i]);
}
}
#include <stdio.h>
void main()
{
int days = 365;
int month = 12;
int Table[5] = {1, 2, 3, 4, 5};
// & : 주소를 의미한다.
printf("addr of days : %x\n", &days);
printf("addr of month : %x\n", &month);
printf("addr of array : %x\n", Table); // 배열명은 기본적으로 주소를 나타냄.
printf("addr of first element of array : %x\n", &Table[0]);
printf("addr of second element of array : %x\n", &Table[1]);
}
포인터변수의 선언
형식 : 자료형 *포인터변수명;
사용 예 : int *p;
기능 : 변수 p는 포인터 변수로서 정수형의 자료를 갖는 변수의 주소를 갖는다.
int *p
p : 포인터 변수로서 정수 형 자료가 수록되어있는 주소를 갖고 있다.
*p : 해당 주소에 수록되어 있는 정수 형 자료를 갖고 있다.
#include <stdio.h>
void main()
{
int a, b;
int *p; // 변수 p를 포인터 변수로 선언.
a = 5000;
p = &a; // 포인터 변수 p에 변수 a의 주소값 대입.
b = *p; // 포인터 변수 p가 가리키는 주소의 내용을, 변수 b에 저장.
printf("a : %d, b : %d, p : %x", a, b, p);
}
포인터변수의 참조
포인터 변수의 참조 => &, * 연산자 사용.
잘 못 된 예
포인터변수의 올바른 참조 방법.
포인터 변수의 참조 예
#include <stdio.h>
void main()
{
int *p, i = 3, j;
p = &i; // 포인터 변수 p가 변수 i의 주소를 가리킴. 주소값 확보.
j = *p; // 포인터 변수 p가 가리키는 번지의 내용을 변수 j에 대입.
j++; // 변수 j의 값을 1증가.
printf("*p = %d\n", *p);
printf(" p = %x\n", p);
printf(" j = %d\n", j);
}
/**
* p = &i;
* 포인터 변수 p가 어느 공간을 가르킬 것인가.
* 포인터 변수는 특정 기억공간을 가리키는 지시자이고,
* 이 지시자가 어느 위치를 가르킬 것인지를 지정하는 것이 포인터 변수에서 제일 중요.
*/
포인터 변수 참조의 기억공간 표현
void 형 포인터
형식 : void *포인터명;
의미 : 프로그램 실행시에 자료형이 결정되는 경우에 사용.
저장하기 전에 명시적 형변환 필요.
void 형 포인터의 사용 예
#include <stdio.h>
void main()
{
int a = 100;
char b = 'B';
void *p = NULL; // void형 포인터를 선언 후 초기화
p = (int *)&a;
// void형 포인터 p에 int형 변수 a의 주소를
// 명시적 형변환을 이용하여 대입.
printf("*p = %d\n", *(int *)p);
p = (char *)&b;
// void형 포인터 p에 char형 변수 b의 주소를
// 명시적 형변환을 이용하여 대입.
printf("*p = %c\n", *(char *)p);
}
일반 변수와 표인터 변수의 비교
일반 변수
포인터 변수
선언
int a;
정수형 변수 a 선언
int *a;
포인터변수 a를 정수형으로 선언
값 할당
a = 100;
변수 a에 100 할당
*a = 100;
a 주소에 100 할당
주소 참조
&a
변수 a의 주소
a
a 자체가 주소
주소 연산
연산 불가능
a--;
포인터를 1 감소
포인터 연산
포인터가 선언 되어있을 때 포인터와 포인터와 끼리의 계산이 가능하다.
포인터와 기억공간의 대응 관계
포인터 변수에 +, -, ++, -- 연산자를 사용하는 연산
int a[10], *p, *q;
포인터 연산의 예
#include <stdio.h>
void main()
{
int *p, a[] = {10, 20, 30, 40, 50};
// 배열 첫 번째 요소의 주소값을 포인터변수 p에 저장.
p = &a[0];
printf("*p == %d\n", *p); // 10
// 포인터 p의 값 출력 후 주소를 1(4byte) 증가.
printf("*p++ == %d\n", *p++); // 10
// 포인터 p의 주소를 1(4byte) 증가 후 출력.
printf("*++p == %d\n", *++p); // 30
// 포인터 p의 주소를 2(8byte) 증가
p = p + 2;
printf("*p == %d\n", *p); // 50
printf("a[2] == %d\n", a[2]); // 30
// 포인터 p의 값에 2를 증가.
printf("*p + 2 == %d\n", *p + 2); // 32
}
#include <stdio.h>
void main()
{
int *p, *q;
int a[] = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
p = &a[3];
printf("*p == %d\n", *p); // 40
// *(p + 3)과 *p + 3은 다르다.
printf("*(p + 3) == %d\n", *(p + 3)); // 70
q = p + 3;
printf("*q == %d\n", *q); // 70
// 동일 배열을 가르키는 경우 두 포인터 간의 뺄샘.
printf(" q - p == %ld\n", q - p); // 3
printf(" p - q == %ld\n", p - q); // -3
// 두 포인터 간의 덧셈은 불가능.
//printf(" p + q == %d\n", p + q);
}
배열의 개념에 대해 알아보고, 배열의 정의와 선언 형태, 배열과 기억공간의 표현에 대해 알아본다.
학습 목표
배열을 선언하고 초기화.
배열의 요소를 참조.
배열과 기억공간의 표현을 이해.
char형 배열을 이해.
주요 용어
배열 : 동일한 자료형으 ㅣ값들이 순서적으로 하나의 이름(배열명)에 모여있는 것으로, 같은 이름을 갖는 하나 이상의 변수 리스트.
1차원 배열 : 배열의 첨자가 하나만 있는 배열.
2차원 배열 : 배열의 첨자가 2개인 배열.
3차원 배열 : 배열의 첨자가 3개인 배열.
char형 배열 : 문자열을 처리하기 위해 사용되는 배열.
배열의 개념
n개의 자료를 처리하기 위해, n개의 변수를 만들고 모든 변수 이름을 기억하고 자료를 처리하기는 복잡함. -> 일관성 있고 효율적인 새료운 변수릐 필요
하나의 변수 이름에 순서에 의한 번호 부여.
변수명[0], 변수명[2], ...
효율적인 자료 처리 가능.
배열의 정의와 형태
배열의 정의.
동일한 자료형을 갖는 자료들의 리스트.
배열의 각 요소는 하나의 변수로 취급.
배열은 배열명과 첨자로 구분.
배열 선언 형태.
1차원 배열.
2차원 배열.
3차원 배열.
1차원 배열
배열의 첨자가 하나만 있는 배열.
첨자의 개수는 배열 전체의 구성요소의 개수를 의미.
배열의 각 요소는 배열명과 첨자로 구분.
첨자는 0 부터 시작.
배열의 각 요소는 배열명과 첨자로 구분.
자료형과 기억 클래스는 갖는다.
선언
형식 : 자료형 배열명 [개수]
사용 예 : int a [10]
의미 : 1차원 배열로서, 배열명은 a, 크기는 10, 정수 값이 기억됨.
1차원 배열의 기억 공간 표현
1차원 배열의 기억 공간 표현
1차원 배열의 초기화
배열을 선언하면 기억공간을 초기화 해야 함.
초기화 방법.
배열선언 후 초기값 할당.
int arr[4]; // -> 반드시 배열의 크기를 지정해야 함.
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
arr[3] = 40;
배열선언과 동시에 초기값 할당.
int arr[4] = {10, 20, 30, 40}; // -> 배열의 각 요소에 초기 값 할당.
int arr[] = {10, 20, 30, 40}; // -> 배열의 크기 생량 가능.
int arr[4] = {10, 20, 30,}; // -> arr[3] = 0으로 초기화.
int arr[4] = {10, , 30, 40}; // -> 에러 발생.
int arr[4] = {10, 20, 30, 40, 50}; // -> 에러
외부로부터 자료를 입력받아 초기화.
int x[10];
for( i = 0; i < 10; i++ ) {
scanf("%d", &x[i]);
}
1차원 배열의 초기화 후 기억공간의 표현 int arr[5] = {10, 20, 30, 40, 50};
1차원 배열의 초기화 후 기억공간의 표현
EX 1
#include <stdio.h>
int main()
{
// 배열 선언과 초기화
int arr1[4] = {10, 20, 30, 40};
int arr2[] = {10, 20, 30, 40};
int arr3[4] = {10, 20};
int arr4[4] = {0};
int i;
printf("\narr1 ->\n\t");
for (i = 0; i <= 3; i++)
{
printf("[%d] : %d\t", i, arr1[i]);
}
printf("\narr2 ->\n\t");
for (i = 0; i <= 3; i++)
{
printf("[%d] : %d\t", i, arr2[i]);
}
printf("\narr3 ->\n\t");
for (i = 0; i <= 3; i++)
{
printf("[%d] : %d\t", i, arr3[i]);
}
printf("\narr4 ->\n\t");
for (i = 0; i <= 3; i++)
{
printf("[%d] : %d\t", i, arr4[i]);
}
printf("\n");
return 0;
}
EX 2
#include <stdio.h>
int main()
{
// 1차원 배열 선언과 초기화
static int x[] = {1, 2, 3, 4};
static int y[] = {10, 20, 30, 40};
int i, z[4];
for (i = 0; i < 4; ++i)
z[i] = x[i] + y[3 - i];
printf("SUM OF OTHER SIDE OF EACH ARRAY\n");
for (i = 0; i < 4; ++i)
printf("%d + %d = %d\n", x[i], y[3 - i], z[i]);
return 0;
}
2차원 배열 선언
형식 : 자료형 배열명[행의 수][열의 수]
사용 예 : int a[3][4];
의미 : 2차원 배열로, 배열 명은 a이고, 3행 4열로 됨 12개의 요소를 가진 정수형 배열.