BitOps is an interactive C++17 console demo for bit manipulation. Pick an operation from a menu and watch a 32-bit value and its binary representation change: set, clear, and toggle individual bits, negate the whole value, or shift it left and right.
It started as a 2021 classroom program and was modernized in 2026. The bit operations now live in a testable library (bitops_core), the interactive session is a separate, stream-injected component (bitops_app) that can be driven by scripted tests, and every push is checked by CI on Linux, Windows, and macOS.
This is a teaching demo, not a general-purpose library: it works on one 32-bit value, shifts by one place, and has no command-line interface beyond --help, no file I/O, and no network access.
- A C++17 compiler: GCC 7+, Clang 5+, or MSVC 2017+ (any compiler with
std::from_charsfor integers and inline variables) - CMake 3.16 or newer
- Git, to clone the repository
No third-party libraries are required. Tests are dependency-free and run under CTest.
Prebuilt binaries are available from GitHub Releases, starting with v1.1.0: download the bitops-<platform>.zip for your system, unzip it, and run the binary inside. The binaries are unsigned, so Windows SmartScreen may warn and macOS Gatekeeper may block the first run; on macOS, xattr -d com.apple.quarantine bit_manipulation-macos-arm64 removes the quarantine flag, or build from source below instead.
Or clone the repository and build the Release configuration:
git clone https://github.com/enonymous1/BitOps.git
cd BitOps
cmake -S . -B build -DCMAKE_BUILD_TYPE=Release
cmake --build buildThe executable is build/bit_manipulation (on Windows, build\Release\bit_manipulation.exe).
To install it system-wide after building:
cmake --install buildOr build without CMake, directly with a compiler:
g++ -std=c++17 -Wall -Wextra bit_ops.cpp app.cpp main.cpp -o bit_manipulation./build/bit_manipulation./build/bit_manipulation --help prints usage. Unknown arguments are rejected with exit status 2. Exit the session with menu option 7 or Ctrl-D (closed stdin also exits cleanly with status 0).
Configure a Debug build and run CTest:
cmake -S . -B build -DCMAKE_BUILD_TYPE=Debug
cmake --build build
ctest --test-dir build --output-on-failureThere are two test binaries, both dependency-free:
bitops_tests— the library: set/clear/toggle, negation, shifts (including bits shifted out), binary rendering, and out-of-range bit indices, which must throwstd::out_of_range.bitops_app_tests— the interactive session, driven through string streams: turn-on/toggle/negate/shift flows, invalid and out-of-range input, trailing junk (1abcis rejected, not read as1), and EOF in the middle of a prompt.
An AddressSanitizer + UndefinedBehaviorSanitizer build is also run in CI on Linux. To run it locally:
cmake -S . -B build-asan -DCMAKE_BUILD_TYPE=Debug \
-DCMAKE_CXX_FLAGS="-fsanitize=address,undefined -fno-omit-frame-pointer"
cmake --build build-asan
ctest --test-dir build-asan --output-on-failureCode follows the style in .clang-format (4-space indent, Allman braces, 100 columns). The config is currently advisory only: it is not enforced in CI, because the available clang-format versions differ across machines and a pinned-version check has not been added yet. See REVIEW.md for the follow-up.
bit_ops.hpp/bit_ops.cpp— thebitops_corelibrary: pure bit operations onstd::uint32_tapp.hpp/app.cpp— thebitops_applibrary: the menu session over injected input/output streamsmain.cpp— thin entry point: argument handling only, then callsbitops::runApptests/test_bit_ops.cpp,tests/test_app.cpp— dependency-free tests, run by CTestCMakeLists.txt— C++17 build with per-target warnings (-Wall -Wextra -Wpedantic,/W4on MSVC).github/workflows/ci.yml— build + test on Ubuntu, Windows, and macOS, plus a sanitizer job on LinuxCHANGELOG.md— release historyREVIEW.md— the staff-level review of v1.0.0 and what v1.1.0 changed in response
- Add the pure function to
bit_ops.hpp/bit_ops.cpp(validate any index withstd::out_of_range, as the indexed operations do). - Add a case in
runAppinapp.cppand a line inprintMenu. - Add library cases to
tests/test_bit_ops.cppand, if it is interactive, a scripted session totests/test_app.cpp.
If the menu grows past about eight operations, replace the switch with a data table (id, label, needs-bit flag, function) that renders the menu and dispatches from one source of truth. At seven operations a table is more machinery than the duplication it removes, so the switch stays for now.
There is nothing to deploy. BitOps is a local command-line program: no server, no service, no database, no package registry, and no hosted demo.
Releases are the distribution mechanism, driven by the tag-triggered workflow in .github/workflows/release.yml:
- Bump the version in
CMakeLists.txtand add an entry toCHANGELOG.md. - Push to
mainand let CI go green on all three operating systems. - Tag the pushed tip and push the tag — after pushing
main, not before, because the workflow has to be in the tagged commit to run:
git tag v1.1.0
git push origin v1.1.0The workflow first checks that the tag matches the version in CMakeLists.txt (a - suffix is allowed for pre-releases, e.g. v1.2.0-rc1) and runs the test suite. It then builds and tests on Ubuntu, Windows, and macOS, stages each platform's binary plus the LICENSE, and creates a GitHub Release with generated notes containing:
bitops-linux-x64.zip—bit_manipulationat the zip rootbitops-windows-x64.zip—bit_manipulation.exeat the zip rootbitops-macos-arm64.zip—bit_manipulationat the zip rootSHA256SUMS.txt— SHA-256 checksums for the three zips, verifiable withsha256sum -c SHA256SUMS.txtafter downloading them into one directory
Tags with a - suffix are marked as pre-releases. The binaries are unsigned: see the note in Installation about SmartScreen and Gatekeeper. CI itself (.github/workflows/ci.yml) builds and tests every push to main and every pull request, but does not publish anything — only a tag push creates a release.
A real terminal capture. Starting from 2021, turning on bit 1 gives 2023:
------------------------Bit Manipulation------------------------
Current bitField = 2021
Bits: 00000000000000000000011111100101
1) Turn on a bit
2) Turn off a bit
3) Toggle a bit
4) Negate bitField
5) Left shift bitField
6) Right shift bitField
7) Exit
Enter the number of the operation you'd like to perform: 1
Choose a bit index (0-31): 1
Turned on bit 1!
bitField == 2023
Bits: 00000000000000000000011111100111
------------------------Bit Manipulation------------------------
Current bitField = 2023
Bits: 00000000000000000000011111100111
1) Turn on a bit
2) Turn off a bit
3) Toggle a bit
4) Negate bitField
5) Left shift bitField
6) Right shift bitField
7) Exit
Enter the number of the operation you'd like to perform: 7
Exiting BitOps.
MIT — see LICENSE.