따라 배우는 C언어 : 11
🙇♀️11
🪐배열
배열
int arr[3] = {1, 2, 3};
총 12바이트를 선언받았다. (4 * 3)
arr[0] = 1;
인덱스를 통해서 대입
&arr[0]
와 &(arr[0])
은 같다.
🪐포인터의 산술 연산
Pointer Arithmetic
int* ptr = 0;
printf("%p %lld\n", ptr, (long long)ptr); //0000000000000004 4
ptr += 1;
printf("%p %lld\n", ptr, (long long)ptr); //0000000000000008 8
// int만큼 커진다 void*라면 에러가 난다
최적화 작업을 한다면 void*를 사용한다.
ptr = -ptr;
사용불가.
int arr[10];
int* ptr1 = &arr[3], * ptr2 = &arr[5];
//ptr2 = ptr1 + ptr2; // Not working
int i = ptr2 - ptr1; // 빼기는 된다
printf("%d", i); // 2
🪐포인터와 배열
int arr[10];
int num = sizeof(arr) / sizeof(arr[0]);
for (int i = 0; i < num; i++)
arr[i] = (i + 1) * 100;
int* ptr = arr;
printf("%p %p %p\n", ptr, arr, &arr[0]); // 3값 모두 같다
ptr += 2;
printf("%p %p %p\n", ptr, arr + 2, &arr[2]); // 3값 모두 같다 8만큼 더해짐
//arr += 2; // error
printf("%d %d %d\n", *(ptr + 1), *(arr + 3), arr[3]); // 3값 모두 같다 400
//ex
for (int i = 0, *ptr = arr; i < num; ++i)
{
//printf("%d %d\n", *ptr++, arr[i]);
printf("%d %d\n", *(ptr + i), arr[i]);
}
🪐2차원 배열과 메모리
#include <stdio.h>
// 2차원 배열과 메모리
#define MONTHS 12
#define YEARS 3
int main()
{
double year2016[MONTHS] = { -3.2, 0.2, 7.0, 14.1, 19.6, 23.6, 26.2, 28.0, 23.1, 16.1, 6.8, 1.2 };
double year2017[MONTHS] = { -1.8, -0.2, 6.3, 13.9, 19.5, 23.3, 26.9, 25.9, 22.1, 16.4, 5.6, -1.9 };
double year2018[MONTHS] = { -4.0, -1.6, 8.1, 13.0, 18.2, 23.1, 27.8, 28.8, 21.5, 13.1, 7.8, -0.6 };
// 2차원 배열 만들기
double year[YEARS][MONTHS];
for (int i = 0; i < YEARS; i++)
{
for (int j = 0; j < MONTHS; j++)
{
switch (i)
{
case 0:
year[i][j] = year2016[j];
break;
case 1:
year[i][j] = year2017[j];
break;
case 2:
year[i][j] = year2018[j];
break;
default:
break;
}
}
}
// 2차원배열 데이터 출력
printf("[Temperature Data]\n");
printf("Year index :");
for (int i = 0; i < MONTHS; i++)
{
printf("\t%d", i + 1);
}
for (int i = 0; i < YEARS; i++)
{
for (int j = 0; j < MONTHS; j++)
{
if (j == 0)
{
printf("\n");
printf("Year %d : ", i);
}
printf("\t%.1f", year[i][j]);
}
}
// 띄우기
printf("\n\n");
// 평균 기온 출력
printf("[Yearly average temperatures of 3 years]\n");
for (int i = 0; i < YEARS; i++)
{
double ave = 0, sum = 0;
for (int j = 0; j < MONTHS; j++)
{
sum += year[i][j];
}
printf("Year %d : average temperaure = %.1f\n", i, sum / MONTHS);
}
// 띄우기
printf("\n");
// 3년 월별 평균 기온
printf("[Monthly average temperatures for 3 years]\n");
printf("Year index :");
for (int i = 0; i < MONTHS; i++)
{
printf("\t%d", i + 1);
}
printf("\nAvg temps :");
for (int i = 0; i < MONTHS; i++)
{
double sum = 0;
for (int j = 0; j < YEARS; j++)
{
sum += year[j][i];
}
printf("\t%.1f", sum / YEARS);
}
// 띄우기
printf("\n");
return 0;
}
🪐배열을 함수에게 전달하는 방법
배열의 인자들의 평균을 구하는 함수
double Average(double arr[], int n)
{
printf("Size = %zd in function average\n", sizeof(arr));
double avg = 0.0;
for (int i = 0; i < n; i++)
{
avg += arr[i];
}
avg /= (double)n;
return avg;
}
- 배열을 함수의 인자로 선언할 때 경우의 수
double Average(double* arr, int n); double Average(double*, int n); double Average(double arr[], int n); double Average(double[], int n);
🪐두 개의 포인터로 배열을 함수에게 전달하는 방법
앞의 배열의 인자들의 평균을 구하는 함수이지만 두 개의 포인터를 이용한다
double Average(double* start, double* end)
{
int count = end - start;
double avg = 0.0;
while (start < end)
{
avg += *start++;
//count++;
}
avg /= (double)count;
return avg;
}
함수를 사용할 때는 주소값을 넣어줘야 하기때문에 printf("Average = %f\n", Average(arr1, arr1 + 5));
처럼 사용한다.
🪐포인터 연산 총 정리
double arr[5] = { 100, 200, 300, 400, 500 };
int* ptr1, * ptr2, * ptr3;
ptr1 = arr; // Assignment
printf("%p %d %p\n", ptr1, *ptr1, &ptr1); // dereferencing, Taking a pointer address
ptr2 = &arr[2]; // Address-of operator &
printf("%p %d %p\n", ptr2, *ptr2, &ptr2);
ptr3 = ptr1 + 4; // Adding an integer from a pointer
printf("%p %d %p\n", ptr3, *ptr3, &ptr3);
// Differencing
printf("%td\n", ptr3 - ptr1); // Note : t is for pointer defference
🪐const와 배열과 포인터 정리
int arr[5] = { 1,2,3,4,5 };
arr[1] = 123;
double arr2[3] = { 1.0, 2.0, 3.0 };
arr2[0] = 100.0;
double* pd = arr2;
*pd = 3.0; // pd[0] = 3.0; arr2[0] = 3.0;
pd[2] = 1024.0; // arr2[0] = 1024.0;
printf("%f", pd[2]);
pd++; // allowed
여기서 const double* pd = arr2;
라고 하면 *pd = 3.0;
와 pd[2] = 1024.0;
이 막힌다.
pd++;
은 되는데 이거까지 막기위해서는 const double* const pd = arr2;
라고 하면 된다.
🪐배열 매개변수와 const
void print_array(const int arr[], const int n)
{
for (int i = 0; i < n; i++)
printf("%d ", arr[i]);
printf("\n");
}
void add_value(int arr[], const int n, const int val)
{
for (int i = 0; i < n; i++)
arr[i] += val;
}
int sum(const int arr[], const int n)
{
int total = 0;
for (int i = 0; i < n; i++)
total += arr[i];
return total;
}
함수의 매개변수로 배열을 줄 때는 배열의 값을 변경하는 상황이 아니라면 const
를 붙이는 것이 좋다.
🪐2중 포인터의 작동 원리
int a = 7;
int* ptr = &a;
*ptr = 8; // 간접 접근 (역참조) Indirection (dereferencing)
// int (*(*pptr)) = &ptr;
int** pptr = &ptr;
// double indirection
**pptr = 9; // *(*(pptr)) = 9;
🪐포인터의 배열과 2차원 배열
- Two of 1D arrays ```c
int arr0[3] = { 1, 2, 3 }; int arr1[3] = { 4, 5, 6 };
int* parr[2] = { arr0, arr1 }; // an array of pointers
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)); // 똑같은 값을 출력한다 1(==1, 1) 2(==2, 2) … printf(“\n”); } printf(“\n”);
* 2D arrays are arrays of 1D arrays
```c
int arr[2][3] = { {1, 2, 3}, {4, 5, 6} };
int* parr0 = arr[0];
int* parr1 = arr[1];
for (int i = 0; i < 3; i++)
printf("%d ", parr0[i]);
printf("\n");
for (int i = 0; i < 3; i++)
printf("%d ", parr1[i]);
printf("\n");
- Array of string of diverse lengths example ```c
char* name[] = { “Aladdin”, “Jasmine”, “Magic Carpet”, “Genie” };
const int n = sizeof(name) / sizeof(char*);
for (int i = 0; i < n; ++i) printf(“%s at %u\n”, name[i], (unsigned)name[i]); // Use ull in x64 build printf(“\n”);
char aname[][15] = { “Aladdin”, “Jasmine”, “Magic Carpet”, “Genie”, “Jafar”};
const int an = sizeof(aname) / sizeof(char[15]);
for (int i = 0; i < an; ++i) printf(“%s at %u\n”, aname[i], (unsigned)&aname[i]); // Use ull in x64 build printf(“\n”);
<br>
### 🪐2차원 배열과 포인터
```c
int arr[2][3] = { {1, 2, 3}, {4, 5,6} };
// arr == arr[0] == &arr[0] == &a[0][0] != a[0][0]
// a[0][0] == **arr
// &arr[0][1] = &arr[0][0] + 1
// arr + 1 == &arr[1] == &arr[0] + 1 == &a[1][0] != a[1][0]
// a[1][2] == *(*(arr+1)+2)
float arr2d[2][4] = { {1.0f, 2.0f, 3.0f, 4.0f}, {5.0f, 6.0f, 7.0f, 8.0f} };
printf("%u\n", (unsigned)arr2d); // Use unsigned long long in x64
printf("%u\n", (unsigned)arr2d[0]);
printf("\n");
// arr2d points to arr2d[0] (not arr2d[0][0]), KNK Ch. 12.4
printf("%u\n", (unsigned)*arr2d);
printf("%u\n", (unsigned)&arr2d[0]); // C language allows this
printf("%u\n", (unsigned)&arr2d[0][0]);
printf("%f %f\n", arr2d[0][0], **arr2d);
printf("\n");
printf("%u\n", (unsigned)(arr2d + 1));
printf("%u\n", (unsigned)(&arr2d[1]));
printf("%u\n", (unsigned)(arr2d[1]));
printf("%u\n", (unsigned)(*(arr2d + 1)));
printf("%u\n", (unsigned)(&arr2d[0] + 1));
printf("%u\n", (unsigned)(&arr2d[1][0]));
printf("\n");
printf("%f\n", *(*(arr2d + 1) + 2));
printf("\n");
for (int j = 0; j < 2; ++j)
{
printf("[%d] = %u, %u\n", j, (unsigned)(arr2d[j]), (unsigned)*(arr2d + j));
for (int i = 0; i < 4; ++i)
{
printf("[%d][%d] = %f, %f\n", j, i, arr2d[j][i], *(*(arr2d + j) + i));
*(*(arr2d + j) + i) += 1.0f; // arr2d[j][i] += 1.0f;
}
}
printf("\n");
🪐다차원 배열을 함수에게 전달해주는 방법
#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 },
{ 5, 6, 7, 8 },
{ 9, 0, 1, 2 }
};
printf("%d\n", data[2][3]);
int* ptr = &data[0][0];
printf("%d\n", *(ptr + 3 + COLS * 2));
//printf("Sum of all elements = %d\n", sum2d_1(data));
//printf("Sum of all elements = %d\n", sum2d_2(data, ROWS));
//printf("Sum of all elements = %d\n", sum2d_3(&data[0][0], ROWS, COLS));
return 0;
}
int sum2d_1(int ar[ROWS][COLS])
{
int r, c, tot = 0;
for (r = 0; r < ROWS; r++)
for (c = 0; c < COLS; c++)
tot += ar[r][c];
return tot;
}
int sum2d_2(int ar[][COLS], int row)
{
int r, c, tot = 0;
for (r = 0; r < row; r++)
for (c = 0; c < COLS; c++)
tot += ar[r][c];
return tot;
}
int sum2d_3(int* ar, int row, int col)
{
int r, c, tot = 0;
for (r = 0; r < row; r++)
for (c = 0; c < col; c++)
tot += *(ar + c + col * r); // ar[c + col * r]
return tot;
}