#include <stdio.h>
int main()
{
int my_numbers[5];
my_numbers[0] = 1; // 인덱스 = 0, 값 = 1
my_numbers[1] = 2; // 인덱스 = 1, 값 = 2
my_numbers[2] = 3; // 인덱스 = 2, 값 = 3
my_numbers[3] = 4; // 인덱스 = 3, 값 = 4
my_numbers[4] = 5; // 인덱스 = 4, 값 = 5
return 0;
}
#include <stdio.h>
#define MONTHS 12 // 기호적 상수 MONTHS 선언.
int main()
{
int months[MONTHS] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; // int 자료형의 값을 12개 저장할 수 있는 배열 months 선언 및 초기화.
for (int i = 0; i < MONTHS; ++i) // i = 0부터 12보다 작을 때까지 1씩 증가하며 반복 수행.
{
printf("%d ", months[i]); // 배열 months의 처음 인덱스의 값부터 마지막 인덱스의 값까지 출력.
}
printf("\n");
float avg = 0.0; // 실수형 변수 avg 선언 및 초기화.
for (int i = 0; i < MONTHS; ++i) // i = 0부터 12보다 작을 때까지 1씩 증가하며 반복 수행.
{
avg += months[i]; // 변수 avg에 배열 months의 모든 값을 차례대로 더함.
}
printf("Average = %.2f\n", avg / (float)MONTHS); // avg 값(78)을 실수형으로 캐스팅한 MONTHS 값(12)으로 나누고 소수점 2자리까지만 출력.
return 0;
}
#include <stdio.h>
#define MONTHS 12
int main()
{
int months[MONTHS] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; // 배열 months 선언 및 초기화.
printf("%p %p %p\n", months, &months[0], &months[1]);
// 배열 months의 memory 주소, 배열 months의 첫번 째 인덱스 memory 주소, 배열 months의 두번 째 인덱스 memory 주소 출력.
//for (int i = 0; i < MONTHS; ++i)
//{
// printf("%d ", months[i]);
//}
//printf("\n");
//float avg = 0.0;
//for (int i = 0; i < MONTHS; ++i)
//{
// avg += months[i];
//}
//printf("Average = %.2f\n", avg / (float)MONTHS);
return 0;
}
#include <stdio.h>
int main()
{
int* ptr = 0; // 포인터 변수 ptr 초기화.
printf("%p %lld\n", ptr, (long long)ptr); // 포인터 변수 ptr의 memory 주소, 정수 값 출력.
ptr++; // 포인터 변수 ptr에 1 더함.
printf("%p %lld\n", ptr, (long long)ptr); // 포인터 변수 ptr의 memory 주소, 정수 값 출력.
return 0;
}
#include <stdio.h>
int main()
{
int arr[10]; // 배열 arr 선언.
int num = sizeof(arr) / sizeof(arr[0]); // 배열의 크기 판별.
// 변수 num = 배열 arr의 전체 크기 / 배열 arr[0]의 크기
for (int i = 0; i < num; ++i) // i = 0부터 num 까지 1씩 증가하며 for문 실행.
{
arr[i] = (i + 1) * 100; // arr[0] = 100, arr[1] = 200 ...
}
int* ptr = arr; // 포인터 변수 ptr에 배열 arr 대입.
// 배열 이름(arr)의 값 = 배열의 대표 memory 주소 = 배열의 첫번 째 인덱스의 memory 주소.
printf("%p %p %p\n", ptr, arr, &arr[0]);
// 포인터 변수 ptr, 배열 arr의 대표 memory 주소, 배열 arr의 첫번 째 인덱스의 memory 주소 출력.
ptr += 2; // 포인터 변수 ptr에 2를 더함.
printf("%p %p %p\n", ptr, arr + 2, &arr[2]);
// 포인터 변수 ptr, 배열 arr의 대표 memory 주소 + 2, 배열 arr의 세번 째 인덱스의 memory 주소 출력.
printf("%d %d %d\n", *(ptr + 1), *(arr + 3), arr[3]);
// 포인터 변수 (ptr + 1) 에 해당하는 값, 배열 arr의 (대표 memory 주소 + 3)에 해당하는 값, 배열 arr의 네번 째 인덱스의 값 출력.
return 0;
}
#include <stdio.h>
int main()
{
int arr[2][3] = { {1, 2, 3},
{4, 5, 6} };
/*
int arr[2][3] = {1, 2, 3,
4, 5, 6}; 과 같이 선언 가능
*/
printf("%d\n\n", arr[1][1]); // 2차원 배열 arr의 2번째줄 2번째칸 값 출력.
for (int j = 0; j < 2; ++j)
{
for (int i = 0; i < 3; ++i)
{
printf("%d", arr[j][i]); // arr[0][0] 값 출력, arr[0][1] 값 출력 ... arr[1][2] 값 출력.
} // for문 사용시, 배열의 가장 오른쪽 '[]' 부분을 제일 안쪽의 for문으로 넣어줘야 memory를 사용하는데에 효율적임.
printf("\n");
}
printf("\n");
int* ptr = &arr[0][0]; // 포인터 변수 ptr에 배열 arr의 첫번 째 memory 주소 저장.
for (int k = 0; k < 6; ++k)
{
printf("%d ", ptr[k]); // ptr[0]의 값 출력, ptr[1]의 값 출력 ...
} // 2차원 배열이어도 내부적으로는 1차원이기 때문에 이처럼 1차원 배열같이 사용 가능.
printf("\n\n");
printf("%zd bytes %zd bytes\n", sizeof(arr), sizeof(arr[0]));
// 배열 arr의 전체 memory 크기 출력, 배열 arr의 첫째 줄 memory 크기 출력.
return 0;
}
#include <stdio.h>
#define MONTHS 12 // 기호적 상수 MONTHS 선언(12).
#define YEARS 3 // 기호적 상수 YEARS 선언(3).
int main()
{
double year_2019[MONTHS] = { -0.9, 1.0, 7.1, 12.1, 19.4, 22.5, 25.9, 27.2, 22.6, 16.4, 7.6, 1.4 };
double year_2020[MONTHS] = { 1.6, 2.5, 7.7, 11.1, 18.0, 23.9, 24.1, 26.5, 21.4, 14.3, 8.0, -0.4 };
double year_2021[MONTHS] = { -2.4, 2.7, 9.0, 14.2, 17.1, 22.8, 28.1, 25.9, 22.6, 15.6, 8.2, 0.6 };
// 세 개의 1차월 배열을 한 개의 2차원 배열로 통합.
double all_years[YEARS][MONTHS] = { { -0.9, 1.0, 7.1, 12.1, 19.4, 22.5, 25.9, 27.2, 22.6, 16.4, 7.6, 1.4 },
{ 1.6, 2.5, 7.7, 11.1, 18.0, 23.9, 24.1, 26.5, 21.4, 14.3, 8.0, -0.4 },
{ -2.4, 2.7, 9.0, 14.2, 17.1, 22.8, 28.1, 25.9, 22.6, 15.6, 8.2, 0.6 } };
// 1. 2차원 배열 all_years 출력.
printf("[Temperature Data]\n");
printf("Year index\t :\t"); // \t = 들여쓰기(tap)
for (int m = 1; m <= MONTHS; ++m)
printf("%d\t", m); // 1부터 12까지 들여쓰기를 사용하여 출력.
printf("\n");
for (int y = 0; y < YEARS; ++y) // 2차원 배열 all_years의 왼쪽 [] 부분.
{
printf("Year %d\t\t :\t", y);
for (int m = 0; m < MONTHS; ++m) // 2차원 배열 all_years의 오른쪽 [] 부분.
{
printf("%.1f\t", all_years[y][m]); // all_years[0][0] 출력 ... all_years[2][11] 출력.
}
printf("\n");
}
printf("\n");
//2. 3년 동안의 연 평균 기온 출력.
printf("[Yearly average temperatures of 3 years]\n");
for (int y = 0; y < YEARS; ++y)
{
double avr = 0.0;
for (int m = 0; m < MONTHS; ++m)
{
avr += all_years[y][m]; // avr = avr + all_years[0][0] ... avr + all_years[2][11]
}
avr /= (double)MONTHS;
printf("Year %d : average temperature = %.1f\n", y, avr); // 연 평균 계산 값 출력.
}
printf("\n");
//3. 3년 동안의 월 평균 기온 출력.
printf("Monthly average temperatures for 3 years]\n");
printf("Year index\t :\t");
for (int m = 1; m <= MONTHS; ++m)
printf("%d\t", m);
printf("\n");
printf("Avr temperature :\t");
for (int m = 0; m < MONTHS; ++m)
{
double avr = 0.0;
for (int y = 0; y < YEARS; ++y)
{
avr += all_years[y][m]; // avr = avr + all_years[0][0] ... avr + all_years[2][11]
}
avr /= (double)YEARS;
printf("%.1f\t", avr); // 3년 동안의 월 평균 온도 출력.
}
printf("\n");
return 0;
}
#include <stdio.h>
double avr_cal(double *, int n); // 배열 값들의 평균을 구하는 함수 avr_cal 프로토타입.
int main()
{
double arr1[5] = { 10, 13, 12, 7, 8 }; // 배열 arr1 선언.
double arr2[3] = { 1.8, -0.2, 6.3 }; // 배열 arr2 선언.
printf("Address = %p\n", arr1); // 배열 arr1의 memory 주소 출력.
printf("Size = %zd\n", sizeof(arr1)); // 배열 arr1의 크기 출력.
printf("Address = %p\n", arr2); // 배열 arr2의 memory 주소 출력.
printf("Size = %zd\n", sizeof(arr2)); // 배열 arr2의 크기 출력.
printf("Avg = %f\n", avr_cal(arr1, 5)); // 배열 arr1에 있는 값들의 평균 값 출력.
printf("Avg = %f\n", avr_cal(arr2, 3)); // 배열 arr2에 있는 값들의 평균 값 출력.
return 0;
}
double avr_cal(double *data_array, int n)
{
printf("Size = %zd in fuction average\n", sizeof(data_array));
// 배열을 포인터로 받은 후 해당 포인터의 크기 출력. (x86 = 4 bytes, x64 = 8 bytes)
double avg = 0.0;
for (int i = 0; i < n; ++i)
{
avg += data_array[i]; // avg = 배열의 모든 값의 합.
}
avg /= (double)n; // avg를 배열의 크기로 나눔.
return avg; // avg 값 반환.
}
#include <stdio.h>
double avr_cal(double* start, double* end); // 배열에 속한 값들의 평균 값을 구하는 함수 avr_cal 프로토타입.
int main()
{
double arr1[5] = { 10, 13, 12, 7, 8 }; // 배열 arr1 선언.
printf("Avg = %f\n", avr_cal(arr1, arr1 + 5)); // avr_cal 함수를 사용하여 배열 arr1의 평균 값 출력.
return 0;
}
double avr_cal(double* start, double* end) // avr_cal 함수 정의. 매개변수 = 두 개의 포인터.
{
int count = end - start; // 포인터 end의 값 - 포인터 start의 값 = 두 포인터 간의 거리 = 배열의 크기.
double avg = 0.0;
while (start < end) // 배열의 첫번 째 값부터 마지막 값까지
{
avg += *start++; // 1. avg = avg + *start 연산 후 2. start++ 수행.
}
avg /= (double)count; // avg를 배열의 크기로 나눔.
return avg; // avg 값 반환.
}
#include <stdio.h>
int main()
{
/*
Pointer operations
- Assignment
- Value finding (dereferencing)
- Taking a pointer address
- Adding an integer to a pointer
- Incrementing a pointer
- Subtracting an interger from a pointer
- Decrementing a pointer
- Differencing
- Comparisons
*/
int arr[5] = { 100, 200, 300, 400, 500 };
int* ptr1, * ptr2, * ptr3;
ptr1 = arr; // 포인터 변수 ptr1에 배열 arr의 memory 주소 저장.(Assignment)
// 배열의 이름 = 포인터처럼 동작.
printf("%p %d %p\n", ptr1, *ptr1, &ptr1);
// ptr1의 값(memory 주소), ptr1이 가리키는 memory 주소의 값(dereferencing), ptr1 자체의 memory 주소 값(Taking a pointer address) 출력.
ptr2 = &arr[2]; // 포인터 변수 ptr2에 배열 arr의 세번 째 memory 주소 저장. Address-of operator = &.
printf("%p %d %p\n", ptr2, *ptr2, &ptr2);
ptr3 = ptr1 + 4;
// 포인터 변수 ptr1에 4를 더함 = ptr1의 memory 공간에서 4칸 이후의 memory 공간 = ptr3 = Adding an integer to a pointer.
printf("%p %d %p\n", ptr3, *ptr3, &ptr3);
// Differencing
printf("%td\n", ptr3 - ptr1); // \t는 pointer difference 출력을 위한 형식지정자.
// 포인터간 뺄셈 = 두 포인터가 가르키는 memory 주소간 차이.
ptr3 = ptr3 - 4;
// 포인터 변수 ptr3에 4를 뺌 = ptr3의 memory 공간에서 4칸 이전의 memory 공간 = Subtracing an integer from a pointer.
printf("%p %d %p\n", ptr3, *ptr3, &ptr3);
ptr1++; // Incrementing, ptr1 = ptr1 + 1. 후위연산 = 다른 연산 먼저 수행 후 증감 연산자 수행.
ptr1--; // Decrementing, ptr1 = ptr1 - 1. 후위연산 = 다른 연산 먼저 수행 후 증감 연산자 수행.
++ptr1; // Incrementing, ptr1 = ptr1 + 1. 전위연산 = 증감 연산자 먼저 수행 후 다른 연산 수행.
--ptr1; // Decrementing, ptr1 = ptr1 - 1. 전위연산 = 증감 연산자 먼저 수행 후 다른 연산 수행.
// Comparisons
if (ptr1 == ptr3)
printf("Same\n");
else
printf("Different\n");
return 0;
}
#include <stdio.h>
int main()
{
const int arr[5] = { 1, 2, 3, 4, 5 }; // const 배열 arr 선언.
int* ptr1 = arr; // 포인터 변수 ptr1 에 배열 arr의 첫번 째 memory 주소 저장.
*ptr1 = 10; // 포인터 변수 ptr1 이 가리키는 memory 주소에 해당하는 값을 10으로 변경. (arr[0] = 10; 과 동일)
int* ptr2 = &arr[4]; // 포인터 변수 ptr2 에 배열 arr의 다섯번 째 memory 주소 저장.
*ptr2 = 50; // 포인터 변수 ptr2 이 가리키는 memory 주소에 해당하는 값을 50으로 변경. (arr[4] = 50; 과 동일)
for (int i = 0; i < 5; ++i)
printf("%d ", arr[i]); // 배열 arr의 값 출력.
return 0;
}
#include <stdio.h>
void print_array(const int arr[], const int n)
// 배열의 값을 출력만 해주고 수정할 필요는 없는 함수이므로 배열 매개변수에 const 사용.
{
for (int i = 0; i < n; ++i)
printf("%d ", arr[i]);
printf("\n");
}
void add_value(int arr[], const int n, const int val)
// 배열의 값을 수정해야 되는 함수이므로, 배열 매개변수에 const 제외.
{
int i;
for (i = 0; i < n; i++)
arr[i] += val;
}
int sum(const int arr[], const int n)
// 배열의 값을 더해서 반환해주는 함수이므로 배열 매개변수에 const 사용.
{
int i;
int total = 0;
for (i = 0; i < n; i++)
total += arr[i];
return total;
}
int main()
{
int arr[] = { 1, 2, 3, 4, 5 };
int n = sizeof(arr) / sizeof(arr[0]);
print_array(arr, 5);
add_value(arr, 5, 100);
print_array(arr, 5);
int s = sum(arr, n);
printf("sum is %d\n", s);
print_array(arr, 5);
return 0;
}
int* parr[2] = { arr[0], arr[1] };
#include <stdio.h>
int main()
{
int arr0[3] = { 1, 2, 3 }; // 1차원 배열 arr0.
int arr1[3] = { 4, 5, 6 }; // 1차원 배열 arr1.
int* parr[2] = { arr0, arr1 }; // parr = 포인터가 담길 수 있는 공간이 2개인 포인터의 배열.
for (int j = 0; j < 2; ++j)
{
for (int i = 0; i < 3; ++i)
printf("%d(==%d(==%d)) ", parr[j][i], *(parr[j] + i), *(*(parr + j) + i));
// parr[j][i], *(parr[j] + i), *(*(parr + j) + i) 값 출력. (전부 동일한 값을 가짐)
printf("\n");
}
printf("\n");
return 0;
}
💡 포인터의 배열을 2차원 배열처럼 사용할 때 해석.
parr[0][0] = arr0[0] = 1, parr[0][1] = arr0[1] = 2, parr[0][2] = arr0[2] = 3.
parr[1][0] = arr1[0] = 4, parr[1][1] = arr1[1] = 5, parr[1][2] = arr1[2] = 6.
#include <stdio.h>
int main()
{
int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } }; // 2차원 배열 arr
int* parr[2] = { arr[0], arr[1] }; // 배열 arr의 첫번 째 차열을 차례대로 원소에 저장.
for (int j = 0; j < 2; ++j)
{
for (int i = 0; i < 3; ++i)
printf("%d(==%d(==%d)) ", parr[j][i], *(parr[j] + i), *(*(parr + j) + i));
// parr[j][i], *(parr[j] + i), *(*(parr + j) + i) 값 출력. (전부 동일한 값을 가짐)
printf("\n");
}
printf("\n");
<return 0;
}
💡 추후 동적할당 부분에서는 *(*(parr + j) + i)
의 표현을 사용.
#include <stdio.h>
#define ROWS 3
#define COLS 4
int sum2d_1(int ar[ROWS][COLS]); // 함수 프로토타입.
int sum2d_2(int ar[][COLS], int row); // 함수 프로토타입.
int sum2d_3(int* ar, int row, int col); // 함수 프로토타입. 동적할당에서 사용하는 방식.
int main()
{
int data[ROWS][COLS] = { {1,2,3,4}, // 2차원 배열 data 선언.
{5,6,7,8},
{9,0,1,2} };
printf("%d\n", data[2][3]); // 2차원 배열 data의 3 번째줄 4 번째칸 원소 출력.
int* ptr = &data[0][0]; // 포인터 변수 ptr에 2차원 배열 data의 첫 번째 memory 주소 저장.
printf("%d\n", *(ptr + 3 + COLS * 2)); // 포인터의 산술연산을 사용하여 2차원 배열 data의 3 번째 줄 4 번째칸 원소 출력.
// 이게 이해되면 포인터와 배열, memory 상관 관계를 이해한 것.
printf("Sum of all elements = %d\n", sum2d_1(data)); // sum2d_1 함수 결과 값 출력.
printf("Sum of all elements = %d\n", sum2d_2(data, ROWS)); // sum2d_2 함수 결과 값 출력.
printf("Sum of all elements = %d\n", sum2d_3(data, ROWS, COLS)); // sum2d_3 함수 결과 값 출력.
return 0;
}
int sum2d_1(int ar[ROWS][COLS]) // sum2d_1 함수 정의.
{
int r, c, tot = 0;
for (r = 0; r < ROWS; r++)
for (c = 0; c < COLS; c++)
tot += ar[r][c]; // 배열의 모든 원소를 더해서 변수 tot에 저장.
return tot;
}
int sum2d_2(int ar[][COLS], int row) // sum2d_2 함수 정의.
{
int r, c, tot = 0;
for (r = 0; r < ROWS; r++)
for (c = 0; c < COLS; c++)
tot += ar[r][c]; // 배열의 모든 원소를 더해서 변수 tot에 저장.
return tot;
}
int sum2d_3(int* ar, int row, int col) // sum2d_3 함수 정의.
{
int r, c, tot = 0;
for (r = 0; r < row; r++)
for (c = 0; c < col; c++)
tot += *(ar + c + col * r); // 포인터의 산술연산을 사용하여 2차원 배열의 모든 원소 값을 더함.
return tot;
}
🚩 출처 및 참고자료 : 홍정모의 따라하며 배우는 C 언어 (따배씨)