Modern C and What We Can Learn From It - Luca Sas [ ACCU 2021 ]

แชร์
ฝัง
  • เผยแพร่เมื่อ 28 ก.ย. 2024
  • #Programming #Cpp #AccuConf
    Slides: accu.org/conf-...
    ACCU Website: www.accu.org
    ACCU Conference Website: conference.acc...
    ACCU Twitter: @ACCUConf
    Streamed & Edited By Digital Medium Ltd: events.digital...
    ------
    C is often perceived as an antiquated language that is mostly used for legacy purposes, but many people still prefer coding in C or in a subset of C++ that is very close to C. This is sometimes labeled "Modern C" and the ideas behind it are becoming more popular alongside other paradigms such as Data Oriented Design (DOD), Zero Is Initialization (ZII) and Centralized Memory Management (CMM). In fact, many new systems programming languages, such as Rust, Go and Zig, also embody a lot of similar ideas as Modern C showcasing a high degree of interest in these paradigms. In this talk we will explore how programming looks like with this different approach to C and how it addresses matters such as API design, error handling and resource management as well as what are the benefits and costs of these techniques. By the end we will gain a better understanding of how these ideas can help improve the quality of our code, what new languages have adopted similar concepts and to what extent, and what lessons we can learn from this in order to improve our own existing codebases and styles of coding.
    ------
    Luca Sas
    Luca Sas is a Core Systems Engineer at Creative Assembly who has been coding for almost a decade and is passionate about system architecture and low level programming. Some of his previous work includes mobile apps with some of the biggest NGOs in Romania and video game development. In Romania he was a national champion at programming contests and olympiads where he is now a judge. He enjoys attending conferences and talking to developers about their experience and learning about ways to improve software design as well as mentoring new programmers and giving talks. Previously he gave talks at programming events in Romania and the University of Leeds, and ACCU 2019.
    ------
    Future Conferences:
    ACCU 2022 Spring Conference, Bristol (UK), Marriott City Centre:
    2022-04-05 to 2022-04-09.
    -------------------------

ความคิดเห็น • 229

  • @dengan699
    @dengan699 3 ปีที่แล้ว +155

    2:07 A refresh on C
    4:04 Comments
    4:18 Variables and structs
    5:02 Primitive types
    6:18 Functions
    7:28 C++ is not C
    8:11 Struct initialization
    12:16 Struct initialization: sokol gfx
    13:52 Modern C
    14:54 C11 Additions
    15:18 C11 Additions: static asserts
    15:40 C11 Additions: _Generic and overloading
    16:30 C11 Additions (cont)
    17:06 Awesome macros
    17:32 Awesome macros: defer
    20:20 API Design: Math
    21:18 API Design: Math in Modern C
    23:18 API Design: Error handling
    24:15 API Design: Error handling in Modern C
    30:33 Generic APIs in C
    31:40 Generic APIs in C: Dynamic Arrays
    33:56 Generic APIs in C: Map
    34:24 Libraries in C
    37:06 When writing libraries
    38:30 Memory Management
    40:14 Temporary allocators
    41:31 API Design: Modern C
    42:15 String handling in C
    42:54 Avoid libc
    43:30 Replacing libc functionnality: printf
    46:30 Case study: std::string
    49:10 String handling in Modern C
    51:50 String handling in Old C
    53:40 String handling in Modern C (cont)
    54:35 String handling in Modern C: another awesome macro (iterator)
    55:41 First optimization at CA
    58:40 Conclusion

    • @think-biq
      @think-biq 2 ปีที่แล้ว +2

      Thanks for taking the time and creating timestamps for this talk, very useful.

  • @franzflasch8181
    @franzflasch8181 2 ปีที่แล้ว +13

    People often argue that writing C code is quite dangerous because of buffer overflows and memory leaks, however there are tools which can help to detect the majority of those problems e.g. valgrind. I'll never go back writing a C program without valgrind.

    • @alefratat4018
      @alefratat4018 2 ปีที่แล้ว

      Completely agree, and that is true for C++ as well.

    • @ABaumstumpf
      @ABaumstumpf ปีที่แล้ว

      As if there is any need to use unprotected manually managed buffers - there are so many good libraries out there and even just writing a simple wrapper-struct takes only a few minutes. You only use the lowest level stuff when you either have no clue or when you really need it (tight memory constraints, high performance, low latency - that kinda stuff).

    • @ryonagana
      @ryonagana 6 หลายเดือนก่อน

      -fsanitize=address with -lasan helps telling where in the code has corrupted stack
      and debugging core dumps

    • @MikAlexander
      @MikAlexander 18 วันที่ผ่านมา

      if ( x != NULL) {}; There you go.

  • @TheSulross
    @TheSulross 2 ปีที่แล้ว +4

    one of the most useful talks on programming given in recent times

  • @johndoe1909
    @johndoe1909 2 ปีที่แล้ว +6

    c is still one of the best languages around. it simple, incredible powerrfull and the fastest language there is. i have prigrammed hava since ot was called oak and now a bit c# and alm the others but c is still king. if you want to write code for a nuclear powerplabt, space probe or the kernel for your phone, c is the labguage to use.

  • @GordonKindlmann
    @GordonKindlmann 3 ปีที่แล้ว +11

    (at 43:19) math.h is not for libc, it's for libm ! And with tgmath.h, the math library is effectively generic (over long double, double, and float), which is *AWESOME*, and I think also part of modern C. But point taken that libc has issues.

  • @multicoloredwiz
    @multicoloredwiz 3 ปีที่แล้ว +7

    the presenters string library looks heavenly to work with lol!

  • @openmarkand
    @openmarkand 2 ปีที่แล้ว +5

    - 8:45 C++ has designated initializers now and yes you can initialize structs using "uniform initialization" as well.
    - 48:00 thankfully we have std::string_view now to avoid allocation hell.

    • @alefratat4018
      @alefratat4018 2 ปีที่แล้ว +2

      std::string_view only in C++17 though, still not supported by a lot of embedded systems toolchains.

    • @IsaacKripke
      @IsaacKripke ปีที่แล้ว

      @@alefratat4018 then use something like ETL (Embedded Template Library)? It only requires C++03 and implements its own alternatives to std::string and std::string_view

  • @diceandbricks
    @diceandbricks 3 ปีที่แล้ว +14

    defer macro is cool. However, unlike Go, it will not call the end function if you have an early return, break, or longjmp inside the block.

    • @babgab
      @babgab 3 ปีที่แล้ว +2

      My impression is that many C programmers are borderline dogmatic about not using early returns, specifically because it makes the cleanup simpler without RAII.

    • @diceandbricks
      @diceandbricks 3 ปีที่แล้ว +2

      Many are, yes. Some C style guides require it. Not everyone, though. In some circumstances, I find early returns dramatically clean up the code and avoid deeply nested if blocks.

    • @mettemafiamutter5384
      @mettemafiamutter5384 3 ปีที่แล้ว +4

      There is a proposal to add PROPER defer to C. I'm not sure if a pure library implementation is possible. Google "A defer mechanism for C" (can't post links).

    • @diceandbricks
      @diceandbricks 3 ปีที่แล้ว

      @@mettemafiamutter5384 That could be pretty nice. Thanks for the tip.

    • @kuhluhOG
      @kuhluhOG 2 ปีที่แล้ว

      @@mettemafiamutter5384 to my knowledge C already has something similar, although it only accepts function pointers with void return and no parameters

  • @Little-bird-told-me
    @Little-bird-told-me 8 หลายเดือนก่อน

    As someone who is starting to learn C for the first time, this talk is very useful

  • @jonathanmoore5619
    @jonathanmoore5619 ปีที่แล้ว +2

    Me. I love C. Nothing better.

  • @adanjsuarez
    @adanjsuarez 2 ปีที่แล้ว +2

    Pretty nice talk! Thanks and we need more of this.

    • @ACCUConf
      @ACCUConf  2 ปีที่แล้ว

      Thank you for your comment!

  • @slmjkdbtl
    @slmjkdbtl 3 ปีที่แล้ว +11

    "prefer value to pointer" wow that's kinda new to me, wouldn't it be expensive if the value is big? i usually would not pass by value if the value size exceeds a pointer size

    • @grafgrantula6100
      @grafgrantula6100 3 ปีที่แล้ว +1

      Yeah, I'm also puzzled by that. I think of it like this until I find out how it really works:
      If it's reasonable to assume this struct can be stored in CPU registers, pass it by value.
      So my uneducated guess is you could safely pass around 9 values of 32 bit size, probably more.
      No idea what kind of hell breaks loose if you pass something really big, like contents of an image file by value. I expect nightmares.

    • @kuhluhOG
      @kuhluhOG 3 ปีที่แล้ว +3

      It only really starts to become expensive if sizeof(type) > sizeof(void*) * 2 (and on some platforms up to 4).
      The C++ standard library does a lot of passing by value (when this is the case) and it's not known that it's slow.

    • @martinkunev9911
      @martinkunev9911 3 ปีที่แล้ว +1

      @Vironacorus For the aliasing issues, you can use restrict (but I get your point).

    • @alice_in_wonderland42
      @alice_in_wonderland42 2 ปีที่แล้ว

      @@grafgrantula6100 contents of something like image data will be stored in an array. And the array var will only contain the pointer(will decay to it when passed).
      So I don't see How is this even remotely possible.
      It may be possible if u use thousands of ints in a struct for doing that but why would anyone do that.

    • @ABaumstumpf
      @ABaumstumpf ปีที่แล้ว +1

      It depends. If you have a good code-structure than the compiler will see what you are doing and optimise accordingly.
      Say you are passing in a large struct by value, inside the function you are manipulating this local copy and then returning it, and at the calling-side you are not ever touching the original struct ever again: The compiler might very well re-use the old struct and never even create a copy.

  • @illoominate
    @illoominate ปีที่แล้ว +1

    I've been programming in C since 1980, but I was not aware of the spectacular things you can do with struct and union initializers. This is an excellent video, thanks!

    • @ACCUConf
      @ACCUConf  ปีที่แล้ว

      Thank you for your comment which is much appreciated.

  • @andreffrosa
    @andreffrosa 8 หลายเดือนก่อน

    C has remained my favorite language. It is very simple (i.e. not bloated) yet powerful and at the same time very pleasing to program (except string handling). Modern languages that try to be the new C/C++, like go, zig, and rust, don't capture the joyfullness of programing that C does and introduce a lot o friction and other quircks to use. I wish I could find a job using C.

  • @sriramsrinivasan2769
    @sriramsrinivasan2769 3 ปีที่แล้ว +2

    Lovely talk. defer and passing structs by value are really nice.

  • @spinthma
    @spinthma 3 ปีที่แล้ว +6

    Super Cool, thanks a lot!

  • @animalibera4326
    @animalibera4326 3 ปีที่แล้ว +2

    So good uwu
    Note: Rust's error handling is also very built-in, the try keyword of Zig is the ? unary operator in Rust ^^

  • @rohandvivedi
    @rohandvivedi 2 ปีที่แล้ว +1

    Thanks, this talk was of great help. I learned a few new tricks.

    • @ACCUConf
      @ACCUConf  2 ปีที่แล้ว

      Great to hear!

  • @aaronfleisher4694
    @aaronfleisher4694 23 วันที่ผ่านมา +1

    I am confused as to why the null terminator, simply one more character, should cause problems. It seems, rather, that problems arise from the tendency to allocate space on the heap for strings, make unnecessary copies, use pointers larger than size of the character type, and treating strings like variable length arrays. I would appreciate it if someone would explain why the null terminator causes problems.

  • @MissNorington
    @MissNorington 2 ปีที่แล้ว +4

    I only use(ed) C for speed. When I see something like "Everything else gets set to 0" in struct initialization, I am thinking about more safe languages (scripting languages) that do things to protect you as a programmer and not trust the programmer with the data types. At least we know the C compiler will use the most efficient way to initialize all members to 0.... hopefully.

    • @tullochgorum6323
      @tullochgorum6323 11 หลายเดือนก่อน +4

      Scripting languages may protect your memory, but as soon as your project reaches a non-trivial size, you don't get much help with your types. The older I get, the more I appreciate static analysis. Maybe it's just incipient dementia, but the compiler does catch a lot of bugs for me these days...

  • @alexandermitrokhin3996
    @alexandermitrokhin3996 2 ปีที่แล้ว +1

    The _Generic() example is not a good one. Try adding a string comparison function char *mins(char *a, char *b) and see how things break. A better option would be:
    #define min(a, b) _Generic((a), float: minf, int: mini, char *: mins)(a, b)

  • @theondono
    @theondono 2 ปีที่แล้ว +6

    Great talk, very good presentation, but PLEASE don't code C like this.
    Pretty much none of the macros presented were safe macros, and I'm pretty sure I've seen a bug around. There's no need to use heavy macros like that, at this day an age compilers are sophisticated enough that using functions for this kind of stuff has zero overhead because it will auto inline them.
    In fact its like that by changing to functions with the use of 'restrict' you might even get a boost, because right now the compiler has no guarantees w.r.t. aliasing.

  • @abhisohal4556
    @abhisohal4556 ปีที่แล้ว

    Excellent talk. changed my view of the c language.

  • @Hoowwwww
    @Hoowwwww 3 ปีที่แล้ว +3

    modules, it is the reason why i gave up with C and C++ and moved to D
    i just don't want to deal with headers / predeclaration etc etc, this is such a pain that wastes me so much precious time

    • @Hoowwwww
      @Hoowwwww 3 ปีที่แล้ว +1

      i want some sort of modules in modern C, otherwise it'll always feel bad..

    • @alice_in_wonderland42
      @alice_in_wonderland42 2 ปีที่แล้ว

      @@Hoowwwww there is a similar project by Jens Guesdt(he's on the ISO C board, co author of C11 standard), just search it.

  • @uonliaquat7957
    @uonliaquat7957 ปีที่แล้ว +1

    Such an information video. I just wanted to know that from where did you learn these C language techniques. Is there any book available?

  • @dimitrioskalfakis
    @dimitrioskalfakis ปีที่แล้ว

    satisfying and sound assessment as well as interesting new features.

  • @PaulJurczak
    @PaulJurczak 3 ปีที่แล้ว +5

    Great talk! I wonder why you declare structure types as:
    typedef struct kv {...} kv;
    instead of a simple:
    struct kv {...};

    • @SasLuca
      @SasLuca 3 ปีที่แล้ว +4

      in C if you dont use typedef like that you have to annotate the typename with the keyword struct everywhere, eg:
      struct foo {};
      void bar(struct foo f);
      vs
      typedef struct foo {} foo;
      void bar(foo f);

    • @kenberkely7223
      @kenberkely7223 3 ปีที่แล้ว

      So you don’t have to type out struct every time

    • @CzipperzIncorporated
      @CzipperzIncorporated 3 ปีที่แล้ว

      It allows you to not have to write "struct kv" everywhere

    • @totorotux3708
      @totorotux3708 3 ปีที่แล้ว

      so that we don't have to write struct every time we make a variable or pointer for struct kv, like kv *newvar; instad of struct kv *newvar;

    • @tomibomi4465
      @tomibomi4465 3 ปีที่แล้ว

      Hello, just struct kv {...}; won't compile in C :(

  • @porky1118
    @porky1118 ปีที่แล้ว +1

    31:47 "vector" is a bad name for a dynamically sized array.
    I already have a lot of vector types in all my math libraries:
    - hardware vector types for efficient math on multiple values at once
    - linear algebra (vectors are just 1×n matrices)
    - geometric algebra (vectors are just 1D multi vectors)

  • @baardi2
    @baardi2 3 ปีที่แล้ว +1

    47:05: It most likely doesn't allocate due to small buffer optimization

  • @temdisponivel
    @temdisponivel 3 ปีที่แล้ว +6

    Good stuff

    • @ACCUConf
      @ACCUConf  3 ปีที่แล้ว +3

      Glad you enjoyed

  • @szaszm_
    @szaszm_ 2 ปีที่แล้ว +2

    9:00 wrong, you CAN do it in C++. Search for "Designated initializers" on the "Aggregate initialization" page of cppreference.

  • @thomasaguest
    @thomasaguest 3 ปีที่แล้ว +1

    excellent talk thanks

  • @digitalzoul57
    @digitalzoul57 10 หลายเดือนก่อน

    Just the function overloading using _Generic is not that stable as in c++

  • @MDarkus3
    @MDarkus3 ปีที่แล้ว

    This idea of value oriented design is interesting. But for the embedded world on MCU, where C is still the main goto lang, it is not a good option where memory is so limited you dont want to pass cpy arguments.
    Btw thank you for this great presentation, I learn new ideas of API design notably on strings handling and error handling. I must admit I was a big user of goto err; syntaxe. Maybe I will re-consider this.
    Also I will dive into Zig, it looks promising... having error and build system built-in in the lang!

    • @michaelclift6849
      @michaelclift6849 11 หลายเดือนก่อน

      The value oriented design works well for the str (pointer+size pair), but not the holding buffer.

  • @SerjCrimea
    @SerjCrimea 10 หลายเดือนก่อน

    Developing in Code Blocks(2020) specifying the C99 standard to the compiler, it still forces struct to be written in the code:(
    In which development environment are these innovations implemented?

  • @MsDuketown
    @MsDuketown 2 ปีที่แล้ว

    I always miss ASM and compilers. Should be mandatory in any language discussion. Remember, compiling isn't interpreting. I prefer approaching language from how these machines handle strings, like gnu readline.

  • @stelluspereira
    @stelluspereira 9 หลายเดือนก่อน

    Very informative Thankyou
    What will be a good GUI library which works in MacOs & Windows & Linux for C
    Since you are a game developer you must be experienced & familiar with GUI libs (std applications development,Not Game) let us say something similar ‘look and feel’ Of Visual Studio Code IDE

  • @ingframin
    @ingframin 2 ปีที่แล้ว

    I did not understand how the defer macro works 😞

  • @porky1118
    @porky1118 ปีที่แล้ว

    You forgot to mention Scopes here.

  • @NymezWoW
    @NymezWoW 3 ปีที่แล้ว +4

    C++ has C-Style struct initialization since C++20. What you are saying is not true anymore.

    • @alice_in_wonderland42
      @alice_in_wonderland42 2 ปีที่แล้ว +4

      False
      C++20 designated initializers are very limited
      By that u can only do union
      And non nested struct initialization and fields in the initializer should be in same order as they were in the struct data type
      So u cannot initialize arrays using that
      U cannot initialization nested structs
      U cannot use any order of fields in that initializer
      All of which u can do in C
      So I think that C++ designated initializers not very useful

  • @cemgecgel4284
    @cemgecgel4284 ปีที่แล้ว

    Very nice!

  • @7alken
    @7alken ปีที่แล้ว

    excellent;

  • @henrykkaufman1488
    @henrykkaufman1488 ปีที่แล้ว

    Who would want to use C today? Me

  • @olafschluter706
    @olafschluter706 9 หลายเดือนก่อน

    Funny to question the value of C these days: anything more recent than C is written in C. C is the enabler of anything else. Sure you do not need to learn C to program im Python - but both the Python interpreter and most of the python modules you are using are written in C for performance and efficiency. It is still the most memory-efficient and performant programming language today, even Zig, which claims to be good for embedded systems, produces a bigger Hello; World! then C.
    That being said, memory safety in C is a big issue and always has been. If your software gains a CVE (i.e. an entry in the security vulnerability database on the internet), the bad code causing this is most likely written in C.

  • @unperrier5998
    @unperrier5998 10 หลายเดือนก่อน

    At 27:18 "working with values is a very good sign of a modern language"
    LOL it's also a good sign that you're wasting CPU cycles copying data around. But sure, it's nicer on the eye.

    • @meandtheboyz4796
      @meandtheboyz4796 10 หลายเดือนก่อน +1

      Dont be like this guy. Too blind to see the big picture. He thinks everything is a dogma, that needs to be followed blindly. In gamedev, you pass 3d and 4d vector structs by value, because its less error prone and you use them all the time, and guess what compiler inlines all the operations on them and you get error checking for free. Same goes for initializing everything with 0. I initialize every struct with 0 by default, unless I am absolutely sure its on a critical path. The amount of errors you can avoid by 0 initializes is insane. Heck I don't even break code into functions unless I have atleast 2-3 case of repetition where it makes sense for it to be a function. I don't use malloc, I allocate the memory I need at startup and use arenas to deal with it. And temporary buffers, they are so good.
      TLDR. Use your mind.

  • @nngnnadas
    @nngnnadas 2 ปีที่แล้ว

    I started to watch this talk, which is kind of weird for someone that only knows C and not C++

  • @VictorMistral
    @VictorMistral 2 ปีที่แล้ว

    Embedded software should shift slowly to C++, as newer generation comes, maybe rust in addition/instead...
    After all, C++ is just as light, more alive, can do all C can do, with some higher abstraction.
    To main issue with pushing C++ to embedded domain is just changing mind sets.
    I would guess that going to Rust is simular, except that they have a bit of help with the fact that C isn't in the name, and Rust devs seems to listen a bit more to embedded needs then C++, but that just a feeling, without any research, could be really wrong on that...

    • @ingframin
      @ingframin 2 ปีที่แล้ว +7

      TBH the main issue with C++ in embedded development is unpredictability. You can never be 100% sure when the compiler will call a copy constructor or a move constructor and when it does or does not allocate things. From a microcontroller programmer perspective, those features are problematic. The magic the compiler applies makes it difficult to generate predictable executables and estimate the timing of operations, especially in real time control systems or DSPs.
      Also, my personal opinion, move semantics is a patch to contain this allocation unpredictability rather than a feature.

    • @alefratat4018
      @alefratat4018 2 ปีที่แล้ว

      What I already see a lot in embedded (microcontroller excluded) is the systems / firmware parts are programmed in C, while the applications are programmed in C++.
      Still not sure if it is really an improvement though.

    • @hetaeramancer
      @hetaeramancer 9 หลายเดือนก่อน +2

      why tf do you even believe that higher abstraction is necessary in embedded programming?

  • @_-martin-_
    @_-martin-_ 10 หลายเดือนก่อน

    We need C to evolve with modern features and not turn into the syntax mess that is Rust, Go, etc.

  • @yephick
    @yephick 3 ปีที่แล้ว +11

    You convinced me that "modern C" is basically a glorified MASM. Maybe the title should have been "you can do everything in modern C with macroses"

    • @NymezWoW
      @NymezWoW 3 ปีที่แล้ว

      The question is, why would you? Preprocessor macros are inherently unsafe. C++ Templates are usually a much better solution for the same thing.

    • @alice_in_wonderland42
      @alice_in_wonderland42 2 ปีที่แล้ว

      @@NymezWoW because Linus Torvalds maybe

  • @BigBahss
    @BigBahss 3 ปีที่แล้ว +81

    "There is more to C than meets the eye"
    Nice.

  • @saturdaysequalsyouth
    @saturdaysequalsyouth 3 ปีที่แล้ว +236

    I write C every day as an embedded developer. It's funny to me that some people think C is some ancient obscure language. C is not going anywhere for a long time.

    • @kuhluhOG
      @kuhluhOG 2 ปีที่แล้ว +6

      well, it is ancient
      obscure? besides the variable declaration syntax, not really
      although having a 7 year standard cycle is a bit too long imo

    • @arizablozki9370
      @arizablozki9370 2 ปีที่แล้ว +9

      I love c

    • @Ryan-xq3kl
      @Ryan-xq3kl 2 ปีที่แล้ว +2

      people should experiment with writing modular build systems for C. I would bet there are tons of different ways you could implement them.

    • @jackm_
      @jackm_ ปีที่แล้ว +10

      @@kuhluhOG you do realize that us embedded developer write C99 when we're lucky, right? because most compilers are C90+extensions, some are C99+extensions. And the "slow" update cycle may be a sign that the language is mature and doesn't need new cool features/is stable/[insert another big advantage of C]
      gcc for arm is probably C11 now but how many are using C11 features, really?

    • @rays14ful
      @rays14ful 8 หลายเดือนก่อน

      Exactly. I have been using C for the last 24 years. All my embedded work is in C. At Apple we used C exclusively for all the systems work including the OS, the Apple car and all its systems.

  • @jameslay6505
    @jameslay6505 2 ปีที่แล้ว +72

    He has eloquently voiced so many of my thoughts on C. The libc functions are RIDICULOUS. Also, strtok is pure comedy. Because of library design or build nightmares, C devs often have to re-implement very basic operations. If someone would design a sane, modern C std lib and a build system that could compete with cargo/npm/pip/etc... using C would not require any large tradeoffs from using other languages; and would have some very pronounced advantages, offering more control than any popular alternative. I did look into zig and rust; great languages, but those build times are not great. Idk if that's LLVM or just young compilers, but be prepared to get up and make yourself coffee every time you rename a variable.

    • @mensaswede4028
      @mensaswede4028 2 ปีที่แล้ว +11

      Exactly, no one doing anything meaningful uses much of the standard C library. You have to be willing to build up your own more useful functions if you want to do anything non-trivial nowadays. But today’s culture is that of open-source dependencies where devs are used to being able to download a dependent open-source 3rd-party library to do anything non-trivial. Of course that doesn’t exist in C. But if you’re a dev worth your salt, then you just write your own shit when you need it, and it doesn’t take that long.

    • @NabekenProG87
      @NabekenProG87 2 ปีที่แล้ว +20

      @@mensaswede4028 It only doesn't take that long if it's not much work in the first place. Sure, I would love to learn how to write a multicore async runtime, but I might as well save decades of my life by using one that has been heavily tested

    • @SasLuca
      @SasLuca 2 ปีที่แล้ว +13

      Hi, glad you enjoyed my talk. Zig is actually developing systems meant to make build speeds very fast in debug mode which should solve the build-time issues you have. Another language worth looking into is Jai by game developer Jonathan Blow, tho the language is not yet public.

    • @liam.3d265
      @liam.3d265 2 ปีที่แล้ว

      Please give V (vlang) a try!

    • @nickgennady
      @nickgennady ปีที่แล้ว +4

      Cargo for C would be so amazing.

  • @LinkFromCdi
    @LinkFromCdi 3 ปีที่แล้ว +63

    Good talk.
    I too find modern c to be really refreshing, and use it for personal projects. Also great to see sokol-gfx, which is a joy to use.
    The biggest problem I see with C is its lack of standard library.
    It makes the language inaccessible to people for quick "getting to know the language"-type of projects.
    Often the only alternative to using the standard library is either writing your own libraries or searching for other peoples libraries.
    But without significant experience you just can't judge the libraries you find properly, and certainly can't construct a good one.
    So beginners will use the standard-library, which is in many places crappy and very insufficient.
    Especially string handling, which is also probably one of the first thing people want to do with a language.
    Imo the top priority for any C "comittee" or people interested in pushing the language should be to band together and create a new defacto standard library based on modern c which everyone new then can simply use to get some stuff done.

    • @dandymcgee
      @dandymcgee 2 ปีที่แล้ว

      THIS ^^^^^^^^^^^^

    • @mbartelsm
      @mbartelsm 2 ปีที่แล้ว +14

      I agree, my biggest gripe with C is that I always feel like I have to implement the universe from scratch for any project I want to do.

    • @gaius_marius
      @gaius_marius ปีที่แล้ว +4

      I completely agree. C with a well designed and useful standard library would be amazing. It doesn't need to be huge, but it should have the basic building blocks such as strings, vectors, maps, etc. I don't like OO, but sometimes I use C++ just because I love the STL.

    • @shawnshaw9859
      @shawnshaw9859 ปีที่แล้ว +1

      @@gaius_marius maybe glib is one option, not ideal but it's what we have for now

  • @LemonChieff
    @LemonChieff 3 ปีที่แล้ว +34

    This is probably the best argument for C: Implement your own libraries.
    The result: well defined, portable, benchmarked and optimized, *standard compliant* (ironically), source code.

  • @AndresFH7233
    @AndresFH7233 3 ปีที่แล้ว +36

    This talk is great!, I was searching for a new language close to C, but this just reminded me the power of C. I love these ideas which keep the language updated.

    • @ACCUConf
      @ACCUConf  3 ปีที่แล้ว +3

      Glad it was helpful!

    • @NymezWoW
      @NymezWoW 3 ปีที่แล้ว +5

      The only real alternative to C/C++ is Rust.

    • @kuhluhOG
      @kuhluhOG 2 ปีที่แล้ว +6

      @@NymezWoW or Zig

    • @nephew_tom
      @nephew_tom 2 ปีที่แล้ว +3

      @@kuhluhOG or Jai

    • @alefratat4018
      @alefratat4018 2 ปีที่แล้ว

      @@nephew_tom Jai is not available yet though ?

  • @jkennethking
    @jkennethking 3 ปีที่แล้ว +20

    Even using Zig as a modern C compiler is quite nice. Cross-compilation and a unified build system you can write in Zig is a good bonus if you want to avoid the stack of tooling a typical C project needs.

    • @ggss2836
      @ggss2836 2 ปีที่แล้ว

      what else do you need except for a compiler and a shell/batch script file?

    • @xr.spedtech
      @xr.spedtech ปีที่แล้ว +3

      @@ggss2836 Astyle, valgrind, a profiler, gdb, man pages ...
      See where I'm going ?

    • @FlanPoirot
      @FlanPoirot ปีที่แล้ว +3

      @@ggss2836 a C compiler, a static analysis tool like valgrind, a debugger like gdb, a build system like make, cmake, meson, etc, a version control system very likely git, a way to track your dependencies like git submodules and/or your system's package manager

  • @4fips
    @4fips 3 ปีที่แล้ว +18

    Fixing strings in C is actually hard, although representing strings as { data, size } makes a lot of sense, the problem is when it comes to interoperability with legacy APIs and external libraries, where zero-terminated strings are usually expected, in which case such a string view needs to be reallocated and appended with a zero just for the purpose of passing it to some external API. So it's a matter of preference, one can either have cheap string views / slices, or a natural (zero-terminated) string representation, but not both at the same time. So there's always some trade off.

    • @grafgrantula6100
      @grafgrantula6100 3 ปีที่แล้ว

      Yes, good point!
      Stupid question though: Cant we use a compatible_string that supports both null terminated via an extra pointer and the more handy {data, size} interface?
      Yes, it complicates stuff and might not be worth it for all cases, but maybe for most of them?

    • @alice_in_wonderland42
      @alice_in_wonderland42 2 ปีที่แล้ว +3

      @@grafgrantula6100 str is just storing that null terminated string in its data field
      N calculating its length for the size
      So for str u can just return
      str->data to get back ur null terminated string

    • @SasLuca
      @SasLuca 2 ปีที่แล้ว

      Hi, in regards to zero-terminated string API interoperability, just do what other langs do! You can have strategies where you copy the string to make it null terminated, or sometimes you can write your code such that you guarantee a string is null terminated. Also if you use a string_buffer rather than a string slice you can ensure the string_buffer always puts a null terminator at the end. A collection of strategies like this depending on the kind of program you write can certainly help and languages such as Zig are even better because the type system supports slices natively but also supports slices with sentinel values natively! So you can specify if a slice is meant to have a null terminator in the type system, pretty cool :D

    • @StianGudmundsenHiland
      @StianGudmundsenHiland ปีที่แล้ว +6

      You could have the underlying data just be a null-terminated string, represented by a { data, length } struct where the length is -1 to the underlying null-terminated string length. That way you get the more ergonomic interface where you have it, but you can also easily pass the string to legacy APIs and libs, as well as tap into the null-terminated C string *when you know what you are doing* by the convention that your string (or data pointer) is actually a null-terminated C string. All it costs is one convention and one extra byte per string, which is how C has it already anyway.

    • @ABaumstumpf
      @ABaumstumpf ปีที่แล้ว

      @@StianGudmundsenHiland and that is basically what C++ has been doing with strings since C++11.

  • @zonkle
    @zonkle 3 ปีที่แล้ว +17

    I hadn't seen this defer macro before. I like it.

  • @dummybugstudios6450
    @dummybugstudios6450 2 ปีที่แล้ว +14

    I'm currently writing a basic game engine for a graphical calculator in C and this talk couldn't have come at a better time ❤️

    • @gowthamk7416
      @gowthamk7416 6 หลายเดือนก่อน

      Good luck man!!

  • @websnarf
    @websnarf 2 ปีที่แล้ว +8

    The defer macro described @ 18:00 hides a change in the semantics of the continue statement. Furthermore, the end will not execute if you return from the code block.

  • @jd89
    @jd89 2 ปีที่แล้ว +7

    Learned a lot, thanks for this! I would prefer to write my own game engine in C, but since I'm trying to get into the industry it seems I'm stuck with C++ since everyone uses it. 😢

  • @diceandbricks
    @diceandbricks 3 ปีที่แล้ว +11

    The dynamic array implementation has problems on architectures with strict data alignment. The dynarray_info struct might place your array elements in a misaligned address, which can degrade performance or crash on some architectures like ARM. This can be resolved by combining the array with the info using a flexible array member, so the compiler can ensure proper alignment.

    • @melonwatcher
      @melonwatcher 3 ปีที่แล้ว +3

      By flexible array member, you just mean a void pointer to the start of the array, rather than just assuming it follows after the info struct?

    • @mettemafiamutter5384
      @mettemafiamutter5384 3 ปีที่แล้ว +2

      Good catch. But how would flexible array member work with type safety? They have: "#define dynarray(T) T*" which allow you to use index operator directly on the "vector" but also without casts. I imagine your flexible array member would be of type unsigned char.

    • @mettemafiamutter5384
      @mettemafiamutter5384 3 ปีที่แล้ว

      In practice I doubt this will be a problem, i.e. sizeof(dynarray_info) will be a multiple of sizeof(max_align_t).

    • @diceandbricks
      @diceandbricks 3 ปีที่แล้ว

      @@mettemafiamutter5384 not true on my architecture (actual code output, clang on Arm processor):
      sizeof(dynarray_info) = 24
      sizeof(max_align_t) = 32

    • @diceandbricks
      @diceandbricks 3 ปีที่แล้ว

      @@mettemafiamutter5384 I access elements through the flexible array member. Sort of like this (neglecting error & bounds checking for now):
      #define DYNARRAY(T) struct { dynarray_info info; T data[]; }
      #define DYN_PUSH(A) (A)->data[(A)->info.size++]
      size_t length = 100;
      DYNARRAY(long double) *numbers = malloc(sizeof(*numbers) + (sizeof(*numbers->data) * length));
      numbers->info = (dynarray_info){ 0, length, sizeof(*numbers->data) };
      DYN_PUSH(numbers) = 3.14159;
      Now sizeof(*numbers) == 32, with padding so data[] is properly aligned.
      I suppose you could also union dynarray_info with multiple max_align_t to achieve proper alignment. I'll have to play with that.

  • @YourCRTube
    @YourCRTube 2 ปีที่แล้ว +5

    18:44 This `defer` is footgun™ as it does not call the end function on return statement.

    • @dandymcgee
      @dandymcgee 2 ปีที่แล้ว

      or break or goto probably

  • @shomonercy
    @shomonercy 3 ปีที่แล้ว +9

    This dude and I are on the same wavelength. Well done!

  • @LDdrums20
    @LDdrums20 2 ปีที่แล้ว +7

    I like this. It's being like 20 years that I haven't touched serious c code. This inspires me to get more into the modern stuff

    • @tullochgorum6323
      @tullochgorum6323 11 หลายเดือนก่อน +1

      Ditto - I haven't touched C since the 80s and K&R 1. It was all pretty painful back then - even the tooling was a challenge. Modern C with modern tooling, such as the new VS interactive debugger, seems a much more attractive proposition.

  • @terjeoseberg990
    @terjeoseberg990 ปีที่แล้ว +2

    Why are you so afraid of pointers?

  • @JamesJones-zt2yx
    @JamesJones-zt2yx 2 ปีที่แล้ว +3

    C took the /* ... */ comments from PL/I. Also, PL/I requires the parentheses for an expression being returned. The C statement syntax is just "return expression"... *but* you can always parenthesize an expression, so C will take "return x + y;" or "return (x + y);", and the people who developed Unix had previously worked on Multics, which was written in PL/I. C would thus be accepting of what someone coming from PL/I would do by force of habit.

  • @LunaticEdit
    @LunaticEdit 2 ปีที่แล้ว +36

    All I use is C. It’s the fastest portable and most explicit language out there.

    • @Dazza_Doo
      @Dazza_Doo 8 หลายเดือนก่อน

      What version of C?
      I'm trying to learn it thoroughly. I'm hearing that pointers are the way to go and that passing by reference is the preference ( I agree, passing by pointer / reference is the way to go) and yet on this video they avoid pointers. Hmm

    • @blastygamez
      @blastygamez 5 หลายเดือนก่อน

      True, personally C99 is my fav

    • @jeremymcadams7743
      @jeremymcadams7743 4 หลายเดือนก่อน

      I feel like passing by reference really depends on memory constraints and general size. On an arduino I would always pass by reference, but on my laptop it just depends. I always pass structs by reference but an int or smaller? Not really (unless i want to directly modify it). Just be sure to make it const so it can't be mutated​ if you have no intention of modifying the reference.@@Dazza_Doo

  • @doublex85
    @doublex85 3 ปีที่แล้ว +2

    You might even have your first_split function return a pair of string views, instead of mutating its argument. Not really sure if it's more convenient.
    typedef struct { str _0, _1; } str2;
    str2 first_split(str, str);
    str2 s = first_split(cstr("2021/03/12"), cstr("/"));
    assert(!memcmp(s._0.data, "2021", s._0.size));
    assert(!memcmp(s._1.data, "03/12", s._1.size));

  • @simonfarre4907
    @simonfarre4907 2 ปีที่แล้ว +4

    Struct initialization has been part of c++ since c++14 i believe. Both in clang and gcc

    • @TanigaDanae
      @TanigaDanae 2 ปีที่แล้ว +1

      They made it into the standard C++20. It might be possible that some compiler supported it before that.

  • @anjanbora7943
    @anjanbora7943 2 ปีที่แล้ว +2

    C language is my mother tongue 👅

  • @Aaronb2245
    @Aaronb2245 3 ปีที่แล้ว +3

    Thank you for putting this video together and sharing your knowledge. This is an extremely helpful knowledge share for someone like me just learning C.

    • @ACCUConf
      @ACCUConf  3 ปีที่แล้ว

      Glad it was helpful!

  • @georgerabus9314
    @georgerabus9314 3 ปีที่แล้ว +4

    nice

  • @not_woowoo
    @not_woowoo 2 ปีที่แล้ว +2

    22:50
    How does accessing floats in elements[2] work with struct padding involved; isn't it possible for padding to make the second float's offset more than the size of the first float? Having the elements array assumes that the floats are packed in memory, right?

    • @michaelclift6849
      @michaelclift6849 2 ปีที่แล้ว

      right, padding would break it, but are there platforms which pad for an 8byte alignment?

  • @RyanWhitlie
    @RyanWhitlie 2 ปีที่แล้ว +2

    Really nice talk, I especially like the error handling ideas. I'm no hardcore C programmer, but isn't avoiding passing by reference bad in the file load -> process -> pass to GPU example? The file data is copied when passed as a value to functions, so surely that's way less performant than using a pointer to the initial data, and passing that reference through the call pipeline? Or am I missing something? Does the compiler magically know what you're doing and switch to pointers before generating output?

    • @joshuarowe8410
      @joshuarowe8410 11 หลายเดือนก่อน

      the struct itself doesnt contain the file data it just contains a pointer to the file data

  • @nickgennady
    @nickgennady ปีที่แล้ว +1

    I am started a game framework in C few weeks back.
    I have one .c file (I include .c files and not even bother with .h) for each module (App,physics2D,input, and renderer2D) and there basically its own library and they each have not dependencies on each other.
    Its a good and fresh break when I work on it from C++ Unreal.

  • @IgorStojkovic
    @IgorStojkovic 3 ปีที่แล้ว +8

    Great talk! I really liked the solutions for defer and strings. But it was really painful that you don't mention DLang as you talk about these features in Go, Rust and others (except mentioning it at the end). DLang had these features when all these other languages didn't even exist.

    • @ACCUConf
      @ACCUConf  3 ปีที่แล้ว +5

      Great point!

    • @SasLuca
      @SasLuca 2 ปีที่แล้ว +3

      Good point, I plan on giving a refresh on this talk soon and I will definitely mention Dlang too!

  • @xfcisco
    @xfcisco 3 ปีที่แล้ว +2

    At 44:16 shouldn't `log("Cat: {cat}", c);` be `log("Cat: {cat}", &c);` ?

    • @alice_in_wonderland42
      @alice_in_wonderland42 2 ปีที่แล้ว

      No u just pass c by value
      Then the log function
      Passes &c to the registered function(print cat, probably stored in a hashmap as type function pair)

  • @Narblo
    @Narblo 2 ปีที่แล้ว +1

    What I dont get is why dont they make a new C version that breaks backwards compatibility on some code patterns and adds all these common patterns to the language itself

    • @__gadonk__
      @__gadonk__ ปีที่แล้ว +1

      you already answered the question yourself

  • @evolutionalgd
    @evolutionalgd 3 ปีที่แล้ว +2

    Great talk. Lots to unpack from this.

  • @_-martin-_
    @_-martin-_ 10 หลายเดือนก่อน

    This guy is so funny. He is so proud he reinvented glib string features lol . Typical developer who does not investigate existing solutions before reinventing the deep dish.

  • @xloppyschannel4881
    @xloppyschannel4881 ปีที่แล้ว

    C is only thing I can comprehend tbh, other languages are too big.

  • @0114mercury
    @0114mercury ปีที่แล้ว +1

    I stumbled upon this video a few years later, thanks for a great talk! Could the author (or others) tell an opinion on the following concern:
    The reason some people like C, is that when you program in it (say C99), you can have a pretty good clue of how the assembly code will look like, and how machine will execute code under the hood (Linus Torvalds mentioned this: th-cam.com/video/CYvJPra7Ebk/w-d-xo.html). That's not the case with many higher level languages, e.g. in c++ you write vector v, v.emplace_back(a, b), and not many people know what exactly is happening under the hood.
    1) How can we ensure machine code won't be hidden from the programmer writing modern C?
    2) Should we worry about (1)?
    3) Is there some tool, say a bash command `to_c99 my_modern_c_file.c`, which would translate the modern C code back to an equivalent C99 code, so that if I struggle to understand what modern macros/resource_allocators do, I could inspect the C99 code to get a clue?

    • @michaelclift6849
      @michaelclift6849 11 หลายเดือนก่อน +2

      It's the reason I never made the jump to C++, so much hidden execution. In C you know that x+y performs addition. In C++, x+y could literally do anything.
      1) It won't hide anything significant
      2) No
      3) If you're using GCC you can compile with -E to produce the pre-processor output (which will show you what all the macro's expand to. If you have a reasonable editor like VS code, you can navigate straight to the definitions and declarations. That helps a LOT in figuring out how things work.

  • @lattehour
    @lattehour 5 หลายเดือนก่อน

    few people get it C is infinite in scope you can do anything you want with it and in any shape you want the only limit is yourself

  • @neimsaci942
    @neimsaci942 3 ปีที่แล้ว +2

    Great talk!

  • @ercntreras
    @ercntreras หลายเดือนก่อน

    The thing is not the language but the purpose

  • @0w784g
    @0w784g หลายเดือนก่อน

    You can have more fun in C than any other language imho.

  • @isovideo7497
    @isovideo7497 11 หลายเดือนก่อน

    You don't need parentheses around a return value. It's return ; which can have parentheses around ,but return isn't a function. return(1)+2 returns the integer 3.

  • @icydeadcrusher
    @icydeadcrusher ปีที่แล้ว +1

    Really interesting talk, thank you!

  • @dengan699
    @dengan699 3 ปีที่แล้ว +2

    I wish i d do more C and less python

    • @alefratat4018
      @alefratat4018 2 ปีที่แล้ว

      Just have to find the right job ;)

  • @fredmorcos
    @fredmorcos 3 ปีที่แล้ว +2

    Any reason why isize_t is used for things that should be unsigned (size_t)?

    • @dko1905
      @dko1905 3 ปีที่แล้ว

      I have the same question

    • @alice_in_wonderland42
      @alice_in_wonderland42 2 ปีที่แล้ว

      So that difference of two sizes(some fn can do that for some stuff) doesn't under flow and become a large positive number instead of the expected negative or positive
      Maybe for negative indices like python has

    • @maximkovalkov1334
      @maximkovalkov1334 2 ปีที่แล้ว +1

      I think it has something to do with undefined behavior, which weirdly enough would be a good thing in this case!
      I heard that using "int" instead of "unsigned" even when you always expect a positive value can lead to speedups thanks to compiler optimizations. Basically, for 'unsigned's, the compiler has to handle the possible overflow which can sometimes add a couple instructions; while for 'int's overflow is undefined so the compiler may act as if it could never happen (and provide no guarantee on the result)

    • @ABaumstumpf
      @ABaumstumpf ปีที่แล้ว

      often signed values are used to tell the compiler "hey, these values are small and we will pass along only sane values. So there is no reason for you to do any bounds/overflow-checking".
      But it can also be the other way around: since C99 integer division is rounded towards zero. This means dividing signed integers is slowed cause it needs to handle the negative case having a different rounding.

  • @KANJICODER
    @KANJICODER ปีที่แล้ว

    I got screwed by flash dying. Took me 8 years to figure out what to use next. I wanted something that wouldn't die on me when it takes me forever to build stuff. I chose C and JavaScript .

  • @franzflasch8181
    @franzflasch8181 2 ปีที่แล้ว +1

    Great talk!

  • @septagh
    @septagh 3 ปีที่แล้ว +1

    Nice talk. Love the defer macro

  • @stackoverflow2155
    @stackoverflow2155 3 ปีที่แล้ว +1

    This is INSANELY good!!!

  • @RichardRLindley
    @RichardRLindley ปีที่แล้ว

    I'd say use a microcomputer (the raspberry was the first) - one with easy access to an Assembler. You get to know the chip used (the architecture) and will never run into a problem with libraries as you understand what they rely on - Assembler. It's up and coming is Assembler. You run into problems with a x86 protected chip - which they all seem to be. Finally, we can make video games again!

  • @nickgennady
    @nickgennady ปีที่แล้ว

    My number 1 thing I wanted to be added to C is basically a copy and paste of Rust’s cargo system. Including libraries is the worst thing in C (Even in C++).
    I would also want float2, float3, float4, double2……… and so on added to C (Like HLSL). So that we all have 1 base to build off of. Everyone going around implementing there own is not very good for compatibility.

  • @ABaumstumpf
    @ABaumstumpf ปีที่แล้ว

    It is kind of annoying that C++ is just partially allowing struct-initialisition now. And every time it is prossed it was shut down for stupid reasons that basically boiled down to "nobody needs this".
    Also C should start with giving us named parameters. that can be simulated with some macro-magic but really that should be part of the language.
    And C++ std::string_view - most of the time i would say stay clear of that. There are way too many pitfalls with that, not the least are the standard-library functions that might still convert it to const std::string&.

  • @FPChris
    @FPChris 2 ปีที่แล้ว +1

    C is great. I want a gui framework.

  • @zxuiji
    @zxuiji ปีที่แล้ว

    As for shared pointer issues in C I think I found a way to solve it with custom mutices, I attached octal permissions to it and made it so only the thread declared as the owner can destroy the attached data and only if the mutex has no threads attached and no threads with permission to attach (so when the owning thread tries to revoke it's own permissions it will only succeed if it is either passing ownership to another thread or the mentioned conditions are cleared, in which case destruction is triggered, the mutex pointer is no longer valid then)