티스토리 뷰

190613(4일차) - 함수포인터, typedef, 전처리기 지시자, malloc 등
 
교육을 받으면서 노트필기 했던 내용을 날것 그대로 업로드합니다.

 
int *p 는 int *p[3](포인터배열) 도 가리킬 수 있다.
 
배열 포인터 int (*p)[3] : 인트형 3개짜리 배열을 가리킬 수 있는 포인터
 

 
함수 포인터.
 
함수도 각각 함숟마다 주소를 가지고 있다.
함수는 주소로 호출한다.
배열의 이름도 주소지만, 함수의 이름 자체도 주소다.
 
int add(int a,int b);
int (*p)(int,int);
p=add;
 
#ex
#include <stdio.h>
#pragma warning (disable:4996)
int add(int a, int b) {
return a + b;
}
void main() {
int(*p)(int, int) = add;
printf("%d \n", p(2, 4));
}
 
#함수 포인터 배열
#include <stdio.h>
#pragma warning (disable:4996)
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;
}
void main() {
int(*p[3])(int, int);
p[0] = add;
p[1] = sub;
p[2] = mul;
printf("%d \n", p[1](2, 4));
}
 
#왜 굳이 함수포인터를 쓸까? (-> 콜백함수)
#include <stdio.h>
#pragma warning (disable:4996)
 
void cold() { //client
puts("cold");
}
void hot() { //client
puts("hot");
}
 
void aircon(void(*p)(void)) { //server
p(); // call back
}
void main() { //client
aircon(cold); // call
aircon(hot); // call
}
 
#ex
#include <stdio.h>
#pragma warning (disable:4996)
 
int add(int a, int b) { return a + b; }
int temp(int a, int b, int(*p)(int, int)) {
return p(a, b);
}
 
void main() {
int a = 10, b = 5;
 
int result = temp(a, b, add);
printf("a와 b의 합 : %d", result);
}
 
 
# typedef로 간략화
#include <stdio.h>
#pragma warning (disable:4996)
 
int add(int a, int b) { return a + b; }
typedef int(*pp)(int, int);
main() {
pp p = add;
printf("%d", p(1, 3));
}
 
# 데이터 형의 메모리 크기
char < short < int < unsigned int < long < float < double
타입의 대소관계만 명시해 놨을 뿐. 실제 메모리크기를 지정하는 것은 컴파일러에게 맡겼다.
 
# short와 char형은 덧셈연산시 int로 격상되어 덧셈을 처리한다.
 
# 범용 포인터
main() {
char a[] = "sun";
void *p;
p = a;
printf("%c", *(char*)p);
}
 
# void 포인터 <-> 함수 포인터
#include <stdio.h>
#pragma warning (disable:4996)
 
int add(int a, int b) { return a + b; }
 
main() {
void* p;
p = add;
printf("%d", ((int(*)(int,int))p)(1,2));
 
}
 
#void 포인터 배열 이용한 계산기
#include <stdio.h>
#pragma warning (disable:4996)
 
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;
}
main() {
void* arr[5][2] = { {add,"ADDITION"},{sub,"SUBTRACTION"},{mul,"MULTIPLY"},{div,"DIVIDE"},{0,0} };
int num;
int a = 10, b = 5;
puts("/* 계산기 프로그램 */");
for (int i = 0; i < 4; ++i) {
printf("%d. %s\n",i+1, (char*)arr[i][1]);
}
printf("번호를 선택하세요 : ");
scanf("%d", &num);
 
printf("결과는 : %d\n", ((int(*)(int, int))arr[num - 1][0])(a, b));
}
/* 계산기 프로그램 */
1. ADDITION
2. SUBTRACTION
3. MULTIPLY
4. DIVIDE
번호를 선택하세요 : 3
결과는 : 50
 

@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
int(*p)[3] : int, [3], *, p // 배열 포인터
int* p[3] : int*, [3], p // 포인터 배열
int* p() : int*를 반환하는 함수 p
int (*p)() :함수 포인터
int*(*p)() :함수 포인터
int(*p[])():int형 함수 포인터 배열
 
func()[i] : 함수가 반환한 것의 [i] 번째 인데스
char* func(void){ // char* : char형 주소를 리턴
return "abcd"; // 1. 끝에 널문자. 2. 문자열은 주소다.
}
main(){
for(int i=0;i<2;++i){
printf("%d",func()[i]);
}
}
 
func[i]() : func함수 배열의 i번째 함수 호출.
 

 
#스토리지 클래스
  • extern : 전역변수에 붙어있던 것. 함수에서도. (사실 생략되어 표현됨)
    int a; // 임시정의
    extrern int c=100; // 정의
    extern int d; // 선언 (전역 변수가 밑에 있을때 미리 선언후 위에서 사용)
  • static :
  • auto : 지역 변수에는 사실 auto가 있었던 것. (전역에는 사용불가)
  • register : 지역 변수에만 사용가능. 빠른 변수로 사용하겠다는 것. (메모리가 부족하면 auto로 됨)
 
main() {
extern int i;
printf("%d", i); //30출력
}
int i = 30;
 
 
stack
heap
bss(zero베이스영역)
global(초기화시)(static)
code
 

 
# 전처리기 지시자
 
user.c
전처리기
user.i
컴파일
users.s
어셈블러
user.obj
링킹
user.exe
실행가능.
 
- #define ONE 1
- #define ADD(a,b) (a+b) // 매크로 함수
 
- #include <헤더파일명>
- #include "헤더파일명"
 
- #if FLAG == 1
- #endif
 
- #ifdef FALG
- #endif
 
- #if defined(FLAG)
정의 되어 있다면,
 
- #ifndef FLAG
정의 되어 있지 않다면,
 
- #pragma once
 
- 문자열화 연산자 #ABC -> "ABC
- 결합연산자 ## : O##K -> OK
 
#define STRING(x) #x
 
main() {
printf("%s", STRING(ABC));
}
 
 
#define square(x) (x*x)
#define PR(x) (printf("%d\n",x))
#define ABS(x) (x<0?-x:x)
#define THREE_MAX(a,b,c) (a>b&&a>c)?a:(b>a&&b>c?b:c)
#define SWAP(x,y) a^=b, b^=a, a^=b
 
main() {
printf("%d \n", 25 / square(5));
PR(25);
printf("%d \n", ABS((-25)));
printf("%d \n", THREE_MAX(4,3,2) );
int a = 1, b = 9;
SWAP(a, b);
printf("%d %d\n", a, b);
 
}
1
25
25
4
9 1
 
-매크로 스왑
#define SWAP(a,b) {int t; t=a; a=b; b=t;}
 
 
-메크로 스왑2
#define SWAP2(x,y) do{int t; t=x; x=y; y=t; }while(0)
 
//여러 줄로 이루어진 매크로는 do while로 감싸 처리하자.

 
 
#include <stdio.h>
#include <string.h>
#pragma warning (disable:4996)
 
 
void f0(void) { puts("f0"); }
void f1(void) { puts("f1"); }
void f2(void) { puts("f2"); }
void f3(void) { puts("f3"); }
void fi(void) { puts("fiiii");}
#define call(x) f##x
main() {
for (size_t i = 0; i < 4; i++)
{
call(i)(); // 매크로는 전처리기 시점에 변환이된다..
//하지만 for문은 컴파일 이후에 실행할 때동작하기 떄문에 오류!.
// fi() 함수로 사용..
}
}
fiiii
fiiii
fiiii
fiiii
 
 

- 실행시간에 원하는 크기의 메모리 할당
int b[size];
- C99 표준에서 채택
- 여전히 표준을 따르지 않는 컴파일러
 

 
stack = 1M
heap = 2G~4G
 
heap영역은 오로지 포인터로만 접근이 가능하다.
 

- malloc (메모리 할당) (메모리 얼로케이션)
원하는 크기만큼의 바이트를 할당
힙영역에 메모리 할당 메모리 주소는 void* 형태로 반환된다.
(내땅하고 쓰레기 내비러둬, 시간소요x)
- calloc
똑같은디 모든 비트를 0으로 초기화 시킨다.
(내땅하고 0으로 다 청소해, 시간소요) clear
- realloc
재 할당시 알아서 겹치지 않는 영역으로 할당해준다.
 
-free : 할당한 메모리를 수동으로 해제한다.
프로그램 종료시 자동으로 메모리는 해제된다.
 
main() {
char* p;
char buff[100];
 
gets(buff);
 
p = (char*)malloc(strlen(buff) * sizeof(char) +1 ); /// +1 추가
// malloc으로 입력받은 문자열 길이만큼 char형 크기만큼 할당한다.
strcpy(p, buff); //할당받은 영역p에 buff영역을 값복사해준다.
puts(p);
 
free(p); ///error! : NULL문자도 있기 때문에 +1을 추가해주어야한다.
}
+1을 하지 않을경우 NULL은 힙영역 할당을 받은게아닌데도 free로 해제하려하니 에러발생.!
 
 

"aaa bbb ccc" 입력시
 
-scanf : aaa까지만 받음
 
-gets : 끝까지 받고 엔터값은 '\0'로 치환
 
-fgets : 엔터(\n) 까비 받고 끝에 '\0'을 덧붙여줌.
 

 
-calloc
main() {
int *p;
p = (int*)calloc(4, sizeof(int));
}
int만큼 4개만듬 (0으로 채워서)
 

 
-tip
보통 포이터는 int 크기를 따라간다.
 

 
- 더블 포인터.
 

 
 
-ex
#include <stdio.h>
#include <string.h>
#include <malloc.h> // malloc 사용시 필요
#pragma warning (disable:4996)
 
main() {
printf("원하는 문장의 개수를 입력하세요 : ");
int n;
scanf("%d", &n);
getchar(); // 엔터 받기.
 
char** p = (char**)malloc(n * sizeof(char*)); // 문장 개수만큼 포인터 배열 생성
 
for (int i = 0; i < n; ++i) {
printf("%d번째 문장은 ? ",i+1);
char s[100];
gets(s); // 띄어 쓰기 까지 받기위해 gets사용.
char* ss = (char*)malloc(strlen(s) + 1); // 문장 길이 만큼 메모리할당
strcpy(ss, s); // 할당 메모리 공간에 입력문장 복사
p[i] = ss; // 할당 메모리 주소를 가리키게함.
}
 
for (int i = 0; i < n; ++i) {
printf("%d번쨰 문장 %s \n",i+1,p[i]);
}
}
 
 
댓글
최근에 올라온 글
최근에 달린 댓글
네이버 이웃추가
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함