Skip to Content
Course content

8: Variables and Data Types

Click on the "Edit" button in the top corner of the screen to edit your slide content.

When you first start writing C, there is a strong temptation to treat every number as an int. It's the path of least resistance. You don't have to think about the size of the data or the sign of the number; you just declare it and move on. I've seen this in countless code reviews from developers moving from Python or JavaScript, where "number" is just a generic concept. In C, that mindset is a recipe for subtle, nightmarish bugs.

The "Just Use an Int" Trap

Let's say we're building a simple system to track player stats for a game. You might be tempted to write something like this:

int player_health = 100;
int player_gold = 500;
int player_experience = 1200;
int movement_speed = 5; 

On the surface, this works perfectly. But here is where we run into trouble: int is signed. That means player_gold could technically be -500. If you have a bug in your shop logic that allows a player to spend more than they have, your gold variable will just happily slide into negative numbers. Even worse, if you're tracking something like player_experience in a long-running RPG, a standard 32-bit signed integer caps out at about 2.1 billion. While that sounds like a lot, in the world of "idle games" or high-score trackers, you'll hit that ceiling faster than you think. Once you hit that limit, the number wraps around to -2.1 billion. I can't tell you how many hours I've spent debugging "integer overflow" because someone just used a generic int for a counter that grew too large.

Right-Sizing Your Data

The professional way to handle this is to ask yourself: "What is the absolute nature of this value?" If a value can never be negative, use an unsigned type. If it's a small number that will never exceed 255, use a char (which is essentially an 8-bit integer). If you need precision, you have to choose between float and double.

Here is how I would actually write those player stats:

unsigned int player_gold = 500;      // Gold can't be negative
unsigned long player_experience = 1200; // Give XP more room to grow
unsigned char player_health = 100;     // Health is 0-100, 8 bits is plenty
float movement_speed = 5.5f;           // Speed needs decimals for fine-tuning 

By doing this, you're documenting your intent. When another engineer looks at unsigned int player_gold, they immediately know that negative gold is an illegal state. You're also being mindful of the memory layout. In a small program, the difference between a 1-byte char and a 4-byte int is negligible. But if you're creating an array of 10,000 NPCs, those bytes add up quickly. C gives you this control because it's designed to run on everything from a toaster to a supercomputer; using the right type is how you keep your program lean.

The Precision Trade-off

Then we have the floating-point dilemma. You'll see float and double. I usually lean toward double by default because it has double the precision (64-bit vs 32-bit). However, in game development or embedded systems, float is often preferred because it's faster for the hardware to process and takes up half the space.

The catch is that floating-point numbers are approximations. Never, and I mean never, use a float or double for currency. If you use a float for player_gold, you'll eventually run into a situation where 0.1 + 0.2 equals 0.30000001. That's a great way to lose a customer or break a game economy. For money, stick to integers—represent your gold in cents or smallest possible units instead of using decimals.




📋 Practical Task

Refactoring the Inventory Memory Layout

You have been handed a piece of legacy code for an inventory system. The original developer used int for everything, which is wasting memory and allowing for impossible values (like negative item counts).

Your Task: Rewrite the following variable declarations using the most appropriate C data types based on the requirements provided in the comments. Use unsigned types where values cannot be negative, and choose the smallest integer type that safely fits the described range.

// TODO: Refactor these variables
int item_count = 50;          // Range: 0 to 255
int total_weight = 1200;      // Range: 0 to 65,535
int item_id = 1000000;        // Range: 0 to 4 billion
int item_price = 19;          // Range: 0 to 2 billion
int durability_percentage = 85; // Range: 0 to 100
float item_volume = 1.25f;    // Needs precision, but memory is tight (32-bit is fine)

Submit your refactored declarations. Think about whether unsigned char, unsigned short, unsigned int, or unsigned long is the best fit for each.

Rating
0 0

There are no comments for now.

to be the first to leave a comment.