absl::from_chars·SimpleAtoi — 빠른 숫자 변환
#한 줄 요약
absl::SimpleAtoi 계열과 absl::from_chars는 locale에 의존하지 않고 예외를 던지지 않는 숫자 변환 함수다. sscanf·std::stoi·std::stringstream이 가진 locale lookup, 예외, 임시 객체 alloc을 모두 제거해 hot path에서 10배 이상 빠르다.
#동기
C++에서 문자열 → 숫자 변환에는 다섯 가지 접근이 공존한다.
absl::string_view s = "12345";
// 1. sscanfint v1;::sscanf(std::string(s).c_str(), "%d", &v1); // alloc + locale
// 2. std::stoiint v2 = std::stoi(std::string(s)); // alloc + 예외
// 3. std::istringstreamint v3;std::istringstream(std::string(s)) >> v3; // alloc + locale
// 4. std::from_chars (C++17 / C++20)int v4;auto [ptr, ec] = std::from_chars(s.data(), s.data() + s.size(), v4);
// 5. absl::SimpleAtoiint v5;absl::SimpleAtoi(s, &v5);벤치마크에서 SimpleAtoi와 from_chars가 압도적이다. sscanf/stringstream은 매번 locale을 조회하고 임시 std::string을 alloc한다.
#SimpleAtoi — 가장 자주 쓰는 형태
absl/strings/numbers.h가 제공한다.
#include "absl/strings/numbers.h"
int32_t v;if (!absl::SimpleAtoi(s, &v)) { return absl::InvalidArgumentError("not a number");}
int64_t big;absl::SimpleAtoi(s, &big);
uint32_t u;absl::SimpleAtoi(s, &u);
// hex/oct도 명시int32_t hex;absl::SimpleHexAtoi(s, &hex); // "ff", "0xff", "FF" 모두 OK특징:
- 반환값은
bool. 성공·실패만 알린다. - 전체 문자열이 숫자여야 성공. 뒤에 공백·문자가 남으면 실패.
- 부호 처리 정상.
- 부동소수점은
SimpleAtof/SimpleAtod.
#from_chars — locale-free 표준 기반
absl::from_chars는 std::from_chars와 같은 시그니처를 가진다.
absl::string_view s = "12345xyz";int v;auto result = absl::from_chars(s.data(), s.data() + s.size(), v);
if (result.ec == std::errc()) { // result.ptr → 'x' (변환 멈춘 위치)}SimpleAtoi와 달리 부분 변환을 허용한다. 다음 토큰을 이어 파싱할 때 유용.
// CSV "12,34,56" 파싱const char* p = s.data();const char* end = p + s.size();while (p < end) { int v; auto r = absl::from_chars(p, end, v); if (r.ec != std::errc()) break; Use(v); p = r.ptr; if (p < end && *p == ',') ++p;}#내부 구현 핵심
absl/strings/numbers.cc의 정수 파싱은 직접 작성된 loop다.
// 정수 부분 (요약)bool safe_strtoi(absl::string_view text, int32_t* value) { if (text.empty()) return false; bool negative = false; const char* p = text.data(); const char* end = p + text.size();
if (*p == '-') { negative = true; ++p; } else if (*p == '+') { ++p; } if (p == end) return false;
uint64_t result = 0; for (; p < end; ++p) { if (*p < '0' || *p > '9') return false; uint64_t d = *p - '0'; if (result > (UINT32_MAX - d) / 10) return false; // overflow result = result * 10 + d; }
if (negative) { if (result > -int64_t{INT32_MIN}) return false; *value = -static_cast<int32_t>(result); } else { if (result > INT32_MAX) return false; *value = static_cast<int32_t>(result); } return true;}핵심은 세 가지.
- locale 조회 없음 (
'0'~'9'직접 비교). - overflow를 byte 단위로 미리 차단.
- 예외 없음.
부동소수점은 Ryu/Dragonbox 등 modern 알고리즘 기반. std::stod처럼 round-trip 정확성을 유지하면서 빠르다.
#std::charconv와의 관계
C++17부터 <charconv>가 표준에 들어왔다. 정수는 모든 주요 컴파일러가 빠르게 구현했지만 부동소수점 from_chars는 GCC 11, Clang 14쯤에야 안정화됐다. 이전 버전 호환성을 위해 Abseil은 자체 구현을 가진다.
// C++17 표준auto r = std::from_chars(begin, end, v);
// Abseil 백포트 — 동일 인터페이스auto r = absl::from_chars(begin, end, v);ABSL_USES_STD_CHARCONV가 정의되면 alias가 되어 표준 구현으로 위임한다.
#성능 비교 (참고치)
64-bit 정수 파싱, 100만 회 반복 기준 (낮을수록 빠름):
| 함수 | 상대 시간 |
|---|---|
| sscanf | 100x |
| stringstream | 80x |
| std::stoi (alloc + 예외) | 30x |
| strtol | 5x |
| absl::SimpleAtoi | 1.2x |
| std::from_chars / absl::from_chars | 1.0x |
floating point에서도 비슷한 격차다. stringstream은 locale 조회 비용이 호출당 microsecond 단위다.
#코드 리뷰 포인트
1. sscanf 발견 → 즉시 교체 후보
// 회피int year, month, day;::sscanf(s.c_str(), "%d-%d-%d", &year, &month, &day);
// Good — 단계적 from_chars 또는 absl::Time 파서복잡한 포맷이라면 absl::SimpleAtoi 단계 분해. 시간 포맷이면 absl::ParseTime (Part 7-02).
2. std::stoi 예외 의존 코드
// 회피 — 예외 비용try { int v = std::stoi(s);} catch (const std::exception&) { ... }
// Good — bool 반환int v;if (!absl::SimpleAtoi(s, &v)) { ... }Google 스타일은 예외 금지. SimpleAtoi가 자연스럽다.
3. ostringstream으로 숫자 → 문자열
// 회피std::ostringstream oss; oss << v;std::string s = oss.str();
// Goodstd::string s = absl::StrCat(v);역방향도 StrCat (Part 4-03)이 답이다.
4. SimpleAtoi vs from_chars 선택
- 문자열 전체가 숫자여야 한다 →
SimpleAtoi - 접두사만 숫자고 뒤에 더 파싱할 토큰이 남았다 →
from_chars
#자주 보는 안티패턴
범위 체크 누락
int32_t v;absl::SimpleAtoi(s, &v); // 반환값 무시Use(v); // 실패 시 v는 알 수 없음반환값 무시는 [[nodiscard]] 경고 대상이다. 항상 if로 감싼다.
부동소수점에 SimpleAtoi
double d;absl::SimpleAtoi(s, &d); // 컴파일 에러absl::SimpleAtod(s, &d); // Good오타로 자주 발생.
hex 문자열에 SimpleAtoi
int32_t v;absl::SimpleAtoi("0xff", &v); // false — '0xff'는 십진 아님absl::SimpleHexAtoi("0xff", &v); // true → 255#정리
absl::SimpleAtoi/SimpleAtod는 전체 문자열이 숫자일 때 가장 짧다.absl::from_chars는 접두 파싱과 표준 호환이 필요할 때.- 둘 다 locale-free, 예외 없음, alloc 없음.
sscanf·stringstream·std::stoi는 hot path에서 회피.
#다음 편
Part 15-03 — Cord vs std::string 선택에서 두 문자열 타입의 적용 지점을 정리한다.
#관련 항목
- Part 15-03 — Cord vs std::string 선택
- Part 4-03 — StrCat — 숫자 → 문자열
- Part 4-06 — StrFormat
- Folly Part 5-04 — to/from — Meta의 동급 도구
- EMC++ Item 11 — 예외 비용
Abseil Code Review · 75 of 79
- 1 Abseil Code Review — Google production-grade C++ 라이브러리 분석
- 2 Abseil 개요 — Google이 std를 보완한 이유
- 3 Abseil 설계 철학 — std 호환과 추가 기능의 균형
- 4 Abseil 빌드와 의존성 — Bazel vs CMake
- 5 Abseil LTS vs HEAD 릴리스 모델 분석
- 6 Abseil Versioning과 ABI 호환성 정책
- 7 Abseil 매크로 — ABSL_HAVE_*·ABSL_ATTRIBUTE_*
- 8 Abseil ABSL_PREDICT_TRUE/FALSE — branch hint
- 9 absl::LogSeverity — 로그 레벨 타입
- 10 Abseil type_traits — negation·conjunction·void_t
- 11 Abseil Conformance·Policy 분석
- 12 Abseil Memory utilities 분석
- 13 Abseil raw_logging — heap-free 로깅
- 14 Abseil thread_annotations — clang TSA 통합
- 15 absl::Status — exception-free error handling
- 16 absl::StatusOr<T> — 값 또는 에러
- 17 absl status_macros — ASSIGN_OR_RETURN·RETURN_IF_ERROR
- 18 absl::Status payload — 구조화된 에러 컨텍스트
- 19 absl::Status ↔ exception 변환 패턴
- 20 absl::string_view — non-owning 문자열 참조
- 21 absl::string_view 함정 — dangling·c_str·임시 객체
- 22 absl::StrCat — 가변 인자 문자열 연결과 AlphaNum
- 23 absl::StrSplit — Delimiter·Predicate·컨테이너 변환
- 24 absl::StrJoin — 컨테이너 결합과 Formatter
- 25 absl::StrFormat — type-safe printf·FormatSpec
- 26 Abseil ASCII 함수 — locale-free 분류·대소문자 변환
- 27 Abseil Escape — CEscape·HexEscape·Base64
- 28 absl::flat_hash_map — Swiss Table 기반 hash map
- 29 absl::flat_hash_set — set 버전 Swiss Table
- 30 absl::node_hash_map — stable pointer가 필요할 때
- 31 absl::btree_map — sorted·cache-friendly B-tree
- 32 absl::FixedArray — 런타임 크기 stack 배열
- 33 absl::InlinedVector — small buffer optimization
- 34 Abseil Swiss Table internals — control byte·SIMD probing
- 35 absl::Mutex — reader-writer·fairness·deadlock 검출
- 36 absl::Mutex Conditional Critical Section — Await로 cv 없애기
- 37 absl::Notification — once-only signal
- 38 absl::BlockingCounter·Barrier — 다중 thread 조율
- 39 absl::Mutex annotations — clang thread-safety로 race를 컴파일 타임에
- 40 absl::Time·Duration 분석 — 단단한 type
- 41 absl::Time Format·Parse
- 42 absl::CivilTime 분석
- 43 absl::time_zone 분석
- 44 absl::Time mocking — 테스트 친화 시간
- 45 absl::BitGen — 모던 난수 생성기
- 46 Abseil Random Distributions — Uniform·Exponential
- 47 Abseil Mocking Random — 테스트 결정성
- 48 Abseil Random Seeding·Entropy
- 49 absl::int128·uint128 분석
- 50 absl::bits — popcount·countl_zero
- 51 absl::optional vs std::optional
- 52 absl::variant 분석
- 53 absl::span 분석
- 54 absl::any 분석
- 55 absl::compare — three-way 비교
- 56 Abseil utility — apply·in_place
- 57 Abseil AbslHashValue 분석
- 58 Abseil HashState chaining
- 59 Abseil Custom hashable 구현
- 60 Abseil LOG·VLOG·CHECK 분석
- 61 Abseil LogSink 분석
- 62 Abseil LogEntry·structured logging
- 63 Abseil Stack trace·failure_signal_handler
- 64 ABSL_FLAG 정의 분석
- 65 Abseil ParseCommandLine 동작
- 66 Abseil Flag introspection·validation
- 67 Google 스타일의 Abseil 사용 패턴
- 68 Abseil 자주 보는 anti-pattern
- 69 std → absl 마이그레이션 전략
- 70 absl::Cleanup — 함수 종료 시 실행 보장
- 71 Abseil algorithm container 확장 — c_sort·c_find_if·c_count_if
- 72 absl::function_ref와 any_invocable — 함수 객체 전달의 두 축
- 73 absl::bind_front와 Overload — 함수 객체 보조 도구
- 74 absl::Cord — 분산 시스템용 대용량 문자열
- 75 absl::from_chars·SimpleAtoi — 빠른 숫자 변환
- 76 absl::Cord vs std::string — 선택 기준과 메모리 프로파일
- 77 absl::GetStackTrace와 Symbolize — crash 시 readable stack
- 78 absl::ComputeCrc32c — 하드웨어 가속 체크섬
- 79 absl::PeriodicSampler — 적응형 샘플링·jitter 회피
관련 글
absl::PeriodicSampler — 적응형 샘플링·jitter 회피
absl::profiling_internal::PeriodicSampler — sampling rate를 동적으로 조정, geometric distribution으로 jitter 회피. 메모리 할당 추적·profiling 인프라의 기반.
같은 시리즈에서 이어 읽기
Abseil ParseCommandLine 동작
absl::ParseCommandLine — argv를 flag로 분리하고 positional 인자를 돌려주는 단일 진입점.
같은 시리즈에서 이어 읽기
absl::StrCat — 가변 인자 문자열 연결과 AlphaNum
Part 4-03: absl::StrCat — variadic 문자열 연결, AlphaNum 어댑터, operator+ / ostringstream과의 성능 차이.
같은 시리즈에서 이어 읽기