Skip to content

Instantly share code, notes, and snippets.

@louisswarren
Last active February 13, 2024 08:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save louisswarren/fc607e55e56e13fb4af88b53e9e6d0d8 to your computer and use it in GitHub Desktop.
Save louisswarren/fc607e55e56e13fb4af88b53e9e6d0d8 to your computer and use it in GitHub Desktop.
Type-checked units in C
--- units.asm 2023-06-18 12:02:32.313569952 +1200
+++ units_unsafe.asm 2023-06-18 12:02:32.313569952 +1200
@@ -1,7 +1,7 @@
-metres_from_feet(feet):
+metres_from_feet(double):
divsd xmm0, QWORD PTR .LC0[rip]
ret
-feet_from_metres(metres):
+feet_from_metres(double):
mulsd xmm0, QWORD PTR .LC0[rip]
ret
.LC3:
#include <stdio.h>
typedef struct {
double m;
} metres;
typedef struct {
double ft;
} feet;
metres
metres_from_feet(feet x)
{
const feet m_to_ft = {3.28084};
return (metres){x.ft / m_to_ft.ft};
}
feet
feet_from_metres(metres x)
{
const feet m_to_ft = {3.28084};
return (feet){x.m * m_to_ft.ft};
}
int
main(void)
{
metres h = {2.4};
printf("%lf metres = %lf feet\n", h.m, feet_from_metres(h).ft);
return 0;
}
#include <stdio.h>
#define define_unit(NAME, ABBREV, TYPE) typedef struct { TYPE ABBREV; } NAME
#define define_conversion(NAME_TO, NAME_FROM, VAR, ...) \
NAME_TO \
NAME_TO##_from_##NAME_FROM(NAME_FROM VAR) \
{ \
return (NAME_TO){ __VA_ARGS__ }; \
} \
struct NOOP
define_unit(metres, m, double);
define_unit(feet, ft, double);
define_conversion(metres, feet, x, x.ft / 3.28084);
define_conversion(feet, metres, x, x.m * 3.28084);
double
circumference(double radius)
{
return 2 * 3.14159 * radius;
}
int
main(void)
{
metres h = {2.4};
printf("%lf metres = %lf feet\n", h.m, feet_from_metres(h).ft);
metres c = {circumference(h.m)};
printf("A circle with radius %0.2lfm has circumference %0.2lfm\n",
h.m, c.m);
return 0;
}
#include <stdio.h>
double
metres_from_feet(double x)
{
const double m_to_ft = 3.28084;
return x / m_to_ft;
}
double
feet_from_metres(double x)
{
const double m_to_ft = {3.28084};
return x * m_to_ft;
}
int
main(void)
{
double h = 2.4;
printf("%lf metres = %lf feet\n", h, feet_from_metres(h));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment