Quick Comparison
C string -> char sequence + terminating '\0', buffer capacity는 별도
std::string -> 길이와 저장 공간을 container가 관리
C# string -> immutable text, 반복 연결은 새 문자열 할당 가능
byte buffer -> text라는 보장 없음, length와 encoding을 함께 관리문자열 길이와 buffer capacity는 다릅니다. 복사·입력 API에는 종료 문자 공간과 실제 bytes 수를 함께 계산해야 합니다.
C 문자열
char name[8] = "player"; /* 6 letters + '\0', 한 칸 여유 */
size_t length = strlen(name); /* '\0' 전까지 세므로 O(n) */종료 문자 없는 배열을 C 문자열 함수에 넘기면 범위를 넘어 읽을 수 있습니다. sizeof(buffer)는 배열이 현재 scope에 있을 때 전체 bytes를 주지만 pointer로 전달된 뒤에는 capacity를 알 수 없습니다. 함수에는 buffer와 capacity를 함께 전달합니다.
char line[128];
if (fgets(line, sizeof line, stdin) != NULL) {
line[strcspn(line, "\n")] = '\0';
}fgets는 capacity를 받아 범위를 지키고 성공·EOF를 반환하지만, 긴 한 줄이 buffer보다 크면 나머지가 다음 입력에 남을 수 있습니다. 완전한 한 줄이 필요한 코드는 newline 존재 여부를 확인하고 남은 입력을 처리합니다.
std::string text = "player";
std::size_t bytes = text.size();
text.reserve(64);std::string::size()는 저장된 char 수이며 UTF-8 사용자 글자 수가 아닙니다. reserve는 capacity를 확보하지만 size를 늘리지 않습니다.
직접 buffer를 관리한다면 pointer만 전달하지 않고 상태를 묶습니다.
typedef struct {
unsigned char* data;
size_t size;
size_t capacity;
} Buffer;
size_t remaining = buffer.capacity - buffer.size;size <= capacity를 불변 조건으로 두고 뺄셈 전에 이 조건을 검증해야 unsigned underflow를 막을 수 있습니다.
연결과 비교
Immutable string을 반복문에서 +로 계속 연결하면 중간 문자열을 반복 생성해 전체 비용이 커질 수 있습니다. 조각 수가 많으면 StringBuilder, list에 모은 뒤 join, 크기를 아는 buffer를 검토합니다.
Text 비교는 요구사항에 맞는 ordinal·culture·case 규칙을 명시합니다. UTF-8 bytes 수, Unicode code point 수, 화면의 grapheme 수는 서로 다르므로 Length를 사용자에게 보이는 글자 수로 단정하지 않습니다.
자주 틀리는 점
- 입력 bytes를 encoding 확인 없이 문자로 해석하지 않습니다.
strcpy·sprintf처럼 destination capacity를 받지 않는 API를 무심코 사용하지 않습니다.- 문자열 연결이 항상 O(1)이라고 생각하지 않습니다.
- Binary data 중간의
0byte를 C 문자열 종료로 오해하지 않습니다.
참고 링크
2 sources