c언어, web, system 크게 세 가지 분야로 배웠고 그 중 C언어에 대한 활동들 정리
글 속의 조사 과제 + 백준 등 여러 문제들을 깃허브 c언어 폴더에 워드 파일로 정리되어있음
<깃허브 링크>
<C언어 -1>
1) C언어 소개

절차 지향 언어 VS 객제 지향 언어
2) 변수와 상수

3) 입출력
4) 연산자
5) 조건문
- 조사 과제
1 컴파일러에 대해 조사하기 (컴파일언어와 인터프리터언어(≠스크립트언어)의 차이점 조사)
2 디버그모드와 릴리즈모드의 차이 조사
3 리틀엔디안 vs 빅엔디안 조사 (0x41424344가 빅엔디안일 때 리틀엔디안으로는?)
4 c파일이 실행파일이 되기까지의 과정 조사
5 기계어와 어셈블리어에 대해 조사
<C언어 -2>
반복문
종류 - for문, while문, do~while문, go to문

출처: https://coding-factory.tistory.com/382
출처: https://www.happyfam.or.kr/ysoh/%EC%9E%90%EB%8F%99-%EC%A0%80%EC%9E%A5-%EB%AC%B8%EC%84%9C/
1) continue & break
2) while문
3) 다중 for문
4)switch 문
switch(조건){
case 조건:
문장
case 조건:
문장
default:
문장
}
- 조사 과제
1. do~while문 사용해서 구구단 만들기
2. goto문에 대해 조사하고, 간단한 예제 실습
<c언어 -3>
1) 함수
2) 함수의 구조
int main(void)
int main (void)
return type function name argument
return type: 함수가 반환할 자료형
function name: 함수의 이름
argument: 함수가 사용할 인자 (매개변수)
3) 함수의 선언과 호출
4) 지역변수와 전역변수
구분
|
일반 지역 변수
|
정적 지역 변수
|
전역 변수
|
정적 전역 변수
|
선언 위치
|
함수 안
|
함수 안
|
함수 밖
|
함수 밖
|
생성 시점
|
변수 선언 시
|
프로그램 시작 시
|
프로그램 시작 시
|
프로그램 시작 시
|
해제 시점
사용 범위
|
함수 리턴 시
함수 안
|
프로그램 종료 시
함수 안
|
프로그램 종료 시
프로그램 전체
|
프로그램 종료 시
선언된 소스 파일
|
초기화하지
않았을 때
|
쓰레기 값
(초기화 X)
|
0으로 초기화
|
0으로 초기화
|
0으로 초기화
|
5) 배열
▶ 같은 자료형의 변수들로 이루어진 '유한' 집합
배열을 구성하는 각각의 항목을 배열 요소라고 부름
배열의 위치를 가리키는 숫자인 인덱스는 1인 아닌 0부터 시작
int main() {
int arr[5] = { 1,2,3,4,5 };
int i = 0;
for (int i = 0; i < 5; i++)
printf("%x\n", &arr[i]);
}

int는 4바이트 할당, 4씩 증가
- 다차원 배열


▶ 문자열 - 연속된 문자들의 모임
문자열의 끝에는 문자열의 끝을 표현하는 널 문자('\0')를 함께 보관해야함

※ 배열 사용시 주의사항
#include<stdio.h>
int main() {
char str[9] = "minyeong";
str = "kim-min"; //컴파일 에러
//문자 배열에 다른 문자열을 대입할 수 없다.
}
- 띄어쓰기가 있는 문자열을 입력해야 할 때 gets, fgets를 사용하는 방법도 있음
#include<stdio.h>
int main() {
char str[100];
scanf("%s", str); //str에 공백(띄어쓰기 & 엔터가 있을 때까지 입력받음)
scanf("%[^\n]", str); //띄어쓰기가 있는 문자열을 입력해야 할 때 사용
scanf("%100[^\n]", str); //\n가 입력될 때까지 100글자를 scanf 함
}
배열의 크기를 100으로 지정해놨지만 gets, scanf는 크기가 100넘게 입력 할 수도 있음
→ 버퍼 오버 플로우 발생 ! (나중에 system 영역에서 자세하게 다룰 예정)
를 통해서 100자 제한을 걸어줌
- 조사 과제
1. 난수 관련 함수에 대해 조사 및 실습 (헤더가 무엇인지도 간단하게 같이 조사)
2 .call by reference & call by value 조사 및 구현
3 .main 함수의 argc, argv에 대해 조사 및 실습
4 .메모리 영역(code, data, bss, stack, heap)에 대해서 자세히 조사
5. static변수에 대해 조사 및 실습
6. Calling Convention: cdecl 와 stdcall 에 대해 조사
7. 버블 정렬에 대해 조사 (실습과제에 사용)
<c언어 -4>
1) 디버깅
▶ 프로그래밍 과정 중 발생하는 오류나 비정상적인 연산(버그)를 찾고 수정하는 것
디버그를 하는 행위 = 디버깅
※ visual studio 디버깅 방법

2) 문자열 함수
▶ 문자열을 다룰 때 사용되는 다양한 함수들
헤더) string.h / stdlib.h
함수) strlen / strcpy / strstr / strcat / strcmp 등
3) 재귀함수
▶ 자기 자신을 호출하는 함수

return 값이 있는 재귀함수
return 문은 함수에서 결괏값을 반환할 때 사용함
함수 정의 문에서 return 문이 사용되면 함수를 호출 했을 때 결과값(data)를 반환함
예제) 재귀함수를 이용해 !(팩토리얼)를 구하는 프로그램
#include<stdio.h>
int num = 1;
void number(int a) {
num *= a;
if (a == 0) {
printf("1");
return;
}
if (a == 1) {
printf("%d", num);
return;
}
number(a - 1);
}
int main() {
int a;
printf("INPUT NUMBER: ");
scanf("%d", &a);
number(a);
}
- 조사 과제 + 실습
1. memset, strlen, strcmp, strcat, strcpy, strrev, strtok, strstr, atoi, itoa 함수 조사 및 실습
2 . 위 문자열 함수 중 리눅스 환경에서 실행되지 않는 함수 조사
<c언어 -5>
1) 포인터
▶ 변수의 주소 값, 메모리의 주소를 저장하는 변수
포인터 변수는 다른 변수를 가리키는 변수
포인터를 이용하여 메모리의 내용에 직접 접근할 수 있음.
▶ 포인터 자료형의 크기
32bit - 4바이트, 64bit - 8바이트

& : 변수의 주소를 반환
* : 포인터가 가리키는 (주소의) 메모리 참조
- 메모리 구조
변수는 메모리에 저장, 메모리는 바이트 단위로 액세스
#include<stdio.h>
int main() {
int data = 10;
int* ptr = NULL;
ptr = &data;
printf("data의 주소 : %p\n", &data);
printf("data의 주소 : %p\n", ptr);
printf("data의 값: %d\n", data);
printf("data의 값: %d\n", *ptr);
}

2) 배열과 포인터
- call by reference , call by value
▶ Call by reference (참조에 의한 호출)
함수에서 값을 전달하는 대신 주소값을 전달하는 방식
메모리에 대한 절감
▶ Call by value (값에 의한 호출)
함수에서 값을 복사해서 전달하는 방식
인자로 전달되는 변수를 함수의 매개변수에 복사함.
원본 값을 바꿀 필요가 없는 경우에 사용함.
- 다중 포인터
#include<stdio.h>
int main() {
int num = 17;
int* ptr = #
int** ptr2 = &ptr;
printf("before num: %d \n", num);
(*ptr)++;
printf("after num: %d \n", num);
(**ptr2)++;
printf("after2 num: %d \n", num);
}

※ 배열의 이름(변수명)은 배열의 시작 주소
▶ 포인터 배열 vs 배열 포인터
#include<stdio.h>
int main(){
int num = 10, num2 = 20, num3 = 30, num4 = 40;
int arr[2][4] = { 1,2,3,4,5,6,7,8 };
int i, j;
int* ptr[4] = (&num, &num2, &num3, &num4); //포인터 배열
int(*ptr2)[4] = arr; //배열 포인터
for (i = 0; i < 2; i++) //포인터배열
printf("%d", *ptr[i]);
puts("");
for (i = 0; i < 2; i++) { //배열 포인터
for (j = 0; j < 4; j++)
printf("%d", ptr2[i][j]);
puts("");
}
}
3) 문자열 함수
▶ 문자열을 다룰 때 사용되는 다양한 함수들
- 조사 과제
1. math.h에 대해 조사한 후, math.h에 포함된 라이브러리 함수 조사 및 실습
2. 32bit vs 64bit 차이 자세하게 조사
#include<stdio.h>
#define nnu(a) (a)*(a)
int main() {
int num = nnu(3 + 2);
printf("%d", num);
}
2) 헤더파일

전처리기를 통해 다른 파일을 해당 파일에 포함시킴
▶ 헤더파일 포함 방법
#include <헤더파일명> //표준 라이브러리의 헤더 파일을 포함할 때 사용
#include "헤더파일명" //현재 소스 파일을 기준으로 헤더 파일을 포함
<상대경로>
“header.h”: 현재 소스파일과 같은 경로에 있는 header.h 파일을 포함
“test/header.h”: 현재 소스파일 경로에서 test 디렉토리 아래의 header.h를 포함
“../header.h”: 현재 소스파일 경로의 상위(이전) 디렉토리에 있는 header.h를 포함
<절대경로>
“c:/header/lib/header.h”: c:/header/lib/header.h경로에 존재하는 header.h를 포함
▶ visual stuido 에서 헤더파일 생성 방법

- 조사 과제 + 실습
1. 상대 경로와 절대 경로 조사
2.[strcpy, strcat, strcmp, strstr, atoi] 함수를 포인터를 활용하여 직접 똑같이 구현하고, 헤더파일로 구현
(•인자로 들어오는 문자열의 길이와 상관 없이 함수를 실행할 수 있어야한다.
•string.h 헤더파일 사용 금지)
<c언어 -7>
1) 구조체
▶ 구조체 선언
구조체의 정의 & 선언 범위는 전역과 지역 모두 가능
struct 태그 {
자료형 멤버1 ;
자료형 멤버2 ;
}
#include<stdio.h>
struct Student {
char Name[100];
int age;
int birth;
};
int main() {
struct Student info = { "minyeong", 20, 30719 };
printf("Name : %s \n", info.Name);
printf("age : %d \n", info.age);
printf("birth : %d \n", info.birth);
info.age = 21;
printf("Age : %d \n", info.age);
}

- 배열과 같이 {}를 통해 초기화 가능
- 접근 연산자 . 을 이용해 구조체 멤버에 접근
▶ 구조체 안의 구조체 선언
#include<stdio.h>
struct date {
int year;
int month;
};
struct Student {
struct date Birthday;
char Name[100];
int age;
};
int main() {
struct Student info = { {2003, 7}, "minyeong", 20 };
}
▶ 자료형 재정의
- typedef (기존 자료형) (새로 정의할 이름)
typedef는 이미 사용되는 자료형을 다른 새로운 자료형 이름으로 재정의할 수 있도록 하는 키워드
- 일반적으로 프로그램의 시스템간 호환성과 편의성을 위해 사용함 (가독성 ↑, 단순화)
▶ 구조체 포인터
접근 연산자 -> 를 사용
ptr -> Name = (*ptr).Name //같은 의미임
2) 동적할당
▶ 정적(static) 메모리 할당 방법
프로그램이 실행되기 이전에 변수의 저장공간 크기가 정해짐
프로그램 또는 함수가 시작되면 메모리에 할당하는 방식 . (DATA, BSS 영역, STACK 영역 사용)
▶ 동적(dynamic) 메모리 할당 방법
프로그램 실행 중에 필요한 메모리를 할당하는 방법 (HEAP 영역을 사용)
- 메모리를 효율적으로 사용할 수 있음 (할당 – 해제)
- 배열 할당 크기를 유동적으로 사용 가능
- 배열 사용 시 스택 메모리 부족으로 인한 오류를 해결할 수 있음
<메모리 관련 함수> 헤더파일 : stdlib.h
메모리
|
함수원형
|
기능
|
메모리 할당
|
void * malloc(size_t)
|
인자만큼 메모리 할당 후 기본 주소 반환
|
메모리 할당
|
void * calloc(size_t, size_t)
|
뒤 인자만큼의 메모리 크기로 앞 인자 수만큼 할당 후 기본 주소 반환
|
기존 메모리 변경
|
void * realloc(void *, size_t)
|
앞 인자의 메모리를 뒤 인자 크기로 변경 후,
기본 주소 반환
|
메모리 해제
|
void free(void *)
|
인자를 기본 주소로 갖는 메모리 해제
|
int* ip;
ip = (int*)malloc(sizeof(int) * 5);
→ int는 4바이트이니 (4 * 5 = 20) 20byte만큼 할당해준 주소


※ arr안에 주소(주소배열)이 들어감
arr 는 int 이중 포인터
malloc 에서 height 만큼 할당, height의 크기를 가지는 int 포인터 배열을 가리킴
반복문 arr[i] = int 배열 주소를 가지고 있음

int **array = int 배열의 주소들이 저장된 포인터 배열임
이중 포인터 배열 → 포인터 배열 → 배열
#include<stdio.h>
#include<stdlib.h>
int main() {
int i, num;
char** str;
scanf("%d", &num);
str = (char**)malloc(num * sizeof(char*));
for (i = 0; i < num; i++)
str[i] = (char*)malloc(32 * sizeof(char));
for (i = 0; i < num; i++)
scanf("%s", str[i]);
for (i = 0; i < num; i++)
printf("%s\n", str[i]);
for (i = 0; i < num; i++) //할당 입력
free(str[i]);
free(str); //할당 해제
}
- 조사 과제
1. calloc, realloc 조사하고 실습
2. 공용체(union)에 대해 조사 & 간단한 실습
3. 열거형(enum)에 대해 조사
4. Socket의 개념(종류, 역할, 용도 등 자세히)과 Socket 통신(TCP 프로토콜 통신)의 과정 조사
+ 구조체를 이용한 친구 관리 프로그램 제작
조건: 동적할당 사용 (구조체, 이름, 상태메시지) – 구조체 포인터는 동적할당 사용하지 않아도 괜찮음
각 기능을 함수로 만들기 – 친구 추가, 친구 삭제, 검색, 전체 출력
동명이인 있는 경우 예외처리 (입력 받지 못하게 하거나 에러 메시지 출력)
친구는 100명을 넘지 않는다. 이름은 영문이다.
<c언어 -8>
1) 파일 입출력
▶ 텍스트 파일 (text file)
- 메모장과 같은 편집기로 작성된 파일 등 (.txt)
▶ 바이너리 파일 (binary file)
- 동영상, 사진 파일, 실행프로그램 등 (.exe)
- 스트림
입력과 출력에 대한 바이트들의 흐름


▶ 파일 입출력 스트림
스트림
|
설명
|
장치
|
stdin
|
표준 입력
|
키보드
|
stdout
|
표준 출력
|
화면
|
stderr
|
표준 에러
|
화면
|
stdprn
|
표준 프린터
|
프린터
|
stdaux
|
표준 보조
|
직렬포트
|

▶ 파일 open

fopen()에서 char* mode 의 종류
+ 가 붙은 모드의 경우 읽기, 쓰기가 가능 / 그렇지 않은 경우 해당 모드 전용으로만 오픈
▶ 데이터 입.출력 모드

default 가 t 이므로 텍스트 모드로 불러울 경우 데이터 입출력 모드 적지 않아도 됨
▶ 파일 접근 처리
- 파일을 처음으로 열면 모드에 관계없이 파일 위치는 모두 0이다.
- 파일을 읽거나 쓰면 자동으로 파일 위치가 마지막으로 이동된다.
fseek()

ftell() : 파일 포인터의 현재 위치를 반환
rewind() : 파일 포인터의 현재 위치를 시작점으로 이동

파일 입출력 과정
▶ open 과 fopen
open() :
저수준, 버퍼를 사용 X
리턴값은 int형의 파일 디스크립터
파일 디스크립터는 커널에서 갖고있는 파일에 대한 번호
파일이 open되면 순서대로 번호가 3번 부터 붙음
파일을 읽고 쓸 때, read(), write()를 쓸 수 밖에 없음
fopen() :
고수준, 버퍼를 사용
파일 스트림 정보
리턴값은 FILE * 형태의 파일 스트림 포인터
fopen도 내부적으로 open을 쓰고, 파일 스트림 구조체에 저장하는 과정이 한번 더 이루어짐
파일을 읽고 쓸때, fread,fopen,fseek등 다양한 함수를 쓸 수 있음
- 조사 과제
1. 파일 디스크립터와 파일 포인터 개념과 차이점
2. 네트워크 포트 개념
3. TCP vs UDP
4. 검색을 통해 소켓통신 예시코드 완성, 코드 분석
(주석 꼼꼼하게 달기)
클라이언트, 서버 통신 실행 캡쳐
+netstat명령어 조사 후 사용하여 소켓통신 확인
+ 친구관리 프로그램 추가 기능 제작
*기능은 파일 입출력을 사용하여 구현*
저장(백업) 기능 (자동저장 or 저장기능 구현-자유, 하나의 텍스트파일에 모든 친구 정보 저장)
불러오기 기능 (저장된 학생 전체 정보 불러오기 후 목록으로 확인 가능하고 개별 삭제도 가능해야 함)
'C' 카테고리의 다른 글
main 함수의 argc, argv (0) | 2023.02.05 |
---|---|
C 소켓 (0) | 2022.11.26 |