145

Modern C? - ACCU

  • Upload
    others

  • View
    5

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Modern C? - ACCU
Page 2: Modern C? - ACCU

Modern C?

Page 3: Modern C? - ACCU

Modern C?- what if there is more to C than meets the eye?

Page 4: Modern C? - ACCU
Page 5: Modern C? - ACCU

Modern C?- what if there is more to C than meets the eye?

Page 6: Modern C? - ACCU

Modern C?- what if there is more to C than meets the eye?

- present a modern way in which C can be used and address misconceptions

Page 7: Modern C? - ACCU

Modern C?- what if there is more to C than meets the eye?

- present a modern way in which C can be used and address misconceptions

- explore how ideas inspired from C can improve our C++ code

Page 8: Modern C? - ACCU

Modern C?- what if there is more to C than meets the eye?

- present a modern way in which C can be used and address misconceptions

- explore how ideas inspired from C can improve our C++ code

- showcase how these ideas manifest in other languages, old and new

Page 9: Modern C? - ACCU

About me

Core Systems Engineer @ Creative Assembly

Game Development

Low Level Systems

Programming Language

BananyaDev#9587

@SasLuca

[email protected]@

Page 10: Modern C? - ACCU

A refresh on C

Page 11: Modern C? - ACCU

A refresh on C- Developed in 1972 (49 years ago)

Page 12: Modern C? - ACCU
Page 13: Modern C? - ACCU
Page 14: Modern C? - ACCU

A refresh on C- Developed in 1972 (49 years ago)

- Standardized by ANSI and later by ISO (ANSI C, C89, C99, C11, …)

Page 15: Modern C? - ACCU

A refresh on C- Developed in 1972 (49 years ago)

- Standardized by ANSI and later by ISO (ANSI C, C89, C99, C11, …)

- C does still have an active ISO committee (WG14)

Page 16: Modern C? - ACCU

A refresh on C

Page 17: Modern C? - ACCU

A refresh on C- Developed in 1972 (49 years ago)

- Standardized by ANSI and later by ISO (ANSI C, C89, C99, C11, …)

- C does still have an active ISO committee (WG14)

- What have we missed in the past 50 years and how is C different from C++?

Page 18: Modern C? - ACCU

Comments

Page 19: Modern C? - ACCU

Variables and structs

Page 20: Modern C? - ACCU

Variables and structs

Page 21: Modern C? - ACCU

Primitive types

Page 22: Modern C? - ACCU

Primitive types

Page 23: Modern C? - ACCU

Primitive types

Page 24: Modern C? - ACCU

Functions

Page 25: Modern C? - ACCU

Functions

Page 26: Modern C? - ACCU

C++ is not C- C++ is not fully compatible with C

Page 27: Modern C? - ACCU

C++ is not C- C++ is not fully compatible with C- They are compatible enough that C headers will mostly work in C++

Page 28: Modern C? - ACCU

C++ is not C- C++ is not fully compatible with C

- They are compatible enough that C headers will mostly work in C++

- C++ did inherit a lot of baggage from this attempted compatibility with C

Page 29: Modern C? - ACCU

What else is different between C and C++?

Page 30: Modern C? - ACCU

Struct initialization

Page 31: Modern C? - ACCU

Struct initialization- Unlike C++, structs in C are just plain old bags of data (PODs)

Page 32: Modern C? - ACCU

Struct initialization- Unlike C++, structs in C are just plain old bags of data (PODs)

- C99 introduces a new and powerful form of struct initialization

Page 33: Modern C? - ACCU

Struct initialization

Page 34: Modern C? - ACCU

Struct initialization

Page 35: Modern C? - ACCU

Struct initialization

Page 36: Modern C? - ACCU

Struct initialization

Page 37: Modern C? - ACCU

Struct initialization

Page 38: Modern C? - ACCU

Struct initialization

Page 39: Modern C? - ACCU

Struct initialization

Page 40: Modern C? - ACCU

Struct initialization

Page 41: Modern C? - ACCU

Struct initialization

Page 42: Modern C? - ACCU

Struct initialization

Page 43: Modern C? - ACCU

Struct initialization

Page 44: Modern C? - ACCU

Struct initialization- Unlike C++, structs in C are just plain old bags of data (PODs)

- C99 introduces a new and powerful form of struct initialization

- We can easily initialize complex data structures with nested initializers

Page 45: Modern C? - ACCU

Struct initialization- Unlike C++, structs in C are just plain old bags of data (PODs)

- C99 introduces a new and powerful form of struct initialization

- We can easily initialize complex data structures with nested initializers

- Everything we don’t explicitly initialize gets set to 0 (ZII)

Page 46: Modern C? - ACCU

Struct initialization- Unlike C++, structs in C are just plain old bags of data (PODs)

- C99 introduces a new and powerful form of struct initialization

- We can easily initialize complex data structures with nested initializers

- Everything we don’t explicitly initialize gets set to 0 (ZII)

- This is one of the features that lead to Modern C

Page 47: Modern C? - ACCU

Struct initialization: sokol gfx

Page 48: Modern C? - ACCU

Modern C- Challenging the way APIs have historically been structured in C

- Using newer features of C in order to improve the ease of use and safety of the API

- Decoupling the data manipulations from hosted services (allocators, io)

- Centralizing resource management (custom allocators, system-wide resource managers)

- Let’s explore some other features and then more examples

Page 49: Modern C? - ACCU

C11 Additions- The latest major version

Page 50: Modern C? - ACCU

C11 Additions- The latest major version

- As of recent it is now supported by all major compilers including MSVC

Page 51: Modern C? - ACCU

C11 Additions: static assert

Page 52: Modern C? - ACCU

C11 Additions: _Generic and overloading

Page 53: Modern C? - ACCU

C11 Additions- The latest major version

- As of recent it is now supported by all major compilers including MSVC

- static_assert

- overloading

- atomics (available in older versions with libraries like c89atomics)

- thread_local (available via compiler extensions in C99)

Page 54: Modern C? - ACCU

Awesome Macros

Page 55: Modern C? - ACCU

Awesome Macros- Macros CAN be evil!

Page 56: Modern C? - ACCU

Awesome Macros- Macros CAN be evil!

- There are some cases in which they can make our life much nicer.

Page 57: Modern C? - ACCU

Awesome Macros: defer

Page 58: Modern C? - ACCU

Awesome Macros: defer

Page 59: Modern C? - ACCU

Awesome Macros: defer

Page 60: Modern C? - ACCU

Awesome Macros: defer

Page 61: Modern C? - ACCU

Awesome Macros: defer

Page 62: Modern C? - ACCU

Awesome Macros: defer

Page 63: Modern C? - ACCU

API Design

Page 64: Modern C? - ACCU

API Design: Math

Page 65: Modern C? - ACCU

API Design: Math

- Out params are harder to spot at the call site

Page 66: Modern C? - ACCU

API Design: Math

- Out params are harder to spot at the call site- There are indirection and aliasing issues caused by the pointers which can harm performance

Page 67: Modern C? - ACCU

API Design: Math in Modern C

- value oriented design

Page 68: Modern C? - ACCU

API Design: Math in Modern C

- value oriented design- we can use literals in the function call and readability is improved

Page 69: Modern C? - ACCU

API Design: Math in Modern C

- value oriented design- we can use literals in the function call and readability is improved- performance is actually better

Page 70: Modern C? - ACCU

API Design: Math in Modern C

Page 71: Modern C? - ACCU

API Design: Error handling

Page 72: Modern C? - ACCU

API Design: Error handling

Page 73: Modern C? - ACCU

API Design: Error handling

Page 74: Modern C? - ACCU

API Design: Error handling

Page 75: Modern C? - ACCU

API Design: Error handling in Modern C

Page 76: Modern C? - ACCU

Error handling in Modern C

Page 77: Modern C? - ACCU

Error handling in Modern C

Page 78: Modern C? - ACCU

Error handling in Modern C

Page 79: Modern C? - ACCU

Error handling in C++ with optional

Page 80: Modern C? - ACCU

Error handling in Modern C

Page 81: Modern C? - ACCU

Error handling in Modern C

Page 82: Modern C? - ACCU

Error handling in Modern C

Page 83: Modern C? - ACCU

Error handling: std::expected

Page 84: Modern C? - ACCU

Error handling in Rust

Page 85: Modern C? - ACCU

Error handling in Zig

Page 86: Modern C? - ACCU

Error handling in C++

Page 87: Modern C? - ACCU

Generic APIs in C- C lacks generic programming (eg: templates)

Page 88: Modern C? - ACCU

Generic APIs in C- C lacks generic programming (eg: templates).

- C can also force us to think outside the box and not rely excessively on templates.

Page 89: Modern C? - ACCU

Generic APIs in C- C lacks generic programming (eg: templates).

- C can also force us to think outside the box and not rely excessively on templates.

- There do exist some solutions for some very common use cases.

Page 90: Modern C? - ACCU

Generic APIs in C: Dynamic Arrays

Page 91: Modern C? - ACCU

Generic APIs in C: Dynamic Arrays

Page 92: Modern C? - ACCU

Generic APIs in C: Dynamic Arrays

Page 93: Modern C? - ACCU

Generic APIs in C: Dynamic Arrays

Page 94: Modern C? - ACCU

Generic APIs in C: Map

https://github.com/nothings/stb/blob/master/stb_ds.h

Page 95: Modern C? - ACCU

Libraries in C- Historically messy due to the multitude of build systems and no standard.

Page 96: Modern C? - ACCU

Libraries in C- Historically messy due to the multitude of build systems and no standard.

- Single header libraries arise as a convenient way to solve this problem.

Page 97: Modern C? - ACCU

Libraries in C- Historically messy due to the multitude of build systems and no standard.

- Single header libraries arise as a convenient way to solve this problem.

Page 98: Modern C? - ACCU

Libraries in C- Historically messy due to the multitude of build systems and no standard.

- Single header libraries arise as a convenient way to solve this problem.

- Sane CMake is another good option. Single headers can optionally be auto-generated.

Page 99: Modern C? - ACCU

Great talk on Cmake

Page 100: Modern C? - ACCU

Libraries in newer languages- Newer langs improve significantly on the library situation.

- Rust has a very well received easy to use build system and centralized database for libraries.

- Zig takes a unique approach by having the build system be part of the language.

Page 101: Modern C? - ACCU

When writing libraries● Avoid allocations if possible, request allocators or buffers from

the user.

Page 102: Modern C? - ACCU

When writing libraries● Avoid allocations if possible, request allocators or buffers from

the user.

● Try and make your library freehosted.

Page 103: Modern C? - ACCU

When writing libraries● Avoid allocations if possible, request allocators or buffers from

the user.

● Try and make your library freehosted.

Page 104: Modern C? - ACCU

Memory management● Consider centralizing allocations.

● Differentiate between temporary and long lived allocations.

● Use buffers with maximum sizes where possible.

● Consider handles instead of pointers (eg: ECS)

Page 105: Modern C? - ACCU

Temporary allocators

Page 106: Modern C? - ACCU

API Design: Modern C- More declarative and functional, less stateful

- More value oriented and less pointers

- Zero initialization is used heavily (ZII)

- Uses C99 and C11 features and macros to modernize the code

- Centralized resource management

- Allocator aware

Page 107: Modern C? - ACCU

String handling in C- Strings in C have been a historical disaster

Page 108: Modern C? - ACCU

String handling in C- Strings in C have been a historical disaster

- Terrible standard API (strstr, strtok, strpbrk)

Page 109: Modern C? - ACCU

Public service announcement: avoid libc- Very old

- Slow

- Terrible API design

- Very few parts are actually useful (stdint.h, memmove/memcpy/memset, math.h)

Page 110: Modern C? - ACCU

Replacing libc functionality: printf

Page 111: Modern C? - ACCU

String handling in C- Strings in C have been a historical disaster

- Terrible standard API (strstr, strtok, strpbrk)

- Null terminated strings are very slow

Page 112: Modern C? - ACCU
Page 113: Modern C? - ACCU
Page 114: Modern C? - ACCU

It’s not just null terminated strings

Page 115: Modern C? - ACCU

Case study: std::string

Intent: reading an array of bytes representing text

Page 116: Modern C? - ACCU

Case study: std::string

Page 117: Modern C? - ACCU

Case study: std::string

This causes a memory allocation.

Page 118: Modern C? - ACCU

What’s the problem with a few couple of temporary strings here and there?

Page 119: Modern C? - ACCU

Real life examples:Chrome

● Half of all allocations are std::string.

Page 120: Modern C? - ACCU

Real life examples:Chrome

● Half of all allocations are std::string.

● Typing one character in the Omnibox used to result in over 25000 allocations.

Page 122: Modern C? - ACCU

Real life examples:Chrome

● Half of all allocations are std::string.

● Typing one character in the Omnibox used to result in over 25000 allocations.

● Performance issues resulted from lot’s of copies and temporary objects.

Page 123: Modern C? - ACCU

String handling in Modern C

● No implicit conversions and constructors.

Page 124: Modern C? - ACCU

String handling in Modern C

● No implicit conversions and constructors.

● Stronger distinction between owning and non-owning strings.

Page 125: Modern C? - ACCU

String handling in Modern C

Page 126: Modern C? - ACCU

String handling in Modern C

Page 127: Modern C? - ACCU

String handling in Modern C

Page 128: Modern C? - ACCU

String handling in Modern C

Page 129: Modern C? - ACCU

String handling in Modern C

Page 130: Modern C? - ACCU

String handling in Old C

Page 131: Modern C? - ACCU

String handling in Old C

Page 132: Modern C? - ACCU

String handling in Modern C

Page 133: Modern C? - ACCU

String handling in Modern C: overloading

Page 134: Modern C? - ACCU

String handling in Modern C: overloading

Page 135: Modern C? - ACCU

String handling in Modern C: another awesome macro

Page 136: Modern C? - ACCU

● First ever optimization I did at Creative Assembly was related to string operations.

First optimization at CA

Page 137: Modern C? - ACCU

● First ever optimization I did at Creative Assembly was related to string operations.

● A seemingly cheap function was splitting some string.

First optimization at CA

Page 138: Modern C? - ACCU

● First ever optimization I did at Creative Assembly was related to string operations.

● A seemingly cheap function was splitting some string.

● The function didn’t seem to take much time unless you analyzed its cost cumulatively.

First optimization at CA

Page 139: Modern C? - ACCU

● First ever optimization I did at Creative Assembly was related to string operations.

● A seemingly cheap function was splitting some string.

● The function didn’t seem to take much time unless you analyzed its cost cumulatively.

● The solution was to move to a non-allocating, lazily evaluated string splitter using std::string_view.

First optimization at CA

Page 140: Modern C? - ACCU

String handling in other languages

● Rust has a built-in str type which is different from the owning String class.

● Zig and Odin have built-in array-view types and string-view manipulation functions.

● Java and C# also follow a similar model.

● Consider starting to use std::string_view instead of const std::string& in C++.

● C++17 added std::string_view.

● C++20 ranges will make lazy non-allocating algorithms more easy to use.

Page 141: Modern C? - ACCU

In conclusion

● I hope that you gained a better appreciation for what can be done in a limited language like C.

Page 142: Modern C? - ACCU

In conclusion

● I hope that you gained a better appreciation for what can be done in a limited language like C.

● Checkout the latest developments in C++ and other systems languages.

Page 143: Modern C? - ACCU

In conclusion

● I hope that you gained a better appreciation for what can be done in a limited language like C.

● Checkout the latest developments in C, C++ and also other systems languages.

● Re-examine some of the patterns and preconceptions that you may hold.

Page 144: Modern C? - ACCU

In conclusion

● I hope that you gained a better appreciation for what can be done in a limited language like C.

● Checkout the latest developments in C, C++ and also other systems languages.

● Re-examine some of the patterns and preconceptions that you may hold.

● By challenging our current understanding and not taking things for granted we can discover new and better ways of doing things.

Page 145: Modern C? - ACCU

Shoutouts

Modern C for C++ Peeps: https://floooh.github.io/2019/09/27/modern-c-for-cpp-peeps.html

Odin: https://odin-lang.org/

Zig: https://ziglang.org/

Handmade Hero: https://handmadehero.org/

Handmade Network: https://handmade.network/