Unit 61. 함수 반환값
구조체, 공용체처럼 사용하는 구조는 비슷하다.
반환값 자료형에 포인터로 함수이름을 적고,
중괄호에 return 될 반환값을 써주면 된다.
이러한 내용의 구조체를 반환하는 함수도 정의가 가능하다.
#include <stdio.h>
#include <stdbool.h>
float getArmor() {
return 20.500000;
}
bool hasSlowSkill() {
return false;
}
int main()
{
float armor;
bool slow;
armor = getArmor();
slow = hasSlowSkill();
printf("%f\n", armor);
printf("%s\n", slow == true ? "true" : "false");
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* getName() {
char* name = malloc(sizeof(char) * 20);
strcpy(name, "Neptune");
return name;
}
int main()
{
char* name;
name = getName();
printf("%s\n", name);
free(name);
return 0;
}
반환될 자료형이 char 포인터형이고, malloc으로 동적 메모리 할당이
되어있기 때문에 밑에 free 부분을 살펴봐야한다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void* allocMemory()
{
char* name = malloc(sizeof(char) * 100);
return name;
}
int main()
{
char* name;
float* stats;
name = allocMemory();
strcpy(name, "Mercury");
printf("%s\n", name);
free(name);
stats = allocMemory();
stats[0] = 87.969f;
stats[1] = 115.8776f;
printf("%f %f\n", stats[0], stats[1]);
free(stats);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
struct Point2D {
int x;
int y;
};
struct Point2D* allocPoint2D() {
struct Point2D* pos = malloc(sizeof(struct Point2D));
pos->x = 90;
pos->y = 75;
return pos;
}
int main()
{
struct Point2D* pos1;
pos1 = allocPoint2D();
printf("%d %d\n", pos1->x, pos1->y);
free(pos1);
return 0;
}
Unit 62. 함수 매개변수
#include <stdio.h>
float setAttackSpeed(float a) {
return printf("Attack Speed: %f\n", a);
}
int main()
{
setAttackSpeed(0.638f);
setAttackSpeed(1.23f);
return 0;
}
철자 틀렸다고 심사문제 틀렸다고 하시는건 조금...ㅠ (speed -> Speed)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
long long add(long long num1, long long num2) {
return num1 + num2;
}
int main()
{
long long num1, num2;
scanf("%lld %lld", &num1, &num2);
printf("%lld\n", add(num1, num2));
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
struct Point3D {
float x;
float y;
float z;
};
struct Point3D* allocPoint3D(float x, float y, float z) {
struct Point3D* p1;
p1 = malloc(sizeof(struct Point3D));
p1->x = x;
p1->y = y;
p1->z = z;
return p1;
}
int main()
{
float x, y, z;
struct Point3D* pos1;
scanf("%f %f %f", &x, &y, &z);
pos1 = allocPoint3D(x, y, z);
printf("%f %f %f\n", pos1->x, pos1->y, pos1->z);
free(pos1);
return 0;
}
Unit 63. 함수 포인터 매개변수
함수에 포인터 매개변수를 지정하고 값을 가져오기 위해서는
똑같이 역참조로 값을 가져오고 저장할 수 있다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int getQuotientAndRemainder(int a, int b, int* c) {
*c = a % b;
return a / b;
}
int main()
{
int num1;
int num2;
int quotient; // 몫
int remainder; // 나머지
scanf("%d %d", &num1, &num2);
quotient = getQuotientAndRemainder(num1, num2, &remainder);
printf("%d %d\n", quotient, remainder);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
void allocArray(void** a, int b, int c) {
*a = malloc(b * c);
}
int main()
{
long long* numArr1;
int* numArr2;
allocArray((void**)&numArr1, 10, sizeof(long long));
allocArray((void**)&numArr2, 3, sizeof(int));
scanf("%lld %d", &numArr1[9], &numArr2[2]);
printf("%lld %d\n", numArr1[9], numArr2[2]);
free(numArr2);
free(numArr1);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void printFullName(char *a, char *b) {
printf("%s%s", a, b);
}
int main()
{
char familyName[31];
char givenName[31];
scanf("%s %s", familyName, givenName);
printFullName(familyName, givenName);
return 0;
}
Unit 64. 함수 배열 매개변수
함수안에 배열을 매개변수로 사용하기 위해서는
자료형의 매개변수 뒤에 []를 선언해주면 된다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void printReverse(int a[], int b) {
for (int i = b - 1; i >= 0; i--) {
printf("%d ", a[i]);
}
}
int main()
{
int numArr[10];
scanf("%d %d %d %d %d %d %d %d %d %d",
&numArr[0], &numArr[1], &numArr[2], &numArr[3], &numArr[4],
&numArr[5], &numArr[6], &numArr[7], &numArr[8], &numArr[9]
);
printReverse(numArr, sizeof(numArr) / sizeof(int));
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void transpose(int (*a)[4], int b) {
int temp[1][1];
for (int i=0; i<b; i++) {
for (int j=0; j<i; j++) {
temp[0][0] = a[i][j];
a[i][j] = a[j][i];
a[j][i] = temp[0][0];
}
}
}
int main()
{
int matrix[4][4];
scanf("%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
&matrix[0][0], &matrix[0][1], &matrix[0][2], &matrix[0][3],
&matrix[1][0], &matrix[1][1], &matrix[1][2], &matrix[1][3],
&matrix[2][0], &matrix[2][1], &matrix[2][2], &matrix[2][3],
&matrix[3][0], &matrix[3][1], &matrix[3][2], &matrix[3][3]
);
int n = sizeof(matrix[0]) / sizeof(int);
transpose(matrix, n);
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d ", matrix[i][j]);
}
printf("\n");
}
return 0;
}
앞에 숫자 뒤바꾸기처럼 matrix를 앞뒤로 뒤집어주고,
임시로 저장할 배열에 값을 넣어준다.
Unit 65. 함수 구조체 매개변수
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct Point2D {
int x;
int y;
};
int movePoint2D(struct Point2D* p1, int offsetX, int offsetY) {
p1->x = p1->x + offsetX;
p1->y = offsetY + p1->y;
}
int main()
{
struct Point2D p1;
int offsetX, offsetY;
scanf("%d %d %d %d", &p1.x, &p1.y, &offsetX, &offsetY);
movePoint2D(&p1, offsetX, offsetY);
printf("%d %d\n", p1.x, p1.y);
return 0;
}#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <math.h>
struct Point2D {
int x;
int y;
};
double getDistance(struct Point2D p1, struct Point2D p2) {
double distance = sqrt(pow((p2.x - p1.x), 2) + pow((p2.y - p1.y), 2));
return distance;
}
int main()
{
struct Point2D p1;
struct Point2D p2;
scanf("%d %d %d %d", &p1.x, &p1.y, &p2.x, &p2.y);
printf("%f\n", getDistance(p1, p2));
return 0;
}
Unit 66. 함수 가변인자
#include <stdarg.h> // va_list, va_start, va_arg, va_end가 정의된 헤더 파일
해당 내용을 사용하여 가변 인자를 사용할 수 있다.
va_list는 가변 인자 목록을, va_start는 가변 인자 포인터 설정을,
va_arg는 가변 인자 포인터에서 특정 자료형 크기만큼 값을 가져온다.
va_end는 가변 인자 처리가 끝났을 때 포인터를 NULL로 초기화한다.
함수에서는 ...로 가변 인자를 설정한다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdarg.h>
int sum(int args, ...)
{
int sum = 0;
va_list ap;
va_start(ap, args);
for (int i = 0; i < args; i++) {
sum += va_arg(ap, int);
}
va_end(ap);
return sum;
}
int main()
{
int num1, num2;
int num3, num4, num5;
scanf("%d %d", &num1, &num2);
scanf("%d %d %d", &num3, &num4, &num5);
printf("%d\n", sum(2, num1, num2));
printf("%d\n", sum(3, num3, num4, num5));
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdarg.h>
int getSum(char* args, ...)
{
int sum = 0;
int i = 0;
va_list ap;
va_start(ap, args);
while (args[i] != '\0')
{
switch (args[i])
{
case 'i':
sum += va_arg(ap, int);
break;
case 'd':
va_arg(ap, double);
break;
case 's':
va_arg(ap, char*);
break;
default:
break;
}
i++;
}
va_end(ap);
return sum;
}
int main()
{
int num1, num2, num3;
scanf("%d %d %d", &num1, &num2, &num3);
printf("%d\n", getSum("isi", num1, "C", 10));
printf("%d\n", getSum("sdsi", "Hello, world!", 5.3, "A", num2));
printf("%d\n", getSum("iiss", 25, 38, "k", "R"));
printf("%d\n", getSum("sidii", "Hello, C", num3, 2.234567, 878, 1291));
return 0;
}
정수의 합만 구하기 때문에 int에 해당하는 값들만 더해준다.
Unit 67. 함수 재귀호출
재귀 호출은 반환되는 값 혹은 함수 로직에서
무한정 실행시킬 수 있으므로 오버 플로우에 유의해야한다.
해당 내용에서는 팩토리얼을 알고리즘으로 구현하는 방법을 설명한다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int fib(int num1) {
if (num1 == 0 || num1 == 1)
return num1;
return fib(num1 - 1) + fib(num1 - 2);
}
int main()
{
int num1;
scanf("%d", &num1);
printf("%d\n", fib(num1));
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int sum(int n)
{
if (n == 1)
return 1;
return n+sum(n-1);
}
int main()
{
int n = 0;
scanf("%d", &n);
printf("%d\n", sum(n));
return 0;
}
Unit 68. 함수 포인터 사용
함수 포인터는 함수를 저장하는 포인터이다.
해당 포인터를 주고 받거나 함수를 호출할 수 있다.
반환값과 매개변수가 없는 함수와 함수 포인터를 선언해서 사용한다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
int add(int* a, int* b)
{
return *a + *b;
}
int sub(int* a, int* b)
{
return *a - *b;
}
int mul(int* a, int* b)
{
return *a * *b;
}
int div(int* a, int* b)
{
return *a / *b;
}
int main()
{
char funcName[10];
int num1, num2;
scanf("%s %d %d", funcName, &num1, &num2);
int (*fp)(int *, int *) = NULL;
if (strcmp(funcName, "add") == 0)
fp = add;
else if (strcmp(funcName, "sub") == 0)
fp = sub;
else if (strcmp(funcName, "mul") == 0)
fp = mul;
else
fp = div;
printf("%d\n", fp(&num1, &num2));
return 0;
}
Unit 69. 함수 포인터 활용
함수 포인터를 배열에 활용할때는 (*fp[])(int, int) 등과 같이
사용하면 된다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct Person {
char name[30];
int age;
void (*print)(struct Person*);
};
void print(struct Person* p)
{
printf("%s %d\n", p->name, p->age);
}
void executer(void (*fp[])(struct Person*), struct Person p[], int count)
{
for (int i = 0; i < count; i++)
{
fp[i](&p[i]);
}
}
void (*getPrintFunc(struct Person* p))(struct Person*)
{
return print;
}
int main()
{
struct Person p[3];
p[0].print = print;
p[1].print = print;
p[2].print = print;
scanf("%s %d %s %d %s %d",
p[0].name, &p[0].age,
p[1].name, &p[1].age,
p[2].name, &p[2].age
);
void (*fp[3])(struct Person*);
for (int i = 0; i < sizeof(p) / sizeof(struct Person); i++)
{
fp[i] = getPrintFunc(&p[i]);
}
executer(fp, p, sizeof(p) / sizeof(struct Person));
return 0;
}
Unit 70. 파일 문자열 읽고 쓰기
파일을 여는 방법은 FILE 파일 포인터를 선언하고
fopen으로 열게 된다. 파일명과 파일모드를 사용한다.
파일을 열고 파일 포인터를 얻은 뒤 fprintf 함수를 사용하고,
fclose로 파일 포인터를 닫는다.
파일 모드에는 r/w/a/r+/w+/a+/t/b이 있으며,
주로 읽는 r과 쓰는 w를 사용하게 된다.
그리고나서 rb, rt와 같이 조합해서 사용한다.
위의 내용 그대로 fopen() -> fprintf() -> fcloase() 순으로 진행된다.
그외에 fscanf, fputs, fwrite, fgets, fread 등을 사용하게 된다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
int main()
{
char name[31];
int order;
scanf("%s %d", name, &order);
FILE* fp = stdout;
fprintf(fp, "The %dth Satellite of Jupiter: %s", order, name);
fclose(fp);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char* buffer = malloc(100);
memset(buffer, 0, 100);
FILE* fp = fopen("words.txt", "r");
fread(buffer, 100, 1, fp);
printf("%s\n", buffer);
fclose(fp);
free(buffer);
return 0;
}
Unit 71. 파일 포인터
파일 크기 구할때는 fseek, ftell 함수를 사용한다.
읽기 모드로 열고 포인터를 끝으로 옮긴다음 현재위치를 얻고 출력한다.
처음부터 이동, 현재부터 이동, 끝부터 이동에 관해서
SEEK_SET, CUR, END 순서로 사용한다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int getFileSize(FILE* fp)
{
int size;
int currPos = ftell(fp);
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, currPos, SEEK_SET);
return size;
}
char* getData(int offset, int size, int* count, FILE* fp)
{
char* buffer = malloc(size + 1);
memset(buffer, 0, size + 1);
fseek(fp, offset, SEEK_SET);
*count = fread(buffer, sizeof(char), size, fp);
return buffer;
}
int main()
{
char* buffer;
int size;
int count;
FILE* fp = fopen("words.txt", "r");
size = getFileSize(fp);
buffer = getData(0, size, &count, fp);
printf("%s\n", buffer);
printf("%d", count);
fclose(fp);
free(buffer);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char* buffer;
int size = 0;
FILE* fp = fopen("words.txt", "r");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
buffer = malloc(size);
fseek(fp, 7, SEEK_SET);
fread(buffer, 4, 1, fp);
printf("%s", buffer);
memset(buffer, 0, 10);
fseek(fp, -6, SEEK_END);
fread(buffer, 2, 1, fp);
printf("%s", buffer);
free(buffer);
return 0;
}
words.txt는 Github 저장소에서 사용하라고 했는데 주소는 다음과 같다.
(https://github.com/gilbutITbook/006759/tree/master/Unit%2071)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
char* buffer;
int size = 0;
FILE* fp = fopen("words.txt", "r");
fseek(fp, 0, SEEK_END);
size = ftell(fp);
fseek(fp, 0, SEEK_SET);
buffer = malloc(size + 1);
memset(buffer, 0, 10);
fread(buffer, size, 1, fp);
for (int i = size - 1; i >= 0; i--) {
fwrite(&buffer[i], sizeof(char), 1, stdout);
}
free(buffer);
return 0;
}
앞 문제들에서 거꾸로 출력처럼 --로 작성해준다.
Unit 72. 파일 구조체 읽고 쓰기
파일에 구조체를 쓸때는 fwrite 함수를 사용한다.
파일에 구조체를 읽을 때는 fread 함수를 사용한다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#pragma pack(push, 1)
struct X820Firmware {
int serial;
char desc[13];
short tag;
char mode;
};
#pragma pack(pop)
int main()
{
struct X820Firmware x1;
memset(&x1, 0, sizeof(x1));
FILE* fp = stdout;
x1.serial = 1800891002;
strcpy(x1.desc, "X820 Firmware");
x1.tag = 8512;
x1.mode = '-';
fwrite(&x1, sizeof(x1), 1, stdout);
fclose(fp);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <string.h>
#pragma pack(push, 1)
struct X850Firmware {
short serial;
char mode;
char desc[20];
int version;
};
#pragma pack(pop)
int main()
{
struct X850Firmware x1;
FILE* fp = fopen("x850.bin", "rb");
fread(&x1, sizeof(x1), 1, fp);
printf("%d\n%c\n%s\n%d", x1.serial, x1.mode, x1.desc, x1.version);
fclose(fp);
return 0;
}
Unit 73. 배열 정렬
1) 버블 정렬은 현재와 다음 값을 비교해서 큰 값을
다음 자리로 보낸다.
2) 퀵 정렬에서는 오름차순 정렬 조건에서 다음 값이 크면 -1을
작으면 1을 같으면 0을 반환하여 정렬할 수 있게 만든다.
(이때, 비교 인자의 뺄셈에서 뒷 값이 앞으로가면 내림차순이 된다)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
void bubble_sort(int arr[], int count) {
int temp;
for (int i=0; i<count; i++) {
for (int j = 0; j<count-1; j++) {
if (arr[j] < arr[j + 1]) {
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
}
int main()
{
int numArr[10];
scanf("%d %d %d %d %d %d %d %d %d %d",
&numArr[0], &numArr[1], &numArr[2], &numArr[3], &numArr[4],
&numArr[5], &numArr[6], &numArr[7], &numArr[8], &numArr[9]
);
bubble_sort(numArr, sizeof(numArr) / sizeof(int));
for (int i = 0; i < 10; i++)
{
printf("%d ", numArr[i]);
}
printf("\n");
return 0;
}
문제에서 출력 값이 역순으로 출력되기 때문에,
기존 버블 정렬에서 arr[j]가 arr[j+1]보다 작은 값으로 비교해준다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare(const void* a, const void* b) {
char text1 = *(char*)a;
char text2 = *(char*)b;
return strcmp((char*)b, (char*)a);
}
int main()
{
char s1[10][20];
scanf("%s %s %s %s %s %s %s %s %s %s",
s1[0], s1[1], s1[2], s1[3], s1[4], s1[5], s1[6], s1[7], s1[8], s1[9]
);
qsort(s1, sizeof(s1) / sizeof(s1[0]), sizeof(s1[0]), compare);
for (int i = 0; i < 10; i++)
{
printf("%s ", s1[i]);
}
printf("\n");
return 0;
}
문자열을 비교해서 역순으로 출력해야하기 때문에,
strcmp 함수를 사용하고 b, a순으로 값을 비교한다.
Unit 74. 연결 리스트
NODE 구조체에서 중요한 부분은 struct NODE *next;라고 설명한다.
next에는 NODE 구조체로 만든 다른 노드의 메모리 주소를 저장한다. (자기 자신 X)
malloc(sizeof(struct NODE))로 생성된 head, node1, node2 각각의 next가 연결된다.
node1의 주소 -> node2의 주소 -> NULL로 연결 리스트가 생성된다.
기준 노드 뒤에 새 노드를 추가하게 되면 기준 노드 -> 새 노드 -> 기존 다음 노드 순으로 진행된다.
노드 삭제는 free 함수로 삭제할 노드의 메모리를 해제해준다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
struct NODE {
struct NODE* next;
int data;
};
void addFirst(struct NODE* target, int data)
{
struct NODE* newNode = malloc(sizeof(struct NODE));
newNode->next = target->next;
newNode->data = data;
target->next = newNode;
}
void removeNode(struct NODE* node, int data)
{
if (node == NULL)
return NULL;
struct NODE* prev = node;
while (prev != NULL) {
struct NODE* curr = prev->next;
if (curr->data == data) {
prev->next = curr->next;
free(curr);
break;
}
prev = prev->next;
}
}
int main()
{
int numArr[10] = { 0, };
int removeNum;
scanf("%d %d %d %d %d %d %d %d %d %d",
&numArr[0], &numArr[1], &numArr[2], &numArr[3], &numArr[4],
&numArr[5], &numArr[6], &numArr[7], &numArr[8], &numArr[9]
);
scanf("%d", &removeNum);
struct NODE* head = malloc(sizeof(struct NODE));
head->next = NULL;
for (int i = 0; i < 10; i++)
{
addFirst(head, numArr[i]);
}
removeNode(head, removeNum);
struct NODE* curr = head->next;
while (curr != NULL)
{
printf("%d ", curr->data);
curr = curr->next;
}
curr = head->next;
while (curr != NULL)
{
struct NODE* next = curr->next;
free(curr);
curr = next;
}
free(head);
return 0;
}
특정 노드를 삭제할 때 직전 노드 포인터를 prev에 저장한다.
직전 노드의 다음 노드에 현재 노드의 다음 노드를 넣고,
free로 현재 노드를 해제한다.
Unit 75. 매크로 사용
#define을 헤더 상단에 매크로이름과 값을 정의해주고 사용한다.
해당 매크로를 동일하게 사용할 수 있다.
#define 매크로이름() 함수() 처럼도 사용할 수 있다.
여러 줄을 매크로로 정의할 때는 세미콜론 뒤에 \을 작성한다.
(맨 마지막줄은 작성 x)
또한, #define에서 ##을 사용하면 여러 값을 붙일 수도 있다.
그리고 #undef로 정의된 매크로 해제가 가능하다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#define RGB(r, g, b) (((unsigned char)(r))|((unsigned short)((unsigned char)(g)<<8))|((unsigned int)((unsigned char)(b)<<16)))
int main()
{
int r, g, b;
scanf("%d %d %d", &r, &g, &b);
printf("#%06X\n", RGB(r, g, b));
printf("#%06X\n", RGB(1 & 1, 2 & 2, 3 & 3));
return 0;
}
출력은 잘되는데 계속 답이 아니라고 나와서 진짜 화난 문제..
이유는 () 괄호에 대한 연산자 우선순위에 있었다.. 머 내잘못이겠지..
다들 연산자 우선순위에 조심하자. 그리고 unsigned char로 받은 변수에 대해서
short, int로 비트 연산자 시켜준다.
#include <stdio.h>
struct Point2D {
float x, y;
};
#define ARRSIZE(x) sizeof(x)/sizeof(x[0])
int main()
{
int numArr1[10];
long long numArr2[5];
struct Point2D p[3];
printf("%d\n", ARRSIZE(numArr1));
printf("%d\n", ARRSIZE(numArr2));
printf("%d\n", ARRSIZE(p));
return 0;
}
배열이 차지하는 크기 = sizeof(x)에서
요소 [0] 만큼의 크기를 나눈다.
Unit 76. 조건부 컴파일
조건부 컴파일은 정의된 매크로에 대해서
#ifdef, #endif 사이의 코드를 컴파일한다.
조건부 컴파일은 값 또는 식으로도 할 수 있는데,
#if ~ 코드 ~ #endif 처럼 나타낼 수 있다.
참고로 직접 .h 헤더 파일을 추가해서 #include 할 수도 있다.
#include <stdio.h>
#define TARGET_PLATFORM 4
#define PLATFORM_UNKNOWN 0
#define PLATFORM_IOS 1
#define PLATFORM_ANDROID 2
#define PLATFORM_WIN32 3
#define PLATFORM_LINUX 4
#define PLATFORM_MAC 5
#if defined(IOS)
#define TARGET_PLATFORM PLATFORM_IOS
#endif
#if defined(ANDROID)
#define TARGET_PLATFORM PLATFORM_ANDROID
#endif
#if defined(WIN32) && defined(_WINDOWS)
#define TARGET_PLATFORM PLATFORM_WIN32
#endif
#if defined(LINUX)
#define TARGET_PLATFORM PLATFORM_LINUX
#endif
#if defined(MAC)
#define TARGET_PLATFORM PLATFORM_MAC
#endif
#if TARGET_PLATFORM == PLATFORM_LINUX
#define printf printf
#define fprint fprintf
#else
#define printf
#define fprintf
#endif
int main()
{
printf("OS: Linux\n");
return 0;
}
#include <stdio.h>
#define printf
#define fprintf
#define TARGET_PLATFORM 2
#include "platform.h"
int main()
{
printf("OS: Android\n");
return 0;
}
Unit 77. 여러 소스 파일 사용
여기서부터는 프로그램 설계에 대해서 배우게 된다.
작업한 계산기 예시에 대해서 총 6개의 파일을 작성하면 다음과 같은 결과가 나온다.
#include "append.h"
#include "print.h"
int main()
{
DATA data = { 0, };
append(&data, "The ", "Little Prince");
print(&data);
return 0;
}
Unit 78. 전역 변수 사용
함수 외부, 즉 헤더 파일 밑에 전역에 선언해주는 변수를 전역 변수라고 한다.
(함수 바깥에서 선언)
전역 변수는 초깃값을 지정하지 않으면 0으로 초기화된다.
해당 전역 변수를 다른 파일에서 사용할때는 extern 자료형 전역변수를 적어준다.
#include <stdio.h>
#include <stdlib.h>
struct Point2D {
int x;
int y;
};
struct Point2D* p1;
void printPoint2D()
{
printf("%d %d\n", p1->x, p1->y);
}
int main()
{
p1 = malloc(sizeof(struct Point2D));
p1->x = 10;
p1->y = 20;
printPoint2D();
free(p1);
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "person.h"
extern struct Person* p1;
int main()
{
p1 = malloc(sizeof(struct Person));
strcpy(p1->name, "홍길동");
p1->age = 30;
strcpy(p1->address, "서울시 용산구 한남동");
printf("%s %d %s\n", p1->name, p1->age, p1->address);
free(p1);
return 0;
}
Unit 79. 기억 부류 지정자
자동 변수는 auto int 처럼 사용하면 되고 현재 블록이 끝나면 소멸된다.
정적 변수는 static int 처럼 사용하면 된다.
정적 전역 변수는 파일 외부에서 사용할 수 없다.
정적 변수는 초깃값을 지정하지 않으면 전역이든 지역이든 0으로 초기화된다.
정적 변수는 프로그램이 시작될 때 생성되고 끝날 때 소멸된다.
정적 함수는 static void 함수()로 정의한다.
레지스터 변수는 메모리 대신 CPU 레지스터를 사용하며 register int 처럼 사용한다.
그 외에도 const, volatile, restrict, _Atomic 의 키워드 등이 있다.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
struct Point2D {
int x, y;
};
struct Point2D movePoint(int offset)
{
static struct Point2D p = {10, 20};
p.x = p.x + offset;
p.y = p.y + offset;
return p;
}
int main()
{
int num1;
struct Point2D p;
scanf("%d", &num1);
p = movePoint(num1);
printf("%d %d\n", p.x, p.y);
p = movePoint(num1);
printf("%d %d\n", p.x, p.y);
p = movePoint(num1);
printf("%d %d\n", p.x, p.y);
return 0;
}
Unit 80. 실행 파일 옵션
전에 자주봤던 패턴이 있는데 바로 다음이다.
int main(int argc, char *argv[])
main 함수에서 첫 번째 매개변수 argc는 옵션의 개수가 되고,
argv는 옵션 문자열의 배열이 된다. (디컴파일, 리버싱 공부할 때 많이 봤음)
옵션의 개수와 옵션 문자열을 배열로 받으면 옵션의 개수만큼 (i < argc) 반복하는
for문 사용이 가능하고 argv[i]에 대한 옵션 문자열을 printf로 출력 가능하다.
유닛 80번은 심사문제가 없다.
고생했다...
'Study > C언어' 카테고리의 다른 글
[C언어] HTTP 서버 구현.c (2) (0) | 2022.10.07 |
---|---|
[C언어] HTTP 서버 구현.c (1) (0) | 2022.10.06 |
[C언어] 코딩도장 공부 (Unit 41~60) (0) | 2022.09.23 |
[C언어] 코딩도장 공부 (Unit 21~40) (0) | 2022.09.22 |
[C언어] 코딩도장 공부 (Unit 8~20) (0) | 2022.09.20 |