https://cs50.harvard.edu/x/2023/weeks/4/
Week 4 Memory - CS50x 2023
Harvard University's introduction to the intellectual enterprises of computer science and the art of programming.
cs50.harvard.edu
- allocate 떼어놓다 할당하다
- prompt 촉진하다, 자극하다
16진수 (Hexadecimal)
8bits = 1byte (0x00(0)~FF(255))
binary (2) in bits | 0000 0000 | 1111 1111 |
decimal (10) | 0 | 255 |
hexadecimal (16) | 00 | FF |
0 1 2 3 4 5 6 7 8 9 a b c d e f
그리고 16진수임을 표기하기 위해 앞에 0x 를 붙임
0x10 = 16
0xF = 15
Pointer 포인터 : 메모리의 주소값이 저장된 변수
#include <stdio.h>
int main(void)
{
int n = 50;
printf("%p\n", &n);
}
0x16b01b21c
변수명 앞에 * 붙이면 포인터변수가 선언됨.
string s = "HI!"
C언어에서는 String이 없고,(CS50.h에서 정의된 값임)
string s = "HI!"
char *s = "HI !"
( 지금까지 나온 string은 모두 라이브러리에서 불러온것임. )
s = t 와 같이 변수를 복사하면, 값이 복사되는게 아니라 첫 주소만 복사되며, 실제 값은 여전히 하나이다.
<stdlib.h>
malloc : 필요한 만큼의 메모리를 불러움(해당 메모리 첫 주소를 돌려줌) nul값이 들어가야 하므로 string길이+1을 사용해야 함.
free : melloc으로 호출된 메모리는 반납되지 않으므로 free로 반납을 해줘야 함.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
// Get a string
char *s = get_string("s: ");
// Allocate memory for another string
char *t = malloc(strlen(s) + 1);
// Copy string into memory, including '\0'
for (int i = 0, n = strlen(s); i <= n; i++)
//가운데 조건문에 함수 부르면 매번 계산하므로, 앞에 변수로 빼줌.
{
t[i] = s[i];
}
// Capitalize copy
t[0] = toupper(t[0]);
// Print strings
printf("s: %s\n", s);
printf("t: %s\n", t);
}
strcpy(t, s); 로 간단하게 할수 있음.
메모리를 할당할때, nul을 마지막에 할당해서 닫아주지 않으면, 해당 string은 우연히 다른 값의 nul을 만날때까지 이어지게 됨(에러)
string에서 절대 Nul을 빼먹으면 안됨.
// Get a string
char *s = get_string("s: ");
if (s == NULL)
{
return 1;
}
// Allocate memory for another string
char *t = malloc(strlen(s) + 1);
if (t == NULL)
{
return 1;
}
malloc, get_string 은 오류가 나면 null값을 반환하는데 이경우 위와 같이 오류코드와 함께 빠져나올수 있는 장치를 마련해서 더 큰 충돌을 막아야 함.(nul과 Null은 다름),
// Free memory
free(t);
return 0;
마지막에는 0을 반환해서 정상작동 값도 반환하고, 메모리도 free해줘야 함.
(특히 항시 작동하는 프로그램의 경우 수동반환해줘야함) > 메모리 누수의 원인
메모리 관련 버그는 흔히 일어나는 버그의 종류로, 소프트웨어로 찾아내는 도구가 많이 나와있음.
Vargrid
garbage values
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int scores[1024];
for (int i = 0; i < 1024; i++)
{
printf("%i\n", scores[i]);
}
}
array를 선언할때는 자료형 배열명[크기]
형태로 선언이 되는데, 문제는 크기만 지정하고 내부 값을 지정해주지 않으면 이전에 썼던 메모리 값의 조각들이 의도와 다르게 섞여나오게 되므로, 크기를 선언하면 반드시 그 내부 값을 지정해줘야만 한다.
https://www.youtube.com/watch?v=5VnDaHBi8dM
Swap
#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);
}
//C언어에서만 아래 함수가 작동 안함(변수의 메모리 주소값만 복사해서 가져오므로)
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);
}
void swap(int *a, int *b) //자료형 뒤에 붙는 *은 포인터변수 선언
{
int tmp = *a; //변수 앞에 붙는 *은 내용연산자 실행(내용을 수정)
*a = *b;
*b = tmp;
}
heap overflow
stack overflow
buffer overflow
scanf. : C언어에서 입력값을 받아오려면 기본 라이브러리에는 scanf만 있으며, 해당 입력값의 길이를 미리 지정을 해줘야만 한다.
#include <stdio.h>
int main(void)
{
char s[4];
printf("s: ");
scanf("%s", s);
printf("s: %s\n", s);
}
Files 외부 파일에 기록
#include <cs50.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
// Open CSV file
FILE *file = fopen("phonebook.csv", "a");
// Get name and number
char *name = get_string("Name: ");
char *number = get_string("Number: ");
// Print to file
fprintf(file, "%s,%s\n", name, number);
// Close file
fclose(file);
}