개발/C·C++
-
덧셈 연산 어셈블리 코드 간단 분석개발/C·C++ 2024. 9. 7. 00:29
다음 코드를 어셈블리로 봐보자. for (int i = 0; i 00007FF6993C57AA mov rax,qword ptr [counter] 00007FF6993C57B1 mov eax,dword ptr [rax] 00007FF6993C57B3 inc eax 00007FF6993C57B5 mov rcx,qword ptr [counter] 00007FF6993C57BC mov dword ptr [rcx],eax 1. mov rax, qword ptr [counter]- counter 변수의 주소값을 rax 레지스터가 담는다- 주소이기 때문에 8바이트를 읽어야 하므로 qword ptr이 사용된다2. mov ea..
-
std::transform()에 대한 간단한 고찰개발/C·C++ 2024. 9. 4. 22:21
C++ 문법에 대해 살펴보다가 재미있는 코드가 있어서 간단하게 고찰해보려고 한다.공식 문서에 구현 예제까지 나와있다.헤더는 templateconstexpr //templateconstexpr // 대략적인 흐름은 원본 데이터에 대한 시작 반복자, 끝 반복자로 범위를 지정해주고결과물을 저장할 자료구조(우리 예제에서는 vector)의 시작 반복자,그리고 데이터를 가공할 방법을 안내하는 콜백 함수를 넣어주는 형태다. 앞서 잠시 언급했듯이 vector를 사용해 볼 건데,transform()에 넣을 함수 포인터는 멤버 함수에 대한 함수 포인터다.멤버 함수 포인터를 만드는 방법은 일반 함수와 조금 다르다.멤버 함수를 호출할 때 보통 "인스턴스." 혹은 "포인터 변수->"의 방식으로멤버 함수를 호출하고 필요한 인수를..
-
포인터의 타입 추론개발/C·C++ 2024. 8. 31. 12:31
templatevoid f(T* param){ cout f() 함수는 T*으로 인수를 받고 있다. const int*로 선언된 pcx 변수를 전달하면 어떤 타입으로 추론이 되는지 살펴본다. 답을 보기 전에 가능한 시나리오를 검토해보자.pcx는 const int*이니까 T는 const int가 될 수도 있고 모종의 이유로 const가 탈락한 int가 될 수도 있다. 혹은 T* 이므로 해당 타입이 가리키는 타입으로 추론될 수도 있을 것이다. 정답은 아래를 드래그 하면 된다. int 예상 가능한 시나리오의 세 번째에 해당한다고 볼 수 있다.T*은 해당 포인터 변수가 가리키는 타입을 추론한다. int형 가리키기 때문에 int로 추론된다.그렇다면 f() 함수의 파라미터가 T이면 어떨까?#include #in..
-
[사소한 테스트] 곱셉/나머지 연산의 로직을 덧셈/뺄셈으로 변경한다면?개발/C·C++ 2024. 8. 28. 17:43
사소해서 코드까지 올릴 문제는 아니다. 문자열로 표현된 숫자를 가지고 더하기 연산을 할 때, 올림값(carry) 관련해서 곱셉과 나머지 연산을 이용하면 간결한 코드를 작성할 수 있다. 이를 조건문, 덧셈, 뺄셈으로도 표현할 수 있는데 코드가 조금 길어진다. 문득 이 두 로직 간의 성능 차이가 얼마일지 궁금해서 100만 번 테스트를 했다.나노초 단위로 표현된 차이이며 백만 번 수행했을 때 속도 차이는 0.1초였다. CPU 기준에선 꽤 큰 차이라고 할 수 있다. 라이브 중인 서비스라면 결코 무시할 수 없는 수치라고 생각한다. 어느 정도 예상했겠지만 Test_2() 함수가 조건문, 덧셈, 뺄셈으로 구현된 함수다. 곱셈, 나눗셈, 나머지 연산이 느리다는 건 알고 있었지만 테스트로 직접 눈으로 확인해보니까 조금 ..
-
[윈도우 시스템 프로그래밍] 압축 파일 복사하기개발/C·C++ 2024. 8. 27. 23:17
파일을 윈도우에서 제공하는 API를 통해 메모리로 추상화를 하면 파일을 메모리처럼 사용할 수 있다. 텍스트 파일을 메모리로 추상화하면 strcpy_s() 함수를 이용해 텍스트 파일에 문자열을 복사할 수 있으며 같은 맥락에서 파일 복사 역시 memcpy_s() 사용해서 편하게 복사할 수 있다. 기본 과정은 어렵지 않고 세부적으로 함수를 호출할 때 플래그만 잘 넣어주면 된다. 예를 들어 읽기 속성으로 파일 핸들을 구했는데, 매핑 객체를 만드는 함수를 호출할 때 읽기/쓰기 플래그를 넣으면 정상적인 반환 값을 얻을 수 없다. 테스트 파일은 압축 파일이다. 압축 파일은 crc로 무결성을 검사하기 때문에 정확한 복사 여부를 확인할 수 있기 때문이다. 복사한 압축 파일을 풀어서 데이터를 열람할 수 있으면 된다. 다음..
-
std::remove_if, std::erase개발/C·C++ 2024. 8. 17. 20:18
이 둘을 이용해서 데이터를 지우는 로직은 보통 다음과 같다.auto it = std::remove_if(data_vector_.begin(), data_vector_.end(), [remove_node](const std::unique_ptr>& node) { return node.get() == remove_node; }); if (it != data_vector_.end()) { data_vector_.erase(it, data_vector_.end());} remove_if의 구현 방식은 대단히 간단한데 다음과 같다.(참고링크)templateForwardIt remove_if(ForwardIt first, ForwardIt last, UnaryPred p){ fir..
-
전화번호 무작위 생성개발/C·C++ 2024. 8. 3. 13:57
테스트 삼아 10,000개의 데이터를 선형 자료구조에서 중복 검사까지 하면서 생성해보니 6~7분 정도 걸리는 것 같다. C++에서 제공하는 라이브러리들은 비선형 구조이기 때문에 데이터 삽입과 탐색이 선형 자료구조에 비해 압도적으로 빠르다. PhoneNumberMaker 클래스에서는 PhoneNumberMakerImpl의 unique_pointer만 들고 있고 실제 구현은 PhoneNumberMakerImpl에서 이뤄진다. 이 구조의 장점은 데이터를 가리키는 포인터와 실제 데이터를 클래스로 구분할 수 있다는 점이다. 별도의 클래스 생성으로 아주 약간 메모리를 더 쓰긴 하지만 차이는 미미하다고 봐도 될 것 같다. PhoneNumberMaker은 일종의 인터페이스만 제공하는 역할을 한다 PhoneNumber..
-
[정렬] 더미 노드와 병합 정렬개발/C·C++ 2024. 7. 18. 14:02
연결 리스트를 정렬하는 데에는 병합 정렬이 최적이다. 시간 복잡도가 평균적으로 N(log(2)N)을 보장하며 순서가 뒤바뀌지 않는 안전 정렬이다. 구현한 연결 리스트는 더미 헤드 노드와 더미 테일 노드를 가지는데 이 존재가 정렬할 때 조금 문제가 되었다. 나이와 전화번호를 가지고 있는데, 정렬의 포인터는 헤드 노드 포인터의 next_ptr부터 시작할 수 있으므로 문제가 되지 않지만 더미 테일 노드는 제외하는 로직을 넣어야 하기 때문이다. 병합하는 과정에서, 마지막 과정임을 확인하는 건 작업하는 노드의 갯수를 세는 방법밖에 없으므로 카운팅 로직 하나당 O(N)의 시간 복잡도가 발생하는데, 총 세 번이 발생한다. 데이터의 양이 적을 땐 유의미하지 않지만 데이터가 200만개가 되니까 처리 시간이 급속도로 늦어..