5월 26일용 - dlekdbs0710/rlakf1wnck GitHub Wiki

코드 1

#include <stdio.h>
#include <stdlib.h>

int main()
{
  int* pa = NULL; //pa는 int형 데이터를 가리키는 포인터
  double* pb = NULL; //pb는 double형 데이터를 가리키는 포인터

  pa = (int*)malloc(sizeof(int)); //malloc():지정된 바이트 수만큼 힙 메모리를 할당
  pb = (double*)malloc(sizeof(double)); //반환값: void*

  *pa = 10; //pa가 가리키는 메모리 주소에 10 저장
  *pb = 3.14; //pb가 가리키는 메모리 주소에 3.14 저장
  printf("int : %d\n", *pa); // %d:정수 출력
  printf("double : %g\n", *pb); //%g: 실수 출력(소수점 자릿수, 지수 표기 자동 조절)

  free(pa); // 메모리 해제-> 메모리 누적 방지를 위해서 해야함
  free(pb);
}

설명

  • malloc()은 지정된 바이트 수만큼 힙 메모리를 할당함
  • free(): 메모리 해제, 메모리의 누적을 방지하기 위해서 해야함

결과

int : 10 
double : 3.14

코드 2

#include <stdio.h>
#include <stdlib.h>

int main()
{
  int* pa = NULL; // 정수형 메모리를 가리킬 포인터
  double* pb = NULL;// 실수형 메모리를 가리킬 포인터
  // CRUD(Create, Read, Update, Delete)

// 동적 메모리 할당(create)

  pa = (int*)malloc(sizeof(int)); //4바이트 정수형 메모리 확보 
  pb = (double*)malloc(sizeof(double));// 8바이트 실수형 메모리 확보

// 값 저장 및 출력(Update & Read)

  *pa = 10; //할당된 정수형 메모리 공간에 10 저장
  *pb = 3.14; // 실수형 메모리 공간에 3.14 저장
  printf("int : %d\n", *pa); // 결과: int: 10 
  printf("double : %g\n", *pb); // 결과: double: 3.14

  free(pa);
  free(pb); //메모리 해제=> pa=NULL; pb=NULL;로 초기화도 가능, 결론: pa, pb가 가리키는 메모리만 해제, 포인터 변수 자체는 남음  
}

⭐코드 3

#include <stdio.h>
#include <stdlib.h>

// 메모리 할당 함수들(Create)
int* AllocInt()
{
  return  (int*)malloc(sizeof(int)); => int와 double 하나를 저장할  있는 크기의  메모리를 할당하고 포인터 반환 , malloc()실패시, NULL 반환됨->사용시 주의 필요
}
double* AllocDouble()
{
  return (double*)malloc(sizeof(double));
}

// 값 설정 함수들(Update)==> 전달받은 포인터(p)가 가리키는 위치에 값 저장 
void SetInt(int* p, int data)
{
  *p = data; // 해당 메모리 공간에 값을 대입
}
void SetDouble(double* p, double data)
{
  *p = data;
}

// 값 출력 함수들(Read)==> 값만 받아서 출력(포인터가 아닌 복사된 값을 받음) 
void PrintInt(int data)
{
  printf("int : %d\n", data);
}
void PrintDouble(double data)
{
  printf("double : %g\n", data);
}

// 메모리 해제 함수들(Delete)==>free()을 통해 메모리 해제, 이후에 해당 포인터 다시 사용시, '정의되지 않은 동작'이라고 뜸
void FreeInt(int* p)
{
  free(p);
}
void FreeDouble(double* p)
{
  free(p);
}
int main() //main 함수 동작의 흐름
{
  int* pa = NULL;
  double* pb = NULL;

  pa = AllocInt(); //int* 메모리 할당
  pb = AllocDouble();//double* 메모리 할당

  SetInt(pa, 10);//SetInt(&*pa, 10); // 할당된 메모리에 10 저장
  SetDouble(pb, 3.14); //3.14 저장

  PrintInt(*pa); //10 출력 
  PrintDouble(*pb); //3.14 출력

  FreeInt(pa); //메모리 해제 
  FreeDouble(pb);
}

결과

int : 10 
double: 3.14

코드 4

#include <stdio.h>
#include <stdlib.h>

//
int* AllocInt()
{
  return  (int*)malloc(sizeof(int));
}
double* AllocDouble()
{
  return (double*)malloc(sizeof(double));
}
void SetInt(int* p, int data)
{
  *p = data;
}
void SetDouble(double* p, double data)
{
  *p = data;
}
void PrintInt(int data)
{
  printf("int : %d\n", data);
}
void PrintDouble(double data)
{
  printf("double : %g\n", data);
}
void FreeInt(int* p)
{
  free(p);
}
void FreeDouble(double* p)
{
  free(p);
}
int main()
{
  int* pa = NULL;
  double* pb = NULL;

  pa = AllocInt();
  pb = AllocDouble();

  SetInt(pa, 10);//SetInt(&*pa, 10);
  SetDouble(pb, 3.14);

  PrintInt(*pa); 
  PrintDouble(*pb);

  FreeInt(pa);
  FreeDouble(pb);
}

설명

  • 전체 구조 개요
  • C: 동적 메모리 할당(Create)
  • R: 값을 읽어 출력(Read)
  • U: 메모리 값 저장(Update)
  • D: 메모리 해제(Delete)

코드 5

#include <stdio.h>
#include <stdlib.h>

int main()
{
  int* pa = (int*)malloc(sizeof(int) * 10); //int형 크기만큼 10개의 메모리 할당, 4X10(int가 4바이트인 경우=> 40바이트), pa = 이 메모리의 블록의 시작 주소를 가리킴

  for (int i = 0; i < 10; ++i) // 결과적으로 pa[0]~pa[9]: 값 1~10이 됨
    pa[i] = i + 1; // pa[i]=*(pa + i)와 동일

  for (int i = 0; i < 10; ++i) // 배열에 저장된 값을 한 줄씩 출력
    printf("data : %d\n", pa[i]);

  free(pa); // 동적으로 할당된 메모리 해제
}

결과

data : 1
data : 2
data : 3
data : 4
data : 5
data : 6
data : 7
data : 8
data : 9
data : 10

코드 6

#include <stdio.h>
#include <stdlib.h>
void AllocIntArray(int** pp, int capacity) //이중 포인터(int **pp)를 사용-> 함수 외부의 포인터 변수에 해당
{
  *pp = (int*)malloc(sizeof(int) * capacity); // main()안에서는 AllocIntArray(&pa, 10);형태로 호출
}
void InitIntArray(int* pa, int size) // 동적 배열이나 일반 배열을 초기화할 수 있음
{                                   // int size는 배열의 크기(원소 개수)
  for (int i = 0; i < size; ++i)
    pa[i] = i + 1;
}
void PrintIntArray(int* pa, int size) //전달받은 정수 배열을 순서대로 출력
{
  for (int i = 0; i < size; ++i)
    printf("data : %d\n", pa[i]);
}
void FreeIntArray(int* pa)
{
 free(pa);
}
int main()
{
  int* pa = 0;
  
  AllocIntArray(&pa, 10);
  InitIntArray(pa, 10);
  PrintIntArray(pa, 10);
  FreeIntArray(pa);
}

#include <stdio.h>
#include <stdlib.h>
int* AllocIntArray(int capacity)  // 반환값으로 포인터 전달
{
  return (int*)malloc(sizeof(int) * capacity);
}
void InitIntArray(int* pa, int size)
{
  for (int i = 0; i < size; ++i) //main에서는 int* pa=AllocIntArray(10);처럼 간단히 사용 
    pa[i] = i + 1;
}
void PrintIntArray(int* pa, int size)
{
  for (int i = 0; i < size; ++i)
    printf("data : %d\n", pa[i]);
}
void FreeIntArray(int* pa) 
{
  free(pa);
}
int main()
{
  int* pa = AllocIntArray(10); 
  InitIntArray(pa, 10);
  PrintIntArray(pa, 10);
  FreeIntArray(pa);
}

코드 7

#include <stdio.h>
#include <stdlib.h> //이 코드는 굳이 필요X

int main()
{
  int a = 10;
  int b = 20;
  int* p = NULL;

  //p = &a; //활성화하면 출력값은 10
  p = &b; // 포인터 p가 b를 가리키므로 p는 20

  printf("data : %d\n", *p);
}

결과

data : 20

코드 8

#include <stdio.h>
#include <stdlib.h>
void AssignAddress(int** pp,int* pdata)
{
  *pp = pdata; //pp는 int*의 주소(즉, int**), pdata: 어떤 정수형 변수의 주소(int*)
}             // pp가 가리키는 포인터에 pdata를 넣음->즉 , 포인터 변수 자체를 바꿔줌
int main()
{
  int a = 10;
  int b = 20;
  int* p = NULL;

  //p = &a;
  //p = &b;
  AssignAddress(&p, &b); //p가 b의 주소를 가리키게 변경됨-> *p는 b의 값인 20을 출력

  printf("data : %d\n", *p);
}

결과

data : 20

코드 9

#include <stdio.h>
#include <stdlib.h>
typedef int I; //I는 int와 완전히 동일한 타입
typedef int* PI; //PI는 int*와 동일한 타입[PI p; = int* p;]

void AssignAddress(PI* pp, I* pdata)
{
  *pp = pdata; //pp는 p를 가리키는 포인터(즉 &p), p=pdata;와 같음=> 즉, p가 이제 pdata가 가리키는 주소(b의 주소)임
}
int main()
{
  I a = 10; //int a=10;
  I b = 20; // int b =20;
  PI p = NULL;// int* p = NULL;

  //p = &a;
  //p = &b;
  AssignAddress(&p, &b);// int** 전달, int* 전달==> p=&b가 

  printf("data : %d\n", *p);//b를 가리키게 되었으므로 *p==20
}

결과

data : 20

설명

  • pp는 &p(p의 주소 )
  • *pp는 p 자신
  • pdata는 &b(b의 주소)

코드 10

#include <stdio.h>
struct Point //struct는 사용자 정의 자료형을 만든다는 뜻임, Point- x,y의 좌표를 저장하는 구조체 타입
{
  int x; //구조체에 두 개의 멤버 변수 x, y 가 있다는 뜻임
  int y;
};
int main()
{
  int n = 10; //일반 정수 변수 선언 
  Point pt = { 2,3 }; //구조체 변수 pt 선언 및 초기화 

  printf("%d\n", n);
  printf("(%d, %d)\n", pt.x, pt.y); //pt 구조체의 x, y 멤버 출력(2,3)
}

결과

10
(2, 3)

코드 11

#include <stdio.h>
struct Point // Point는 int  두개(x, y)를 멤버로 갖는 구조체 
{
  int x; // 메모리상에서 x와 y는 연속된 메모리에 저장됨
  int y;
};
int main()
{
  Point pt = { 2,3 };
  printf("(%d, %d)\n", pt.x, pt.y);

  printf("%p %p\n", &pt, &pt+1); //&pt는 구조체 변수 pt의 시작 주소 , &pt+1: 구조체 크기만큼 그 다음 구조체의 주소 
  printf("%p %p\n", &pt.x, &pt.x+1); //&pt.x: pt의 첫 번째 멤버 x의 주소, &pt.x+1: pt.y의 주소와 같음 

  Point* p1 = &pt; // p1은 구조체 전체를 가리킴(Point*)
  int* p2 = &pt.x; //p2는 정수 x를 가리킴(int*)-> 연속해서 y도 접근 가능 
}

코드 12

#include <stdio.h>
struct Point
{
  int x;
  int y;
};
int main()
{
  Point pt = { 2,3 };//구조체 변수 pt 선언 및 초기화 (x, y)
  Point* p = &pt;// 구조체 변수 pt의 주소를 포인터 p에 저장
  printf("(%d, %d)\n", pt.x, pt.y);//pt를 통해 접근 
  printf("(%d, %d)\n", p->x, p->y);// 포인터 p를 통해 pt의 멤버에 접근
} //📌 ->연산자는 구조체 포인터가 구조체의 멤버에 접근할 때 사용(간접 참조)

결과

(2,3)
(2,3)

코드 13

#include <stdio.h>
struct Point //구조체의 정의(Point는 두 개 int 멤버 x, y)
{
  int x; //메모리 상에서는 연속된 8바이트로 저장됨(int가 4바이트 기준)
  int y;
};
int main()
{
  Point pt = { 2,3 }; //pt는 구조체 변수, x=2, y=3
  Point* p = &pt;  //p는 pt를 가리키는 구조체 포인터
  printf("(%d, %d)\n", pt.x, (&pt)->y); 
  printf("(%d, %d)\n", (*p).x, p->y); //(*p).x → p가 가리키는 구조체의 x값 → 2
                                     //p->y → p가 가리키는 구조체의 y값 → 3
}

##결과

(2,3)
(2,3)

코드 14

#include <stdio.h>
// 구조체의 정의 
struct Point
{
  int x;
  int y;
};
//구조체를 매개변수로 받는 함수 
void PrintPoint(Point pt)
{
  printf("(%d, %d)\n", pt.x, pt.y);
}
int main()
{
  Point pt = { 2,3 };

  PrintPoint(pt); //구조체를 함수에 전달(구조체 전체를 복사)
} 

코드 15

#include <stdio.h>
//구조체의 함수 전달 방식(Call by Value)-값 전달
struct Point
{
  int x;
  int y; //int가 4바이트라면 Point 구조체는 총 8바이트, 구조체 변수는 두 개의 정수값을 연속된 메모리에 저장
};
// 함수 내부 
void PrintPoint(Point pt)
{
  printf("(%d, %d)\n", pt.x, pt.y); //단순히 구조체의 멤버 x, y를 출력
}
int main()
{ 
// 선언
  Point pt = { 2,3 };
  Point pt2 = { -1, 3 };
// 함수 호출 
  PrintPoint(pt);
  PrintPoint(pt2);
}

결과

(2, 3)
(-1, 3)

코드 16

#include <stdio.h>
struct Point
{
  int x;
  int y;
};
// 함수 정의 - 구조체의 주소를 받아서 멤버에 접근
void PrintPoint(Point* p) //Point* p는 구조체 Point의 포인터 
{
  printf("(%d, %d)\n", p->x, p->y); //-> 연산자 활용
}
int main() // 두 개의 구조체 변수 pt, pt2 선언, 초기화
{
  Point pt = { 2,3 };
  Point pt2 = { -1, 3 };

  PrintPoint(&pt); //&pt, &pt2: 각각의 구조체 변수의 주소값
  PrintPoint(&pt2);
}
⚠️ **GitHub.com Fallback** ⚠️