Number types and operations
Integer types: signed and unsigned, ranges
signed:
-2^(n-1)…2^(n-1) - 1unsigned:
0…2^n - 1
main.c#include <stdio.h>
void sizes() {
printf("%ld\n", sizeof(char));
printf("%ld\n", sizeof(int)); // short int
printf("%ld\n", sizeof(short));
printf("%ld\n", sizeof(long));
printf("%ld\n", sizeof(long long));
printf("%ld\n", sizeof(float));
printf("%ld\n", sizeof(double));
}
void signs() {
printf("%ld\n", sizeof(char));
printf("%ld\n", sizeof(signed char));
printf("%ld\n", sizeof(unsigned char));
}
void range() {
typedef char int_type;
// typedef signed char int_type;
// typedef unsigned char int_type;
// typedef short int_type;
// ...
int_type min, max;
{
int_type n = 0;
for (;;) {
int_type next = n - 1;
if (next >= n) {
min = n;
break;
}
n = next;
}
}
{
int_type n = 0;
for (;;) {
int_type next = n + 1;
if (next <= n) {
max = n;
break;
}
n = next;
}
}
printf("range: %d - %d\n", min, max);
}
#include <limits.h>
void limits() {
printf("char: %d - %d\n", CHAR_MIN, CHAR_MAX);
printf("schar: %d - %d\n", SCHAR_MIN, SCHAR_MAX);
printf("uchar: %d - %d\n", 0, UCHAR_MAX);
printf("short: %d - %d\n", SHRT_MIN, SHRT_MAX);
}
#include <stdint.h>
void fixed_limits() {
int64_t i = INT64_MIN;
printf("int64_t: %ld - %ld\n", i, INT64_MAX);
}
int main() {
sizes();
// signs();
// range();
// limits();
// fixed_limits();
return 0;
}
Floating-point types
Conversion:
main.c#include <limits.h>
#include <stdio.h>
/* 2's complement */
int const MAXINT_DEC = 2147483647;
int const MAXINT_HEX = 0x7FFFFFFF;
// typedef unsigned int uint;
int main() {
printf("%d\n", MAXINT_DEC == INT_MAX);
printf("%d\n", MAXINT_HEX == INT_MAX);
int i = MAXINT_DEC;
printf("%d\n", i);
printf("%d\n", i + 1);
printf("%u\n", (unsigned int) i);
printf("%u\n", (unsigned int) i + 1);
printf("%u\n", i);
printf("%u\n", i + 1);
unsigned int ui = (unsigned int) i;
float f = i;
printf("%f\n", i);
printf("%f\n", (float) i);
printf("%f\n", f);
printf("%f\n", (float) (i + 1));
printf("%f\n", (float) (ui + 1));
return 0;
}
Range and precision:
float.c#include <float.h>
#include <stdio.h>
int main() {
// precision: ~ 6 decimal digits
// range: ~ +/- 1.2e-38 .. 3.4e38
printf("%ld\n", sizeof(float));
// printf("%f %f %d\n", FLT_MIN, FLT_MAX, FLT_DIG);
// printf("%g %g %d\n", FLT_MIN, FLT_MAX, FLT_DIG);
// precision: ~ 15 decimal digits
// range: ~ +/- 2.2e-308 .. 1.8e308
printf("%ld\n", sizeof(double));
// printf("%g %g %d\n", DBL_MIN, DBL_MAX, DBL_DIG);
// precision is platform-dependent: 64/80/128 bits?
// 128 bits: quad-precision
// precision: ~ 18 decimal digits
// range: ~ +/- 3.4e-4932 .. 1.2e4932
printf("%ld\n", sizeof(long double));
// printf("%Lg %Lg %d\n", LDBL_MIN, LDBL_MAX, LDBL_DIG);
return 0;
}
Pitfalls:
pitfall.c#include <stdio.h>
#include <limits.h>
#include <float.h>
int main() {
printf("int bits:\t%lu\n", sizeof(int) * CHAR_BIT);
printf("flt radix:\t%u\n", FLT_RADIX);
printf("flt mant bits:\t%u\n", FLT_MANT_DIG);
int cases = 0;
for(int i = 0; i < INT_MAX; ++i) {
float f = i;
int i2 = f;
if (i != i2) {
printf("%d != %g (%d)\n", i, f, i2);
++cases;
if (10 <= cases)
break;
}
}
return 0;
}