본문 바로가기
교육관련/한화비전 VEDA 수강일지

[VEDA 1기 수강일지] 5일차 - C언어 기초 (5) : 파일입출력, 전처리, 비트연산, volatile

by 김수효 2024. 7. 19.
수강한 개념

 

파일입출력
- 문자 출력 -> 버퍼에 있다가 버퍼가 다 차거나 엔터를 치면 넘어감
- 바이너리 파일 
- feof
- fprintf 편하긴한데 용량 문제가 있음 (숫자를 문자로 변환하여 저장함)
- fread, fwrite 위 문제를 해결 but 파일을 열어 확인해보기 어려움

전처리
- #define : 매크로
- 매크로 함수 : 함수는 아닌데 식이 대체되어 들어감
ㄴ 함수를 호출하면 비용이 좀 든다 -> 아주 가벼운 함수는 매크로로 쓸 수 있음.
ㄴ 가독성은 좋다
ㄴ 주의 : 매크로 함수에서는 우선순위 연산자 주의해서 사용하기

비트연산

- & | ^ ~ << >> 

- | : 세팅할때 사용

#include <stdio.h>
#define bitSet(x, bit) ((x) |= (1<<(bit)))
#define bitClear(x, bit) ((x) &= (~(1<<(bit))))	//0으로 클리어 
#define bitFlip(x, bit) ((x) ^= (1<<(bit)))	//토글
#define bitIsSet(x, bit) ((x) &= (1<<(bit)))	//현재값

int main()
{
	unsigned cnum = 0x16;	//00010110 
	bitSet(cnum, 3); 
	printf("%x ", cnum);	//00011110  //1e

	bitClear(cnum, 3); 
	printf("%x ", cnum);	//00010110  //16

	bitFlip(cnum, 3);
	printf("%x ", cnum);	//00011110  //1e

	if(bitIsSet(cnum, 3))	//00011110  //1e
		printf("T");
	else printf("F");

	return 0;
}


이미 정의된 매크로

	printf("filename : %s\n", __FILE__);
	printf("function : %s\n", __FUNCTION__);
	printf("line no : %d\n", __LINE__);
	printf("Date : %s\n", __DATE__);

 

조건부 컴파일 지시자

#define DEBUG
...

#ifdef DEBUG //정의 되어있으면 DEBUG 실행
...
#endif


- 디버깅할때 실수로 안지우거나 중요한 것 까지 지워버리는 실수 방지

#pragma
- 컴파일 방법 세부 제어

#pragma pack

- 구조체 얼라이먼트 크기 변경 -> 패딩바이트 조정

 


분할컴파일
- 구조체 등이 중복 정의 되는 경우를 대비한 기능
#ifndef : 정의 되어있지 않다면 정의

volatile 지시자
- 변수 선언부에 사용, 최적화에서 제외한다.

ㄴ 모든 코드를 작성한대로 컴파일하지는 않음 -> 최적화 진행 (보통의 경우)

ㄴ 그런데 그러면 안되는 경우가 있음

volataile int n;

 

 

- 임베디드 시스템에서 많이 사용.
- 하나하나 다 컴파일 -> 최적화를 막는 지시자 -> 통신을 위해서



문제 구현 / 개선방안

 

1. 이전 코드 응용 : 링크드 리스트 -> 파일입출력으로 노드 값 받아오기

 

노드값을 입력받던 함수와 출력하던 함수를 응용

ㄴ 표준입출력으로 처리하던 부분을 파일입출력으로 처리

***

void load(struct link** HEAD, struct link** TAIL)
{
	FILE* fp;
	
#ifdef DEBUG
	printf("filename : %s\n", __FILE__);
	printf("function : %s\n", __FUNCTION__);
	printf("line no : %d\n", __LINE__);
	printf("Date : %s\n", __DATE__);
#endif

	if ((fp = fopen("memo.txt", "rb")) == NULL) // 바이너리 모드로 오픈
	{
		fprintf(stderr, "file not found"); return 1;
	}

	//파일 읽어오기
	while (1)
	{
		struct link* temp = (struct link*)malloc(sizeof(struct link));
		if (temp == NULL)//메모리 할당 실패
		{
			printf("할당 실패\n");
			exit(1);
		}

		fread(temp, sizeof(struct link), 1, fp); //구조체에 읽어오기
		if (feof(fp)) break;//파일의 끝에서 종료
		temp->next = NULL; //주소 초기화


		if (*HEAD == NULL) //첫번째 노드 
		{
			*HEAD = *TAIL = temp;
		}
		else  //첫번째 노드가 아닌경우
		{
			(*TAIL)->next = temp;
			*TAIL = (*TAIL)->next; // == temp;
		}

	}

	fclose(fp);

}

void save(struct link** HEAD, struct link** TAIL)
{
	FILE* fp;
	
	if ((fp = fopen("memo.txt", "wb")) == NULL) // 바이너리 모드로 오픈
	{
		fprintf(stderr, "file not found"); return 1;
	}

	//출력
	struct link* temp = (struct link*)malloc(sizeof(struct link));
	if (temp == NULL)//메모리 할당 실패
	{
		printf("할당 실패\n");
		exit(1);
	}

	temp = *HEAD;
	while (temp != NULL)
	{
		printf("%d, %s\n", temp->id, temp->Bookname);
		fwrite(temp, sizeof(struct link), 1, fp);
		temp = temp->next;
	}

	fclose(fp);
}

***

 

기타 사항 

 

개인공부

- 프로세스

ㄴ 메모리에 올라와 실행되고 있는 프로그램의 인스턴스 (독립적)

ㄴ 독립된 메모리 영역 할당

ㄴ 최소 1개의 스레드 보유

 

- 스레드

ㄴ 프로세스의 수행경로

ㄴ 레지스터와 스택만 분리, 코드영역, 데이터 영역, 힙은 공유

 

- 멀티 프로세스

ㄴ 하나의 프로그램을 여러개의 프로세스로 구성

ㄴ 프로세스 간의 통신(IPC) 필요

 

- 멀티 스레드

ㄴ 한 프로세스에서 여러개의 스레드 구성

ㄴ 멀티 프로세스보다 통신 방법이 간단함

ㄴ 스레드 간 자원 공유를 전역변수로 하기 때문에 동기화 문제 발생 가능

 

 

- Context Switching

ㄴ 여러 브로그램을 CPU가 돌아가면서 처리하는 작업

ㄴ 동작중인 프로세스 대기, 해당 프로세스 상태 보관, 대기하던 다른 프로세스 동작, 이전 프로세스 복구

 


VEDA 바로가기 : www.vedacademy.co.kr

VEDA(한화비전 아카데미) 영상으로 확인하기 : https://url.kr/zy9afd

본 후기는 VEDA(한화비전 아카데미) 1기 학습 기록으로 작성되었습니다.

댓글