Byte Order and Endianness

Floating-Point Endianness

How do SDL's endianness functions handle floating-point numbers differently from integers?

Abstract art representing computer programming

Floating-point numbers require special handling for endianness because they use a more complex internal representation than integers.

SDL provides dedicated functions for handling floating-point endianness because the byte-swapping process needs to account for the IEEE 754 format.

Understanding Float Representation

A 32-bit float consists of:

  • 1 bit for the sign
  • 8 bits for the exponent
  • 23 bits for the fraction (mantissa)

Here's a program that demonstrates how SDL handles float endianness:

#include <iomanip>
#include <iostream>
#include "SDL.h"

void PrintBytes(
  const char* Label, float Value
) {
  auto* Bytes = reinterpret_cast<Uint8*>(
    &Value);
  std::cout << Label << ": ";

  for (int i = 0; i < sizeof(float); ++i) {
    std::cout << std::hex << std::setw(2)
      << std::setfill('0')
      << static_cast<int>(Bytes[i]) << " ";
  }
  std::cout << "(" << std::dec << Value
    << ")\n";
}

int main() {
  float Original{3.14f};
  PrintBytes("Original ", Original);

  // Swap endianness
  float Swapped{SDL_SwapFloat(Original)}; 
  PrintBytes("Swapped  ", Swapped);

  // Swap back
  float Restored{SDL_SwapFloat(Swapped)}; 
  PrintBytes("Restored ", Restored);
}
Original : c3 f5 48 40 (3.14)
Swapped  : 40 48 f5 c3 (3.14)
Restored : c3 f5 48 40 (3.14)

Reading and Writing Floats to Files

When serializing floats, we can simply interpret them as bytes and use functions like SDL_ReadLE32() and SDL_WriteLE32() in the same way we would for any other 4-byte value:

#include <SDL.h>
#include <iostream>

// Write a float to an SDL_RWops stream in
// little-endian order
bool WriteFloat(SDL_RWops* rw, float value) {
  Uint32 data = *reinterpret_cast<Uint32*>(&
    value);
  return SDL_WriteLE32(rw, data) > 0;
}

// Read a float from an SDL_RWops stream in
// little-endian order
bool ReadFloat(SDL_RWops* rw, float& value) {
  Uint32 data = SDL_ReadLE32(rw);
  if (data == 0 && SDL_RWtell(rw) == 0) {
    // Check for read error
    return false;
  }
  value = *reinterpret_cast<float*>(&data);
  return true;
}

int main(int argc, char** argv) {
  SDL_RWops* rw = SDL_RWFromFile(
    "example.bin", "wb+");
  if (!rw) {
    std::cerr << "Failed to open file: "
      << SDL_GetError() << std::endl;
    return 1;
  }

  float valueToWrite = 3.14159f;
  if (!WriteFloat(rw, valueToWrite)) {
    std::cerr << "Failed to write float."
      << std::endl;
  }

  SDL_RWseek(rw, 0, RW_SEEK_SET);
  // Reset file pointer

  float valueRead;
  if (!ReadFloat(rw, valueRead)) {
    std::cerr << "Failed to read float."
      << std::endl;
  } else {
    std::cout << "Read value: " << valueRead
      << std::endl;
  }

  SDL_RWclose(rw);
  return 0;
}
Read value: 3.14159

Key points to remember:

  • Use SDL_SwapFloat() for in-memory byte swapping
  • For file I/O, it is safe to byte-swap floats to achieve the desired endianness

Answers to questions are automatically generated and may not have been reviewed.

sdl2-promo.jpg
Part of the course:

Game Dev with SDL2

Learn C++ and SDL development by creating hands on, practical projects inspired by classic retro games

Free, unlimited access

This course includes:

  • 75 Lessons
  • 100+ Code Samples
  • 91% Positive Reviews
  • Regularly Updated
  • Help and FAQ
Free, Unlimited Access

Professional C++

Comprehensive course covering advanced concepts, and how to use them on large-scale projects.

Screenshot from Warhammer: Total War
Screenshot from Tomb Raider
Screenshot from Jedi: Fallen Order
Contact|Privacy Policy|Terms of Use
Copyright © 2025 - All Rights Reserved