fork download
  1. #include <stdio.h>
  2.  
  3. // эти структуры заводят внутри компилятора новые типы, которые не совместимы с
  4. // другими типами, а главное - друг с другом
  5. struct meters {
  6. int meter;
  7. };
  8.  
  9. struct centimeters {
  10. int centimeter;
  11. };
  12.  
  13. // это плохая функция, потому что в ней нет никакой информации о типах, и очень
  14. // сложно сказать есть ли в ней какая-нибудь ошибка
  15. // конечно, в реальности она будет принимать int m, int cm, но это всё равно
  16. // довольно сложно заметить
  17. int add_distances_bad( int a, int b ) {
  18. return a + b;
  19. }
  20.  
  21. struct centimeters add_distances_good( struct meters a, struct centimeters b ) {
  22. // return a + b; // вот это просто не скомпилируется, потому что со
  23. // структурами так делать нельзя
  24.  
  25. // это всё ещё неправильно, но такой код написать сложнее, и если он-таки
  26. // написан, то при прочтении легко заметить, что что-то тут не так, ибо
  27. // метры складываются с сантиметрами
  28. //получается эдакий гибрид фантомных типов с венгерской нотацией, которая
  29. // кое-как проверяется компилятором
  30. return (struct centimeters) { a.meter + b.centimeter };
  31. }
  32.  
  33. struct meters mk_meters( int a ) {
  34. return (struct meters){ a };
  35. }
  36.  
  37. struct centimeters mk_centimeters( int a ) {
  38. return (struct centimeters){ a };
  39. }
  40. /*
  41. Сами структуры исчезнут после компиляции, даже если оптимизация выключена.
  42. С -О3 от них не останется и следа.
  43. Потому что "механически" они полностью эквивалентны обычному инту.
  44. */
  45. int main(void) {
  46. struct meters m = mk_meters( 10 );
  47. struct centimeters cm = mk_centimeters( 55 );
  48. struct centimeters result1 = add_distances_good( m, cm );
  49. int result2 = add_distances_bad( 10, 55 );
  50. printf( "distances are %d and %d\n", result1.centimeter, result2 );
  51. return 0;
  52. }
  53.  
Success #stdin #stdout 0s 9424KB
stdin
Standard input is empty
stdout
distances are 65 and 65