strlen
size_t strlen(const char* str);
- 인자: str — 길이를 잴 널 종단 문자열의 시작 주소
- 반환값: size_t — \0 직전까지의 문자 개수 (\0 자체는 카운트 안 함)
- 설명: str부터 한 칸씩 전진하며 \0을 만날 때까지 카운트. \0을 찾아야 끝나는 구조라 시간복잡도 O(n). 순수 바이너리 데이터에 쓰면 안 됨(중간에 우연히 0바이트가 있으면 거기서 멈춰버림).
strcpy
char* strcpy(char* dest, const char* src);
- 인자: dest — 복사받을 목적지 버퍼(반드시 src 길이+1 이상 크기여야 함) / src — 복사할 원본 널 종단 문자열
- 반환값: char* — dest의 시작 주소 (체이닝 목적)
- 설명: src를 처음부터 \0까지 한 바이트씩 dest에 복사, \0도 포함해서 복사함. dest 크기 체크를 안 해서 버퍼 오버플로우 위험이 있는 대표적 함수(strcpy_s, strncpy가 대안). src와 dest가 겹치면 undefined behavior.
strcmp
int strcmp(const char* s1, const char* s2);
- 인자: s1, s2 — 비교할 두 널 종단 문자열
- 반환값: int — s1 < s2면 음수, 같으면 0, s1 > s2면 양수
- 설명: 앞에서부터 한 바이트씩 비교하다가 다른 문자를 만나거나 둘 중 하나가 \0에 도달하면 종료. 바이트는 unsigned char로 해석해서 비교(부호 문제 방지). strncmp(s1, s2, n)은 최대 비교 길이 n이 추가된 버전.
memcpy
void* memcpy(void* dest, const void* src, size_t n);
- 인자: dest — 목적지 버퍼 / src — 원본 버퍼 / n — 복사할 바이트 수
- 반환값: void* — dest의 시작 주소
- 설명: \0이나 데이터 의미와 무관하게 무조건 n바이트를 그대로 복사. 구조체, 배열, 임의 바이너리 데이터에 다 사용 가능. dest와 src가 겹치면 undefined behavior — 겹칠 가능성이 있으면 memmove 사용해야 함.
memcmp
int memcmp(const void* s1, const void* s2, size_t n);
- 인자: s1, s2 — 비교할 두 버퍼 / n — 비교할 바이트 수
- 반환값: int — 첫 차이 지점에서 (unsigned char)s1[i] - (unsigned char)s2[i] 부호, 끝까지 같으면 0
- 설명: \0을 특별 취급하지 않고 무조건 n바이트를 끝까지(또는 다른 지점까지) 비교. 구조체 비교, 해시값 비교, 바이너리 패킷 비교 등에 사용.
핵심 구분 기준
| 계열 |
str 계열 |
mem 계열 |
| 대상 |
텍스트(문자열), \0 종단 전제 |
순수 바이트 블록, 타입/의미 무관 |
| 길이 파악 |
직접 \0 찾아가며 판단 |
인자로 받은 n 그대로 사용 |
| \0 만나면 |
거기서 비교/복사 종료 |
무시하고 계속 진행 |
| 대표 용도 |
문자열 처리 |
구조체, 바이너리 패킷, 해시값 비교/복사 |
구현
size_t my_strlen(const char* buf) {
const char* b_temp = buf;
while(*b_temp != '\0') {
b_temp++;
}
return b_temp - buf;
}
char* my_Strcpy(char* dest, const char* src) {
char* d_temp = dest;
while (*src != '\0') {
*dest = *src;
dest++;
src++;
}
*dest = '\0';
return d_temp;
}
int my_strcmp(const char* buf1,const char* buf2, size_t t) {
const unsigned char* b1_temp = (const unsigned char*)buf1;
const unsigned char* b2_temp = (const unsigned char*)buf2;
for (size_t i = 0; i < t; i++) {
if (b1_temp[i] != b2_temp[i]) {
return b1_temp[i] - b2_temp[i];
}
if (b1_temp[i] == '\0') {
return 0;
}
}
return 0;
}
void* my_memcpy(void* dest, void* src, size_t t) {
//파라미터가 void*형 변수이기 때문에 캐스팅을 하려 1바이트씩 복사.
unsigned char* d_temp = (unsigned char*)dest;
const unsigned char* s_temp = (const unsigned char*)src;
for (size_t i = 0; i < t; i++) {
d_temp[i] = s_temp[i];
}
return dest;
}
int my_memcmp(void* buf1, void* buf2, size_t t) {
const unsigned char* b1_temp = (const unsigned char*)buf1;
const unsigned char* b2_temp = (const unsigned char*)buf2;
for (size_t i = 0; i < t; i++) {
if (b1_temp[i] != b2_temp[i]) {
return b1_temp[i] - b2_temp[i];
}
}
return 0;
}