사람 : C언어,JAVA,PHP 등 사용 가능
컴파일러 : C언어,JAVA,PHP or 기계어 사용가능
컴퓨터 : 기계어 사용 가능
🐣 C언어 : 컴파일러가 필요
🐣 컴파일러 : 프로그래밍 언어로 작성된 프로그램을 컴퓨터가 이해할 수 있도록 기계어로 번역해주는 번역기
🌈 컴파일러(Compiler): 소스 코드를 받아들여 그것을 한꺼번에 컴파일하여 기계어로 된 실행 파일을 생성
🌈 어셈블러(Assembler): 어셈블리어(기호로 표현된 어셈블리코드)로 작성된 소스 코드를 받아들여 기계어로 된 오브젝트 코드를
어셈블리 언어는 기계어와 일대일로 대응되는 저수준 언어이다
주로 시스템 프로그래밍이나 임베디드 시스템에서 사용된다
🌈 인터프리터(Interpreter): 소스 프로그램을 한번에 기계어로 변환시키는 컴파일러와는 달리 프로그램을 한 단계씩 기계어로 해석하여 실행하는 언어처리 시스템
🐣도입 부분
#include<stdio.h>
int add(int x,int y);
🐣메인함수 부분
void main(){
int i,j,sum;
printf("함수의 호출\n");
i=10,j=20;
sum=add(i,j);
printf("%d+%d=%d", i,j,sum);
}
🐣함수 부분
int add(int x,int y){
int tot;
tot=x+y;
return tot;
}
- C 프로그램은 반드시 🌀하나 이상의 함수를 포함해야 한다
- 🌀main()함수가 반드시 존재해야 한다.
- 함수의 시작과 끝을 알리는 중괄호를 사용해야 한다
- 중괄호 안에는 변수선언문,치환문,연산문,함수 등의 명령을 기입한다
- 🌀선행처리기를 제외하고 문장의 끝에는 세미콜론을 붙인다
정수형,실수형,문자형,문자열 상수가 있다
자료를 저장할 메모리를 확보하고 이 공간에 이름을 붙여준 것
🐣 변수 선언 : 확보된 메모리에 이름을 부여하는 것
변수선언에는 자료형이 필요하다
🌀주의할 점
한 줄에 하나의 명령만 쓴다
명령문 끝에는 세미콜론을 붙이지 않는다
반드시 #로 시작한다
소스 프로그램의 첫 부분에 위치한다
🐣 sizof() : 지정한 자료형, 수식, 변수가 차지하는 메모리의 크기(byte)를 구함
🐣 cast(형변환) : 지정한 자료형을 다른 자료형으로 강제적으로 바꿈
🐣 & : 주소 연산자로서 피 연산자의 주소를 나타냄
🐣 * : 내용 연산자로서 피 연산자의 내용을 가져옴
#include <stdio.h>
int main() {
int i = 0;
loop:
printf("%d\n", i);
i++;
if (i < 5)
goto loop;
return 0;
}
프로그램 수행 도중 원하는 곳으로 🌈무조건적으로 옮긴다
레이블이 위치한 곳이 다른 if,for 문의 중괄호 안이라면 들어갈 수 없다
실 매개변수와 형식 매개변수 사이에는 자료형과 변수의 개수가 일치해야 한다
& : 주소 연산자
* : 내용 연산자
function(&a,&b); // 함수호출(실 매개변수)
...
...
int function(int *x,int *y){} // 함수정의(형식 매개변수)
a와 b의 메모리의 주소가 x,y로 전달된다
형식 매개변수 x,y는 주소를 받아들일 수 있는 변수이다
*x : x가 주소를 가지고있고 그 주소에 대한 내용을 값으로 가진다
auto를 제외한 나머지는 생략이 불가능하다
기억클래스 자료형 변수명;
int array[4] = {10,20,30,40}; // 배열 각 요소에 초기값 할당
int array[] = {10,20,30,40}; // 배열의 크기 생략 가능
int array[4] = {10,20,30,}; // array[3] = 0 으로 초기화
// 에러 발생
int array[4] = {10,,30,40};
int array[4] = {10,20,30,40,50}; //초기값이 많음
//문자열 단위로 초기화
char name[] = "hong tea hwa";
// 문자 단위로 초기화
// 이경우에는 null문자(\0)를 삽입해야 함
char address[] = {'S','E','O','U','L','\0'};
널 문자를 붙이지 않으면 내가 원하지 않는 쓰레기값이 붙을 수 있음
변수 선언에 의해 메모리가 할당되고
할당된 기억공간에 변수에 대입된 데이터가 저장된다
이때 할당된 메모리는 주소가 부여된다
기억공간을 변수명으로 접근하지 않고 주소로 접근하기 위해 사용한다
int day = 365;
&day를 출력하면 62fe1c 로 나온다 // 매번 변경됨
p : 포인터 변수로서 정수형 자료가 수록되어 있는 주소를 갖고 있다
*p : 해당 주소에 수록되어 있는 정수형 값(주소에 들어있는 내용)을 갖고 있다
int a, b; 정수형 변수 a와 b를 선언
int *p; 정수형 포인터 변수 p를 선언
a = 5000; 변수 a에 5000이라는 값을 할당
p = &a; 포인터 변수 p에 변수 a의 주소를 할당
& 연산자는 변수의 주소를 반환한다
b = *p; 포인터 p가 가리키는 메모리 주소에 있는 값을 변수 b에 할당한다
* 연산자는 포인터가 가리키는 값을 역참조한다
결과는 a, b, *p 모두 5000이 된다
포인터 변수에 +,-,++,-- 연산자를 사용하는 연산
🌈 만약 포인터 변수 2개가 있다면 두 포인터간의 + 연산은 할 수 없다
int main() {
int arr[] = {10, 20, 30, 40, 50};
int *ptr = arr; // 배열의 첫 번째 요소를 가리키는 포인터
printf("첫 번째 요소: %d\n", *ptr); // 10 출력
// 포인터에 산술 연산 수행
ptr++; // 다음 요소를 가리킴
printf("다음 요소: %d\n", *ptr); // 20 출력
ptr += 2; // 두 번째 다음 요소를 가리킴
printf("두 번째 다음 요소: %d\n", *ptr); // 40 출력
ptr--; // 이전 요소로 이동
printf("이전 요소: %d\n", *ptr); // 30 출력
return 0;
}
🌀 *ptr+2 와 ptr+2 는 다르다!!!
char *cp = "COMPUTER";
에서 cp는 문자열의 시작주소를 갖는다
*cp // C
*(cp+1) // O
*(cp+2) // M
*(cp+3) // P
*(cp+4) // U
*(cp+5) // T
*(cp+6) // E
*(cp+7) // R
*(cp+8) // \0
값을 참조할 때와는 달리 포인터변수 cp에 주소를 치환하지 않는다
char s[] = "SCIENCE";
char *cp;
cp = s; //포인터 cp를 이용하여 배열 s의 내용을 참조
- 배열명은 그 배열로 확보된 메모리의 시작주소를 가르킨다
- 배열 s도 주소를 가르키고 있기 때문에 포인터의 개념이다라고 할 수 있다
- 🌈 *cp 를 프린트하면 S가 나온다
- 🌈 *(cp+1)을 프린트하면 C가 나온다
🌀즉 배열은 포인터의 일부분이다
🌀모든 배열은 포인터로 표현이 가능하다
cp+1 은 &s[1] 과 같고
*(cp+1) 은 s[1] 과 같다
포인터의 집합 // 주로 문자열 배열 처리에 사용
char *name1, *name2, *name3
을
char *name[3];
로 표현한다
char *PA[4];
PA[0] = "ELECTRONICS";
PA[1] = "DATA";
PA[2] = "PROCESSING";
PA[3] = "SYSTEM";
포인터 배열은 2차원 배열과 동일하다
2차원 배열에 비해 기억공간 절약효과가 있다
포인터 배열은 자료의 크기만큼 기억공간을 할당하기 때문이다
만약 2차원 배열로 만든다면 A[4][12]로 만들어야 한다
(가장 큰 문자열을 가지는 A[0]의 크기로 고정적으로 만들어야 하기 때문)
2차원 배열로는 총 48개의 기억공간이 필요하다
포인터 배열로는 총 35개의 기억공간이 필요하다
int **p;
p : 기억공간 주소
*p : 주소 p의 값 [ p 의 주소가 값으로 들어가 있다 ]
**p : 주소 p의 값 [ *p의 주소가 값으로 들어가있다 ]
서로 다른 자료형을 갖는 자료들의 모임을 하나의 자료형으로 정의하여 사용하는 자료형
형식 : struct 구조체명 변수명1,변수명2,변수명3;
사용 예 1
struct person{ // 구조체 정의
char name[8]; // 구조체 멤버
int age;
};
struct person X,Y;
struct person{
char name[8];
int age;
}X,Y; // 바로 변수 선언
typedef struct person{
char name[8];
int age;
}taehwa;
// sturct person를 taehwa 라는 새로운 자료형으로 정의
taehwa X,Y;
struct person{
char name[8];
int age;
};
struct person X = {"홍태화",10};
X.name // 홍태화
X.age // 10
🌈 실제 메모리가 할당될 때는 구조체 멤버 중 가장 큰 자료형의 크기로 할당됨
struct person{
char name[8];
int age;
};
struct person X[3];
X[0].name
X[0].age
X[1].name
X[1].age
X[2].name
X[2].age
struct person{
char name[8];
int age;
};
struct person man;
struct person *p;
p = &man;
p에는 구조체 man의 시작주소를 가지고 있다
// 주소를 전달해야 하기 때문에
// 실매개변수에 &를 붙여준다
호출함수(&실매개변수);
// 주소를 전달받아야 하기 때문에
// 형식매개변수에 *를 붙여준다
피호출함수(*형식매개변수){
}
이미 존재하는 자료형에 새로운 이름을 붙이기 위한 키워드
// 언사인드 인트형을 바이트라는 새로운 이름으로 정의
typedef unsigned int BYTE;
// 컴파일러가 unsigned int val 으로 해석
BYTE val;
// int * 를 PTR 으로 재정의
typedef int * PTR;
// 컴파일러 입장에서는 int *p1,*p2 로 해석
PTR p1,p2;
// 공용체 정의
union var{
//공용체 멤버
char a; // 1byte 사용
int b; // 4byte 사용
double c; // 8byte 사용
};
// 공용체 변수의 선언
union var abc;
abc.a = 'A'; // 1바이트만 사용
abc.b = 133; // 4바이트만 사용
abc.c = 1234.5678; // 8바이트만 사용
공용체가 사용되면
🌈 파일을 입출력 할 때 버퍼(buffer) 사용
데이터를 직접 디스크에 쓰고 읽는 대신
일시적으로 메모리 영역에 데이터를 저장하고 있다가
일정량이 모이면 한 번에 디스크에 쓰거나 디스크에서 읽어오는 것을 의미한다
이러한 방식은 입출력 작업의 효율성을 높여준다
#include <stdio.h>
void main(){
// 파일 포인터 선언
FILE *fp;
// 파일 열기 fopen 함수에 의해 실제 파일과 연결됨
fp = fopen("sample.txt" , "w" );
// 파일 닫기
fclose(fp);
}
t
프로그램에서 파일로 자료를 입출력 할 때 변환이 일어나는 입출력 모드
문자 변환이 필요b
변환이 일어나지 않는 입출력 모드
문자 변환이 불필요🐣 fclose() 함수의 사용
- 형식 : fclose(파일포인터 변수)
순차 파일
파일의 처음부터 자료를 차례로 읽고, 기록하는 파일
레코드의 길이가 일정하지 않은 파일
랜덤 파일
파일의 임의의 위치에서 자료를 읽고, 기록하는 파일
레코드의 길이가 일정한 파일
메모리 정적 할당
메모리 동적 할당
데이터 영역
전역변수와 static 변수가 저장되는 영역
프로그램이 시작함과 동시에 할당되고 프로그램이 종료되면 소멸
힙 영역
프로그래머의 필요에 의해 할당/소멸이 이루어지는 영역
실행이 되면서 크기가 늘어나고 줄어들어 자유 기억공간이라 불린다
메모리 동적 할당에 사용되는 영역
스택 영역
지역변수와 매개변수가 저장되는 영역
함수 호출이 완료되면 사라지게 된다
malloc()
- 형식 : void malloc(siz_t number_of_bytes)
- 기능 : number_of_bytes 에서 주어지는 크기만큼 메모리를 동적 할당
- 사용 예 : void malloc(sizeof(int));
인자로 할당 받고자 하는 메모리의 크기를 byte 단위로 전달
힙 영역에 그 크기만큼 메모리를 할당하고
할당한 메모리의 첫 번째 주소를 반환void * 로 명시하여 어떤 형으로든 형 변환이 가능
초기화 안됨(메모리의 초기화를 위해서는 memset() 사용 )
free()
- 형식 : void free(void *p);
- 기능 : 동적으로 할당된 메모리를 해제할 때 사용
힙 영역에 할당된 공간은 프로그램이 종료될 때 까지 유지
할당된 메모리를 해제하지 않으면 메모리 부족 현상 발생
명시적인 반납이 필요하다
calloc()
- 형식 : void calloc(int n, int size);
- 기능 : 주어진 size의 크기를 가지는 메모리 n개를 할당받음
- 사용 예 : void calloc(n, sizeof(int))
malloc() 함수와 동일하게 힙 영역에 메모리 할당
다른점은 사용하는 형태와 할당된 메모리를 0으로 초기화
realloc()
- 형식 : void realloc(void p, int size);
- 기능 : 포인터 p가 가리키고 있는 메모리의 크기를 지정된 사이즈로 변경
이미 할당 받은 메모리 크기를 변경해야 할 때 사용
memcmp() 함수
메모리에 들어있는 자료를 주어지는 크기만큼 비교하여
같은지 여부를 알 수 있게 해주는 함수
memcpy() 함수
메모리의 자료를 다른 메모리 영역으로 복사하기 위한 함수
memset() 함수
메모리의 자료를 지정한 문자로 채우는 함수
할당된 메모리의 초기화나 내용 삭제를 위해서 주로 사용
출처 : 방송통신대학교