728x90
반응형
메모리 주소
16진수(Hexadecimal)
컴퓨터과학에서는 10진수, 2진수 대신 16진수(Hexadecimal)로 표현하는 경우가 많다.
- 0 ~ 9 / A ~ F : 총 16개로 16진수를 표현 가능(F = 15)
- 16진수임을 알리기 위해 문자 앞에
0x
를 붙혀서 표현
메모리 주소
- n은 int 타입이기 때문에, 컴퓨터 메모리 4 byte만큼의 자리를 차지하며 저장됨
- 변수의 메모리상 주소를 받기 위해
&
라는 주소 연산자와%p
라는 형식 지정자를 사용
Pointer(p
, 포인터) : 컴퓨터 메모리의 주소 - 메모리 주소에 있는 실제 값을 얻으려면
*
라는 참조 연산자를 사용
#include <stdio.h>
int main(void)
{
int n = 50;
// 메모리 주소를 출력
printf("%p\n", &n);
// 메모리 주소에 있는 실제 값 출력
printf("%i\n", *&n);
}
/*
결과
0x16f1bb12c
50
*/
포인터
Pointer(p
, 포인터) : 컴퓨터 메모리의 주소(❗️첫 글자의 주소)
- 말 그대로 해당 주소를 가리키고 있다고 생각
- 주소값을 넣는 데이터 자료형
- 32bit 시스템에서 포인터의 크기는 4 byte(32 bit)
- 64bit 시스템에서는 포인터의 크기가 8 byte(64 bit)
*
을 통해서 포인터 역할을 하는 변수를 선언 가능
#include <stdio.h>
int main(void)
{
int n = 50;
// 포인터 역할 변수 선언 (*p)
int p = &n;
printf("%p\n", *p);
// 포인터 내부 값 접근
printf("%i\n", *p);
}
문자열 / 비교 / 복사
문자열
문자열(string)은 문자(char) 여러 개가 이어진 상태
문자는 1 byte 크기의 char에 저장 가능하지만,
문자열은 1 byte를 넘어서므로 저장 불가 → 변수에 저장하지 않고 포인터를 이용해서 주소만 저장
#include <stdio.h>
int main(void)
{
// *s 포인터 변수에 **"E"의 주소값을 저장(문자열의 첫 글자의 주소값)**
char *s = "EMMA";
// 주소값을 출력
printf("%s\n", s);
// 포인터 변수를 참조하여 각각의 값 출력**(주소값에 1을 더해서 다음 문자 출력)**
printf("%c\n", *s); // E
printf("%c\n", *(s + 1)); // M
printf("%c\n", *(s + 2)); // M
printf("%c\n", *(s + 3)); // A
// 포인터 변수를 참조하여 각각의 주소값 출력
printf("%p\n", &s[0]);
printf("%p\n", &s[1]);
printf("%p\n", &s[2]);
printf("%p\n", &s[3]);
}
문자열 비교
- 아래와 같이 진행하면 주소값을 비교하기 때문에
False
반환 - 값이 같은지 확인하기 위해서는 해당 주소값의 문자에 하나씩 접근하여 비교
#include <cs50.h>
#include <stdio.h>
int main()
{
// s와 t에는 주소값이 저장됨
string s = get_string("s: ");
string t = get_string("t: ");
// s와 t의 주소를 비교하기 때문에 항상 False
if (s == t)
{
printf("Same\n");
}
else
{
printf("Different\n");
}
}
문자열 복사
- 예시 1에서는 t에 s의 주소값을 넣어 둘의 주소값이 같아져, t를 대문자로 수정하면 s에도 내용이 반영된 것이다.
malloc()
: 메모리 할당 함수strcpy(A, B)
: 문자열 복사 함수(A에 B문자열을 복사)
예시 1(주소값 복사)
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
int main(void)
{
string s = get_string("s: ");
// t에 s의 주소값을 대입
string t = s;
t[0] = toupper(t[0]);
// 둘의 결과는 동일
printf("s: %s\n", s);
printf("t: %s\n", t);
}
예시 2(메모리 할당 후 문자열 복사)
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char *s = get_string("s: ");
// malloc : 메모리 할당 함수
// strlen(s) + 1인 이유는? NULL 종단 문자 포함하기 위해
char *t = malloc(strlen(s) + 1);
/* strcoy() 함수로 간단히 표현 가능
for (int i = 0, n = strlen(s); i < n + 1; i++)
{
t[i] = s[i];
} */
strcpy(t, s);
t[0] = toupper(t[0]);
printf("s: %s\n", s);
printf("t: %s\n", t);
}
메모리 할당과 해제
Malloc (Dynamic Memory Allocation, 메모리 동적할당)
사용자가 직접 힙 영역에 메모리를 할당할 수 있게 함
- 첫 번째 바이트의 주소값을 반환함
valgrind ./파일명
을 통해 메모리와 관련된 문제가 있는지 확인- 메모리 누수가 발생하지 않게 하기 위해서 메모리 할당 후 해제 필요
free(변수)
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
char *s = get_string("s: ");
char *t = malloc(strlen(s) + 1);
strcpy(t, s);
t[0] = toupper(t[0]);
printf("s: %s\n", s);
printf("t: %s\n", t);
// 메모리 해제
**free(t)**
}
#include <stdlib.h>
void f(void)
{
// sizeof(자료형) : 자료형의 바이트 크기를 반환(int:4바이트)
int *x = malloc(10 * sizeof(int));
/* 인덱스 10은 없기 때문에 버퍼 오버플로우 발생
x[10] = 0;
*/
x[9] = 0;
// 메모리 해제하여 메모리 누수 차단
free(x);
int main(void)
{
f();
return 0;
}
메모리 교환, 스택, 힙
메모리 교환
예제1(x, y값 서로 교환하기)
- a, b는 x, y의 복사본이기 때문에 x, y를 직접적으로 변경할 수는 없음
(a, b의 메모리 주소와 x, y의 메모리 주소가 다름)
#include <stdio.h>
void swap(int a, int b);
int main(void)
{
int x = 1;
int y = 2;
printf("x is %i, y is %i\n", x, y);
swap(x, y);
printf("x is %i, y is %i\n", x, y);
}
void swap(int a, int b)
{
int tmp = a;
a = b;
b = tmp;
}
수정코드(메모리 주소값으로 접근)
#include <stdio.h>
void swap(int *a, int *b);
int main(void)
{
int x = 1;
int y = 2;
printf("x is %i, y is %i\n", x, y);
swap(&x, &y);
printf("x is %i, y is %i\n", x, y);
}
**// a와 b를 x, y를 가르키는 포인터로 지정**
void swap(int *a, int *b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
Heap Memory(힙 메모리)
- 프로그램에서 동적으로 할당된 메모리를 관리하는데 사용되는 영역
- 데이터 크기를 미리 예측하기 어려울 때 유용
- 일반적으로
malloc()
,calloc()
,realloc()
과 같은 함수를 사용해 할당 - 제한된 메모리 용량 아래서 기존의 값을 침범하는
Heap Overflow
발생할 수 있음
Stack(스택)
- 함수의 호출과 관계되는 지역변수와 매개변수가 저장되는 영역
- 함수의 호출과 함께 할당되며, 호출이 완료되면 소멸
- 저장된 함수의 호출 정보를 스택 프레임(Stack Frame)이라고 한다.
- 후입선출(LIFO, Last-In First-Out) 방식으로 동작하므로, 늦게 저장된 데이터가 가장 먼저 인출
- 제한된 메모리 용량 아래서 기존의 값을 침범하는
Stack Overflow
발생할 수 있음
머신 코드(Machine Code) 영역
: 프로그램이 실행될 때 프로그램이 컴파일된 바이너리 파일 저장됨글로벌(Globals) 영역
: 프로그램 안에서 저장된 전역 변수가 저장됨힙(Heap) 영역
: malloc에 의해 동적으로 할당된 메모리 데이터가 저장됨스택(Stack) 영역
: 프로그램 내의 함수 호출시 생성되는 변수나 지역변수들이 저장됨
파일 쓰기
입력 받기
int 타입
#include <stdio.h>
int main(void)
{
int x;
printf("x: ");
// &x : x의 주소를 입력
scanf("%i", &x);
printf("x: %i\n", x);
}
char *(string) 타입
#include <stdio.h>
int main(void)
{
// 메모리 크기 할당
char s[5];
printf("s: ");
// s의 첫 바이트 주소를 찾음
scanf("%s", s);
printf("s: %s\n", s);
}
파일 쓰기
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
// fopen(파일명,작업유형)
// 작업 유형 : r(읽기), w(쓰기), a(덧붙이기)
FILE *file = fopen("phonebook.csv", "a");
// 정보 입력하기
char *name = get_string("Name: ");
char *number = get_string("Number: ");
// 파일의 내용을 출력하기
fprintf(file, "%s,%s\n", name, number);
// 파일 닫기
fclose(file);
}
파일 읽기
파일의 형식 검사
#include <stdio.h>
int main(int argc, char *argv[])
{
// argc 2가 아니면 파일명이 입력되지 않았거나, 다른 인자가 입력됨
if (argc != 2)
{
return 1;
}
// argv[1]에 담긴 파일명인 파일을 읽기모드로 열기
// 파일이 제대로 열리지 않으면 fopen함수는 NULL 반환
FILE *file = fopen(argv[1], "r");
// 파일이 없다면 종료
if (file == NULL)
{
return 1;
}
// 크기가 3인 문자열 만들기
unsigned char bytes[3];
// file의 첫 3바이트를 읽어옴
//fread(배열, 읽을 바이트 수, 읽을 횟수, 읽을 파일)
fread(bytes, 3, 1, file);
// jepg 파일 시그니쳐(0xFF, 0xD8, 0xFF) 확인
if (bytes[0] == 0xff && bytes[1] == 0xd8 && bytes[2] == 0xff)
{
printf("Maybe\n");
}
else
{
printf("No\n");
}
fclose(file);
}
파일 시그니쳐(Common File Signatures, File Magic Number)
파일 형식마다 가지고 있는 고유의 특징, 즉 포맷에 대한 정보
- 파일 처음에 있는 시그니처 헤더(Header) 시그니처
- 파일 마지막에 있는 시그니처 푸터(Footer) 시그니처
- 만약 헤더 시그니처와 푸터 시그니처가 다른 형식일 경우, 파일에 문제가 있거나 조작된 파일일 가능성이 있음
File type | Header Signature | Footer Signature |
JPEG | FF D8 FF E0FF D8 FF E8 | FF D9 |
GIF | 47 49 46 38 37 6147 49 46 38 39 61 | 00 3B |
PNG | 89 50 4E 47 0D 0A 1A 0A | 49 45 4E 44 AE 42 60 82 |
25 50 44 46 2D 31 2E | 25 25 45 4F 46 | |
ZIP | 50 4B 03 04 | 50 4B 05 06 |
DOCX | 50 4B 03 04 14 00 06 00 | 50 4B 05 06 |
ALZ | 41 4C 5A 01 | 43 4C 5A 02 |
TXT | ||
MP3 | 49 44 33 03 | |
HWP | D0 CF 11 E0 A1 B1 1A E1 | |
JAR | 4A 41 52 43 53 00 |
728x90
반응형
'CS50 정리' 카테고리의 다른 글
CS50 6강[자료구조] (2) | 2024.02.25 |
---|---|
CS50 4강[알고리즘] (0) | 2024.02.20 |
CS50 3강[배열] (0) | 2024.02.20 |
CS50 2강[C언어] (0) | 2024.02.20 |
CS50 1강[컴퓨팅 사고] (2) | 2024.02.20 |