Scan the code to follow Chip Dynamics, and say goodbye to “chip” congestion!

Search WeChat
Chip Dynamics
The data types in C language are the core of programming fundamentals, directly affecting memory usage, performance, and security. K&R (the father of C language) clearly states in “The C Programming Language”: “Data types determine the range of values a variable can hold and the operations that can be performed on it.” This is akin to the atomic structure of the physical world; seemingly simple types like char/int/float are actually the quantum bits that construct all complex programs.
Why are data types so critical? Let’s look at a painful lesson: the explosion of the European Space Agency’s Ariane 5 rocket during its maiden flight in 1996 was caused by a 64-bit floating-point number being converted to a 16-bit integer, leading to overflow. This $500 million bug profoundly warns us: our understanding of data types must go beyond the surface.
Today, we will dissect the data types in C language with an engineer’s rigor, from the microscopic world of bits to the macroscopic view of cross-platform development.
Data Types: Have You Chosen the Right “Storage Box”?
In C language, data types are like storage boxes of different sizes, helping you categorize and store data, avoiding the embarrassment of “overusing big materials” or “exploding small materials”.
1. Integer (int):
Integer data, as the name suggests, is used to represent whole numbers. It is like the “legion of integers” in the C language world, including positive integers, negative integers, and 0. In C language, common integer data types include int (basic integer), short (short integer), long (long integer), and long long (even longer integer). Their differences are like different sizes of suitcases: int is a medium-sized suitcase, short is a small suitcase, long is a large suitcase, and long long is an extra-large suitcase that can hold a wider range of integers.
#include <stdio.h>int main(){ short small_box = 32767; // Small box, can hold -32768 to 32767 int medium_box = 2147483647; // Medium box, can hold about ±2.1 billion long big_box = 9223372036854775807; // Large box, can hold about ±922 billion billion printf("Small box:%hd, Medium box:%d, Large box:%ld\n", small_box, medium_box, big_box); // Let's see what happens when we exceed the range small_box = small_box + 1; // Overflow! Becomes -32768 printf("Overflowed small box:%hd\n", small_box); return 0;}
2. Floating Point (float/double):
Floating point data is specifically used to represent numbers with decimal points, like the “magician with decimal points” in the C language world. It can conjure various decimals, such as height, weight, scores, etc. There are mainly two types of floating point data: float (single precision floating point) and double (double precision floating point). Float is like an ordinary magic wand that can represent decimals with a certain precision; double is a more advanced magic wand that can represent decimals with higher precision and a larger range.
#include <stdio.h>int main() { float light_speed = 299792458.0; // Speed of light, in meters/second double pi = 3.141592653589793; // More precise π printf("Speed of light (float): %.2f meters/second\n", light_speed); // %.2f means keep two decimal places printf("More precise π: %.15lf\n", pi); // lf means long float, i.e., double // Floating point precision issue float money = 1234567.89; // Bank deposit (only in dreams) if (money == 1234567.89) { printf("I dreamt I had 1234567.89 yuan!\n"); } else { printf("Huh, why has my money changed to %.10f yuan?\n", money); } // Tip: It's best to use range checking rather than direct equality for floating point comparisons return 0;}
3. Character (char):
Character data is used to represent a single character; it is the “letter sprite” and “symbol monster” in the C language world, including letters, numbers, punctuation, etc. In C language, char is used to define character type variables. Each character has a corresponding ASCII code value, like their “ID number”.
#include <stdio.h>int main() { char initial = 'A'; // Single quotes indicate a character char newline = '\n'; // Escape character indicates a newline char beep = '\a'; // Escape character indicates a beep printf("My initial is %c%c", initial, newline); printf("Listen, the computer is beeping%c", beep); // Characters are actually numbers printf("The ASCII code of 'A' is %d\n", initial); printf("The character corresponding to 65 is %c\n", 65); return 0;}
Character data also has an interesting characteristic: it has a certain relationship with integer data. Since each character has a corresponding ASCII code value, character data can be treated as integer data to some extent. The character ‘A’ is actually the number 65. You can use %d to reveal its true identity or %c to let it wear a letter mask.
#include <stdio.h>int main() { char ch = 'A'; int asciiValue = ch; // Assign the ASCII code value of character 'A' to integer variable asciiValue printf("The ASCII code value of character 'A' is: %d\n", asciiValue); char letter = 'a'; printf("The next letter after 'a' is: %c\n", letter + 1); // Outputs 'b' printf("The ASCII code of 'a' plus 10 is: %c\n", letter + 10); // Outputs 'k' // Case conversion magic printf("'A' to lowercase: %c\n", 'A' + 32); // Outputs 'a' printf("'b' to uppercase: %c\n", 'b' - 32); // Outputs 'B' return 0;}
Understanding the Size of Data Types: Know Your “Storage Box” Capacity
Want to know how big your data types are? Use the sizeof operator:
#include <stdio.h>/************************************************************************************When printing the size of a data type, we usually use %d to output. However, sometimes this method may cause errors in VS. To avoid errors, use %zu. This means to print an unsigned integer returned by sizeof, which can avoid errors or warnings************************************************************************************/int main() { printf("=== Size of Data Types (bytes) ===\n"); printf("char: %zu\n", sizeof(char));//1 byte printf("short: %zu\n", sizeof(short));//2 bytes printf("int: %zu\n", sizeof(int));//4 bytes printf("long: %zu\n", sizeof(long));//4 bytes on 32-bit systems, 8 bytes on 64-bit systems printf("float: %zu\n", sizeof(float));//4 bytes printf("double: %zu\n", sizeof(double));//8 bytes // Interesting discovery int cups_of_coffee = 3; printf("\nI drank %d cups of coffee, which occupies %zu bytes of memory\n", cups_of_coffee, sizeof(cups_of_coffee)); // Output: I drank 3 cups of coffee, which occupies 4 bytes of memory return 0;}
Pitfall Guide
🚫 Pitfall 1: Integer Overflow Leading to Logical Errors
unsigned char a = 255;a += 1; // Actual value becomes 0, no compilation warning!
Solution:
-
Use a larger data type: unsigned int or unsigned long long
-
Manually check boundaries: if (a > UCHAR_MAX – 1) { /* Handle overflow */ }
🚫 Pitfall 2: Implicit Type Conversion Trap
int i = -5;unsigned int j = 10;if (i < j) { /* Actually returns false! Because i is converted to a very large unsigned number */ }
Solution:
-
Explicit type casting: if ((int)j > i)
-
Avoid mixing signed/unsigned comparisons
🚫 Pitfall 3: Floating Point Precision Loss
float f = 0.1f;double d = 0.1;// f is actually stored as 0.10000000149011611938// d is actually stored as 0.10000000000000000555float a = 0.1 + 0.2;if (a == 0.3) { // May not hold // ...}// To check a=0.3, avoid direct comparison#define EPSILON 1e-6if (fabs(a - 0.3) < EPSILON) { // Considered equal}
Solution:
-
Use double when high precision is needed
-
Avoid direct comparison of floating point equality
🚫 Pitfall 4: Uncertainty of char Sign
char c = 255; // Could be -1 or 255
Solution: Explicitly specify signed/unsigned
🚫 Pitfall 5: Confusion Between Characters and Numbers
char ch = '5';int num = ch; // num is 53 ('5' ASCII code)
Solution:
int num = ch - '0'; // Correctly converts to number 5
🚫 Pitfall 6: Integer Division
int a = 5, b = 2;float c = a / b; // c=2.0, not 2.5
Solution:
float c = (float)a / b;
Conclusion
As Dennis Ritchie, the father of C language, said: “Data types are not shackles of programming, but safety rails.” Through this deep exploration of data types, we have unveiled this fundamental and critical feature of C language.
Finally, here’s a programmer’s truth: “Programmers who respect data types will never be awakened by strange bugs in the middle of the night.” May you write efficient and robust code in your C programming journey, thanks to a solid foundation in data types!
Remember three core principles:
-
Know the why behind the what – Understanding the binary representation and storage mechanism of each type allows you to control program behavior at the memory level
-
Boundary thinking – Every data type has its capability range; excellent programmers always consider edge cases
-
Precisely express intent – Choose the most appropriate type; too large wastes space, too small cannot hold your data
(Quiz: Can you explain why the result of int x = 2147483647 + 1; is undefined behavior? What does this indicate about topics we still need to explore?)
Feel free to share in the comments!
END
If you find this article helpful, click “Share”, “Like”, or “View”!