10 배열과 포인터
🔗 혼자 공부하는 C언어
1. 배열과 포인터의 관계
- 배열은 자료형이 같은 변수를 메모리에 연속으로 할당하므로, 첫 번째 요소의 주소를 알면 나머지 요소의 주소도 알 수 있다.
- 주소도 연산이 가능한데, 그 형식은 다음과 같다.
주소 + 정수 -> 주소 + (정수*주소를 구한 변수의 크기)
- 만약 크기가 4 바이트인
int
형 변수 a
의 주소가 100번지라고 하면, 여기에 1을 더한 결과는 101이 아니라 104가 된다.
*(ary + 1) == ary[1]
- 이러한 연산 규칙은 배열에서 유용하며, 주소 연산한 결과를 간접 참조하는 것은 대괄호(
[]
)를 사용하여 첨자로 접근하는 것과 같다.
- 특별한 경우가 아니면 대괄호를 사용하는 것이 편리하며,
&arr[2]
와 같은 경우 arr + 2
로 써서 연산 과정을 줄일 수 있다.
&arr[2]
== &(*(arr + 2))
== arr + 2
2. 배열명 역할을 하는 포인터
- 배열명은 주소이므로 포인터에 저장할 수 있다.
- 포인터에 배열명을 저장하면 포인터 연산을 통해 배열 요소를 사용할 수 있으므로, 포인터를 배열처럼 사용할 수 있다.
int ary[3];
int *pa = ary; // 포인터에 배열명 저장
pa[0] = 10; // 포인터를 배열처럼 사용
*(pa + 1) = 20;
3. 배열명과 포인터의 차이
sizeof
연산 결과가 다르다.
- 배열명에 사용하면 배열의 전체 크기, 포인터에 사용하면 포인터의 크기를 구한다.
- 즉 배열명을 포인터에 저장한 후 포인터로 배열 전체의 크기를 확인할 수는 없다.
- 변수와 상수의 차이가 있다.
- 포인터는 그 값을 바꿀 수 있지만, 배열명은 상수이므로 바꿀 수 없다.
- 즉, 포인터
pa
에 1을 더하여 다시 pa
에 저장할 수 있지만, 배열 arr
에 1을 더하여 다시 arr
에 저장할 수는 없다.
// 가능
pa = pa +1;
pa++;
// 불가능
ary = ary +1;
ary++;
- 포인터로 배열 요소를 출력할 때 다음과 같이 증가 연산자와 간접 참조 연산자를 함께 사용할 수도 있다.
for (i = 0; i < 3; i++)
{
printf("%d ", *(pa++));
}
- 그러나 반복문이 끝나면
pa
의 값은 배열의 범위를 벗어나므로 이후에 사용하려면 다시 초기화를 해야 한다.
- 만약 여기서 전위 표현(
*(++pa)
)를 사용하면 두 번째 요소부터 참조하는데, 마지막에는 쓰레기값을 출력하게 되므로 주의해야 한다.
4. 포인터의 뺄셈과 관계 연산
- 가리키는 자료형이 같은 경우 뺄셈 연산이 가능하다.
포인터 - 포인터 -> 값의 차 / 가리키는 자료형의 크기
- 관계 연산자로 대소 관계를 확인할 수도 있다.
- 배열은 메모리에 순서대로 할당되므로, 관계 연산으로 배열 요소의 순서를 확인할 수 있다.
5. 배열의 값을 출력하는 함수
- 배열의 값을 수시로 출력해야 하는 경우, 매개변수가 포인터인 함수에 배열명을 전달하여 포인터를 배열명처럼 사용할 수 있다.
- 이러한 방식은 배열의 데이터를 복사하지 않고 배열의 데이터에 접근할 수 있으므로 효율적이다.
- 그러나 배열의 주소를 통해 해당 위치의 값을 변경할 수 있기 때문에 주의해서 사용해야 한다.
#include <stdio.h>
void print_ary(int* pa); // 매개변수를 포인터형으로 선언
int main(void)
{
int ary[5] = { 10, 20, 30, 40, 50 };
print_ary(ary); // 배열명을 인자로 전달
return 0;
}
void print_ary(int* pa){
for(int i = 0 ; i < 5 ; i++){
printf("%d ", *pa++);
}
}
// 실행 결과
10 20 30 40 50
💡 매개변수를 배열(int arr[]
)로 선언하고 함수 안에서 값을 변경하면 함수 밖의 배열이 수정되는 이유
- C 언어에서 함수의 매개변수로 배열을 전달하면 포인터로 취급된다.
- 즉 함수 안에서 매개변수로 전달된
arr
는 포인터처럼 사용 가능하다. (arr++
이런 것도 가능)
sizeof
연산자로 크기를 확인해보면 배열의 크기가 아닌 포인터의 크기와 같다.
- 이는 컴파일러가 강제로 배열을 포인터처럼 사용하도록 하는 것이므로, 컴파일러의 부담을 덜기 위해 자료형을 포인터형으로 선언하는 것이 좋다.
- 배열의 데이터 변경이 일어나지 않도록 하려면 새로 배열을 만들어 데이터를 복사한 후에 작업해야 한다.
🔗 참고
- C 언어 코딩 도장 - 64.1 배열 매개변수 사용하기
- 배열을 함수의 매개 변수로 사용할 때 주의할 점
6. 배열 요소의 개수가 다른배열도 출력하는 함수
- 배열의 요소 개수가 달라지면 출력문의 반복 횟수도 달라지므로, 배열 요소의 개수를 함수에 같이 전달해야 한다.
#include <stdio.h>
void print_ary(int* pa, int size); // 매개변수로 배열의 크기 전달
int main(void)
{
int ary1[5] = { 10, 20, 30, 40, 50 };
int ary2[7] = { 10, 20, 30, 40, 50, 60, 70 };
print_ary(ary1, 5);
printf("\n");
print_ary(ary2, 7);
return 0;
}
void print_ary(int *pa, int size){
for(int i = 0 ; i < size ; i++){
printf("%d ", *pa++);
}
}
// 실행 결과
10 20 30 40 50
10 20 30 40 50 60 70
7. 배열에 값을 입력하는 함수
- 배열에 값을 입력할 때는 주소값이 필요하므로, 간접 참조 연산자 없이 포인터명을 그대로 사용한다.
scanf("%lf", pa + i);
Author And Source
이 문제에 관하여(10 배열과 포인터), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://velog.io/@chez_bono/10-배열과-포인터
저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
주소 + 정수 -> 주소 + (정수*주소를 구한 변수의 크기)
int
형 변수 a
의 주소가 100번지라고 하면, 여기에 1을 더한 결과는 101이 아니라 104가 된다.*(ary + 1) == ary[1]
[]
)를 사용하여 첨자로 접근하는 것과 같다.&arr[2]
와 같은 경우 arr + 2
로 써서 연산 과정을 줄일 수 있다.&arr[2]
== &(*(arr + 2))
== arr + 2
int ary[3];
int *pa = ary; // 포인터에 배열명 저장
pa[0] = 10; // 포인터를 배열처럼 사용
*(pa + 1) = 20;
sizeof
연산 결과가 다르다.- 배열명에 사용하면 배열의 전체 크기, 포인터에 사용하면 포인터의 크기를 구한다.
- 즉 배열명을 포인터에 저장한 후 포인터로 배열 전체의 크기를 확인할 수는 없다.
- 포인터는 그 값을 바꿀 수 있지만, 배열명은 상수이므로 바꿀 수 없다.
- 즉, 포인터
pa
에 1을 더하여 다시pa
에 저장할 수 있지만, 배열arr
에 1을 더하여 다시arr
에 저장할 수는 없다.
// 가능
pa = pa +1;
pa++;
// 불가능
ary = ary +1;
ary++;
for (i = 0; i < 3; i++)
{
printf("%d ", *(pa++));
}
pa
의 값은 배열의 범위를 벗어나므로 이후에 사용하려면 다시 초기화를 해야 한다.*(++pa)
)를 사용하면 두 번째 요소부터 참조하는데, 마지막에는 쓰레기값을 출력하게 되므로 주의해야 한다.포인터 - 포인터 -> 값의 차 / 가리키는 자료형의 크기
- 배열은 메모리에 순서대로 할당되므로, 관계 연산으로 배열 요소의 순서를 확인할 수 있다.
#include <stdio.h>
void print_ary(int* pa); // 매개변수를 포인터형으로 선언
int main(void)
{
int ary[5] = { 10, 20, 30, 40, 50 };
print_ary(ary); // 배열명을 인자로 전달
return 0;
}
void print_ary(int* pa){
for(int i = 0 ; i < 5 ; i++){
printf("%d ", *pa++);
}
}
// 실행 결과
10 20 30 40 50
💡 매개변수를 배열(int arr[]
)로 선언하고 함수 안에서 값을 변경하면 함수 밖의 배열이 수정되는 이유
- C 언어에서 함수의 매개변수로 배열을 전달하면 포인터로 취급된다.
- 즉 함수 안에서 매개변수로 전달된
arr
는 포인터처럼 사용 가능하다. (arr++
이런 것도 가능) sizeof
연산자로 크기를 확인해보면 배열의 크기가 아닌 포인터의 크기와 같다.- 이는 컴파일러가 강제로 배열을 포인터처럼 사용하도록 하는 것이므로, 컴파일러의 부담을 덜기 위해 자료형을 포인터형으로 선언하는 것이 좋다.
- 배열의 데이터 변경이 일어나지 않도록 하려면 새로 배열을 만들어 데이터를 복사한 후에 작업해야 한다.
🔗 참고 - C 언어 코딩 도장 - 64.1 배열 매개변수 사용하기
- 배열을 함수의 매개 변수로 사용할 때 주의할 점
#include <stdio.h>
void print_ary(int* pa, int size); // 매개변수로 배열의 크기 전달
int main(void)
{
int ary1[5] = { 10, 20, 30, 40, 50 };
int ary2[7] = { 10, 20, 30, 40, 50, 60, 70 };
print_ary(ary1, 5);
printf("\n");
print_ary(ary2, 7);
return 0;
}
void print_ary(int *pa, int size){
for(int i = 0 ; i < size ; i++){
printf("%d ", *pa++);
}
}
// 실행 결과
10 20 30 40 50
10 20 30 40 50 60 70
scanf("%lf", pa + i);
Author And Source
이 문제에 관하여(10 배열과 포인터), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@chez_bono/10-배열과-포인터저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)