You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Unsigned char는 8비트로 0~255까지 표현이 가능함 (부호비트를 제외하고 8bit이므로 온전한 1byte 표현 가능)
size_t 의미 : 32비트 환경에서는 4바이트 unsigned int, 64비트 환경에서는 8byte unsigned long으로 표현되고 굳이 이렇게 size_t라는 것으로 typedef를 해준 이유는 c언어가 어느 환경에서 사용될지 미지수이기 때문에 사용자 환경에 따라서 자료형이 달라지도록 해주기 위해서임
memset
원본 함수에서 char를 초과하는 범위를 가진 자료형(대표적으로 int)을 초기화 할 때 1 값으로 하면 생각했던 것과 다르게 1로 초기화되지 않고 16843009라는 값으로 되는데 이는 memset 함수가 주소값을 1바이트 단위로 초기화하기 때문이다. (int가 4byte 이므로 00000001 이라는 8비트가 1byte 씩 나눠 들어가서 16843009가 되는 것임)
00000001 00000001 00000001 00000001 = 16843009
그런데 -1로 하면 -1이 그대로 표현되는데 그 이유는 memset의 두번째 매개변수가 int이지만 함수 내부에서 unsigned char로 변환되고 언더플로우가 발생해 1111 1111이 되므로 decimal로 표현할 때 -1로 표현되기 때문이다. (음수를 표현할 때 컴퓨터는 2의 보수로 표현함, 2의 보수는 1의 보수에 +1을 더한 형태이므로 -1은 1의 보수로 1111 1110이 되고 2의 보수로는 여기에 1을 더한 값인 1111 1111이 됨)
즉, -1을 초기값으로 준다면 배열의 모든 비트가 1값으로 초기화 됨
초기화 할 값으로 unsiged long long 범위를 넘어가면 컴파일 오류 발생 (atoi 와도 관련 있을듯)
unsigned char는 c언어 표준 명세 상 패딩비트 사용을 금지하므로 1byte 기준으로 signed char가 아닌 unsigned char를 사용하여 일관성 있는 동작을 할 수 있게 해줌
memcpy
복사받을 메모리와 복사할 메모리의 영역이 같을 때의 동작은 정의되지 않음
버퍼를 거치지 않고 값이 바로 복사됨
restrict : 반드시 서로 다른 변수(또는 객체)를 가리키고 있다는 뜻
const : 변수 선언과 동시에 초기화를 해야 함 (변수 초기값이 변경되지 않도록 Lock을 거는 개념, 상수화)
n값이 dst 크기보다 클 경우에 예외처리를 하려고 포인터로 넘겨받은 배열의 크기를 구하려고 했으나 포인터 변수의 크기만 구해져서 구현하지 못함
값을 복사할 때 1바이트 단위로 처리되는 것을 유의해야 함 (부호 비트가 맨 앞에 있는 비트이므로 원하는 10진수 음수로 초기화하려면은 반드시 배열 1공간의 바이트 크기를 복사해야함)
memmove
복사받을 메모리와 복사할 메모리의 영역이 같아도 문제가 발생하지 않음
버퍼를 거친 후 값이 복사됨
memcpy 와의 차이점을 아직 잘 모르겠음 (소스 상에서 차이는 별도의 버퍼 변수에 먼저 값을 할당하고 그 버퍼 변수를 사용함)
memcpy와의 차이점 : 복사받을 메모리와 복사할 메모리의 영역이 같을 때 메모리의 주소값이 복사받을 메모리가 앞서있다면 memcpy의 경우 원래 있던 값의 파괴가 일어나는데 memmove같은 경우에는 이를 방지하므로 복사받을 메모리의 끝에서부터 값을 채워 넣음
memcmp
길이가 0인 문자열은 항상 동일하다는 것의 의미를 파악해보기
strcmp랑 좀 비슷한 것 같음
strlcat, strlcpy
반환값은 생성’하려는’ 문자열의 총 길이 값임
NULL을 보장하는 안전한 함수이기 때문에 설정한 dstsize 보다 하나 작은 위치까지만 복사됨
void ft_lstadd_back(t_list **lst, t_list *new)
{
if (*lst != 0 && new != 0)
{
while ((*lst)->next != 0)
*lst = (*lst)->next;
(*lst)->next = new;
new->next = 0;
}
}
위 2가지 코드의 차이점은 첫 번째 코드의 경우, curr이라는 포인터 변수를 별도로 하나 더 선언해서 매개변수 **lst로 들어온 *lst의 인자값을 직접적으로 순회하지 않고 간접적으로 순회하기 때문에 함수가 종료된 후에 curr이 사라지므로 *lst의 주소값이 가장 처음을 가리키는 상태로 유지되는 반면에 두 번째 코드의 경우, 별도의 포인터 변수 없이 *lst의 주소값을 하나씩 순회하므로 함수가 종료되었을 때 *lst는 추가된 new end node 바로 앞의 node의 주소값을 가지고 있는 상태가 된다.
가장 처음 상태를 유지할 수 있는 첫 번째 코드가 더 안정적일 것 같아서 첫 번째 코드를 채택함