동글c
동글한 스터디룸
동글c
전체 방문자
오늘
어제
  • 분류 전체보기 (14)
    • 입문 (14)
      • CS50X (14)
      • 컴퓨터과학이 여는 세계 (0)
    • 컴퓨터 구조 (0)
      • CSAPP (0)
    • 프로그래밍 (0)
      • SICP (0)
    • 회고 (0)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 포인터
  • recover
  • 조건문
  • problemset2
  • types
  • Hashtable
  • overflow
  • 반복문
  • scratch
  • hash
  • LinkedList
  • MergeSort
  • compiling
  • tiedman
  • speller
  • selectionsort
  • Datastructure
  • pointers
  • Harvard CS50
  • tree
  • loops
  • Strings
  • computerscience
  • bubblesort
  • Volume
  • command-line arguments
  • CS50
  • int
  • DICTIONARY
  • Trie

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
동글c

동글한 스터디룸

[CS50X] 2024 Week4 Memory
입문/CS50X

[CS50X] 2024 Week4 Memory

2024. 2. 24. 11:37

 

 

Hexadecimal

그래픽이나 색상등 아트와 관련한 것을 컴퓨터로 표현할 때 

hexadecimal 16진수 를 주로 사용한다. 

흔히 흰색을 RGB(255, 255, 255) --> #FFFFFF 로 표현하는 것이다.

16진수에서 한 칸은 16개가 존재한다.

0, 1 ==> Binary 이진수

0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ==> Decimal 10진수

0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F ==> Hexadecimal 16진수

 

16진수를 사용하는 이유는 편리하기 때문이다.

컴퓨터에서 16을 표현하기 위해선 4개의 bit를 사용해야한다. 

보통 컴퓨터에서 메모리를 표현하고 사용할때 8bit / 1byte 가 기준이 된다.

따라서 16진수를 사용하면 11111111 로 표현해야하는 것을 FF 이렇게 줄일 수 있게 된다.

16진수는 10진수와 혼동하기 쉬워서 이를 구분해줘야하는데

0x 가 16진수를 나타내는 표시이다. 28 = 0x1C = 11100

 

 

 

 

 

Pointers

앞으로 자주 쓰게 될 기호가 새롭게 등장한다. & *

& = 엠퍼센트 , &n = n의 메모리 주소

* = 역참조자, 1. *n = 포인터(주소)임을 선언/설정   , 2. *값이 온 주소로 거슬러 감

* 의 경우 맥락에 따라 2가지 의미를 갖는다.

#include <stdio.h>

int main(void)
{
    int n = 50;
    //여기서는 "여기는 포인터(주소)임을 알려주는 역할"
    int *p = &n;
    //여기서는 p의 주소로 거슬러 올라가라는 역할
    printf("%i\n", *p);
}

 

 

포인터의 경우 보통 8bytes 를 사용한다 64bit 인데 어마어마하게 큰 숫자이다.

많은 bytes 를 할당하는 이유는 컴퓨터가 발전함에 따라 점점 메모리 주소의 숫자가 커지고 있다.

포인터는 메모리의 주소를 담아야 하기 때문에 모든 주소를 커버할 수 있어야 한다.

위의 코드가 실행될 때 메모리 모습

포인터에 대해 너무 깊게 생각하지 않아도 될 것 같다.

포인터로 선언된 변수는 어떤 변수의 메모리 주소를 담고 있고

*포인터 변수 를 하면 담고 있는 그 메모리 주소를 따라 그 안에 담겨 있는 것을 가르킬 뿐이다.

 

 

 

 

Strings

전에 type 에서 string에 다루긴 했지만

C는 string 이라는 type을 제공하지 않는다.

string 이라는 type 을 제공하지 않는다고 해서 

문자열 이라는 개념이 없는 것은 아니다. 

분명히 C는 "" 와 '' 를 구분하며 "" 로 선언 될 시 

추가적으로 1bit를 더 할당해서 감시값을 넣어 종료 시점을 확인한다.

stdio 라이브러리에도 string 에 대한 것은 없다. 

강의 보조 라이브러리에만 string 에 대한 것이 있는데

사실 string 은 하나의 포인터 이다.

 

그것도 문자열의 문자중 첫 번째 문자를 가르키는 포인터이다.

따라서 string s = "hi!" 라고 썼던 코드는

char *s = "hi" 와 같아지게 된다.

애초에 C언어를 개발했을 때는 string 이라는 타입이 필요하지 않았다.

 

 

 

 

 

 

Pointer Arithmetic

포인터 주소는 연산도 가능하다.

#include <stdio.h>

int main(void)
{
    char *s = "HI!";
    printf("%c\n", *s);
    printf("%c\n", *(s + 1));
    printf("%c\n", *(s + 2));
}

 

s의 주소는 0x5631a5f77004 예를 들면 이런 값이 되는데

0x5631a5f77004 = s[0] 를 가르키고 

0x5631a5f77005 = s[1] 을 가르킨다. 

메모리 주소에 직접 연산을 해서 그 위치에 있는 값을 찾아 올 수 있다.

 

 

 

 

String Comparison

만약 두 문자열을 비교하는 경우

char *s = "hi";

char *t = "hi"; 

이렇게 선언 되었을 때 s == t 는 false 같지 않음이다.

그 이유는 char * 자체가 문자를 가르키는 것이 아니고

주소를 가르키고 있기 때문이다.

변수가 생성되었을 때 컴퓨터는 메모리 어딘가에 4바이트 짜리 메모리 덩어리를

어디인가에 생성한다. 당연히 s 와 t 가 생성된 위치는 다르므로 같지 않은 것이다.

즉 s == t 는 문자 끼리의 비교가 아니고 주소의 비교이다.

 

그러면 여기서 *s == *t 는 성립할까 궁금해졌다. 

실행해본 결과 성립한다. *s 는 h 를 나타내고, *t 도 마찬가지이다.

하지만 이건 문자열 전체가 같다는 것이 아니라 맨 앞자리만 비교한 것으로 

반복문을 통해 *(s+i) == *(t+i) 를 순차적으로 비교해줘야

문자열 비교가 이뤄질 것이다.

강의에서는 strcmp 를 통해 간단히 구현했지만 strcmp 함수 자체도 구현 가능한 것이다.

 

 

 

 

 

String Copy , Melloc, Free

문자열을 복사하는 경우 그냥 단순히 

char *s = "hi!";

char *t = s;

이렇게 해버리면 t에는 s 주소 값이 들어가 있고

결과적으로 다른 이름의 두 변수가 같은 메모리를 가르키고 있는 모양이 된다.

 

그러면 문자열을 복사하는 것이 아니게 된다.

문자열을 복제하고 싶은 경우 

복사하려고 하는 문자열과 같은 크기의 메모리 공간을 새로 생성하고 - melloc

for 문을 통해 t[i] = s[i] 로 각각의 문자들을 복사하고 - strcpy(라이브러리 함수)

*for 문을 통해 복사할 때는 반드시 s의 센티널 값 까지 복사를 해줘야 한다.

임의로 생성한 메모리를 다시 풀어줘야 한다 - 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: ");
    if (s == NULL)
    {
        return 1;
    }

    // Allocate memory for another string
    char *t = malloc(strlen(s) + 1);
    if (t == NULL)
    {
        return 1;
    }

    // Copy string into memory
    strcpy(t, s);

    // Capitalize copy
    if (strlen(t) > 0)
    {
        t[0] = toupper(t[0]);
    }

    // Print strings
    printf("s: %s\n", s);
    printf("t: %s\n", t);

    // Free memory
    free(t);
    return 0;
}

 

 

 

 

 

 

 

Swapping

 

컴퓨터 메모리를 단적으로 떼서 본다면 이런식으로 구성된다. 

만약 main 함수에서 swap 함수를 호출하는 형태로 코드를 짜면

stack 맨 아래에 main 이 존재하고 그 위에 swap 이 존재한다.

 

main 에서 int x = 1; int y = 2 이런식으로 변수를 설정하고

swap(x ,y) 이런식으로 매개 변수를 통해 x, y를 넘겨주면 

그것은 x, y 그 자체가 아니라 복사본 이다. 그래서 swap 에서 x 와 y 로 하는 작업은

실제 main의 x, y 에 영향을 미치지 않는다.

여기까지는 어떻게 보면 당연한 얘기였는데 그 다음은 굉장히 신선했다.

C에서는 메모리에 직접 접근할 수가 있는데 main 에서 x , y 의 주소를 넘기면

swap 에서 그 메모리 주소를 타고 가서 그 곳에 위치한 값에 접근이 가능한 것이다.

주소만 전달해주면 * 를 통해 역참조해서 그 값을 바꿀 수 있고 scope를 뛰어 넘을 수 있다.

 

#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;
}

 

 

저작자표시 (새창열림)

'입문 > CS50X' 카테고리의 다른 글

[CS50X] Week3 번외편(Sort 구현 - Selection, Bubble, Merge, 비트연산자 )  (0) 2024.03.05
[CS50X] 2024 Week4 Memory Problem Set 4 (Volume, Filter, Recover)  (0) 2024.02.29
[CS50X] 2024 Week3 Algorithms Problem Set 3 (Sort, Plurality, Tideman)  (0) 2024.02.23
[CS50X] 2024 Week3 Algorithms  (1) 2024.02.23
[CS50X] 2024 Week2 Arrays Problem Set 2 (Scrabble, Readability, Substitution)  (0) 2024.02.22
    '입문/CS50X' 카테고리의 다른 글
    • [CS50X] Week3 번외편(Sort 구현 - Selection, Bubble, Merge, 비트연산자 )
    • [CS50X] 2024 Week4 Memory Problem Set 4 (Volume, Filter, Recover)
    • [CS50X] 2024 Week3 Algorithms Problem Set 3 (Sort, Plurality, Tideman)
    • [CS50X] 2024 Week3 Algorithms
    동글c
    동글c
    깃허브 : https://github.com/asena1006

    티스토리툴바