Data type in c
- Ashok Kumar Kumawat
- Feb 8
- 2 min read
Alright Ashok, let’s dive into Data Types in Embedded C with the structured breakdown you asked for. I’ll keep this focused on embedded industry applications, resource-constrained environments, and safety-critical practices.
1. Concept Overview
Data types define how the compiler interprets and allocates memory for variables.
Common C types: char, int, short, long, float, double.
In embedded systems, sizes are implementation-dependent (e.g., int may be 16-bit on some MCUs, 32-bit on others).
Embedded C often uses fixed-width types (uint8_t, int16_t, etc. from <stdint.h>) for portability and predictability.
2. Embedded Industry Usage
Peripheral registers: Often accessed via uint8_t or uint16_t to match hardware register width.
Communication protocols: UART, SPI, I2C buffers typically use uint8_t arrays.
Timers/counters: Use uint16_t or uint32_t depending on hardware counter width.
Sensor data: Floating-point (float) may be avoided in low-power MCUs; fixed-point integers are preferred.
Safety-critical systems: Always rely on fixed-width types to avoid ambiguity.
3. Practical Examples
Example 1: GPIO Register Access
#include <stdint.h>
#define GPIO_PORTA (*(volatile uint8_t*)0x40004000)
void set_pin_high(void) {
GPIO_PORTA |= (1 << 3); // Set bit 3
}
Here uint8_t matches the register width.
Example 2: Timer Counter
#include <stdint.h>
volatile uint16_t timer_count;
void timer_ISR(void) {
timer_count++; // 16-bit counter for timing events
}
Example 3: Fixed-Point Arithmetic (avoiding float)
#include <stdint.h>
int16_t temperature_raw = 235; // scaled value
// Convert to Celsius with scale factor (0.1°C per unit)
int16_t temperature_celsius = temperature_raw / 10;
4. Best Practices
Use <stdint.h> fixed-width types (uint8_t, int32_t) for clarity and portability.
Avoid float/double unless hardware has an FPU; prefer fixed-point math.
Match type to hardware register size (8-bit register → uint8_t).
MISRA-C compliance: Avoid implicit type conversions; always cast explicitly.
Check compiler documentation: int size varies across compilers/architectures.
5. When to Use
uint8_t: Buffers, communication data, register access.
uint16_t: Timers, ADC values, sensor readings.
uint32_t: System ticks, large counters, memory addresses.
float: Only when precision is critical and MCU supports it efficiently.
char: Text buffers, but beware signedness differences (signed vs unsigned char).
6. Memory & Performance Considerations
RAM/ROM footprint: Larger types (long, double) consume more memory.
Execution speed: 8-bit MCUs handle uint8_t faster than uint32_t.
Alignment: Misaligned access (e.g., 32-bit variable on odd address) may cause performance penalties or faults.
Code size: Using float increases code size due to math libraries.
Low-power systems: Integer math is more energy-efficient than floating-point.
Comments