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

Поділитися
Вставка
  • Опубліковано 7 кві 2021
  • #Programming #Cpp #AccuConf
    Slides: accu.org/conf-previous/2021/s...
    ACCU Website: www.accu.org
    ACCU Conference Website: conference.accu.org
    ACCU Twitter: @ACCUConf
    Streamed & Edited By Digital Medium Ltd: events.digital-medium.co.uk
    ------
    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.
    -------------------------
  • Наука та технологія

КОМЕНТАРІ • 225

  • @BigBahss
    @BigBahss 3 роки тому +77

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

  • @saturdaysequalsyouth
    @saturdaysequalsyouth 3 роки тому +233

    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

      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 6 місяців тому

      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.

  • @dengan699
    @dengan699 3 роки тому +153

    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.

  • @LemonChieff
    @LemonChieff 3 роки тому +33

    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.

  • @jameslay6505
    @jameslay6505 2 роки тому +70

    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 роки тому +62

    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

  • @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 Рік тому

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

    • @ABaumstumpf
      @ABaumstumpf 9 місяців тому

      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 4 місяці тому

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

  • @AndresFH7233
    @AndresFH7233 2 роки тому +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  2 роки тому +3

      Glad it was helpful!

    • @NymezWoW
      @NymezWoW 2 роки тому +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 Рік тому

      @@nephew_tom Jai is not available yet though ?

  • @shomonercy
    @shomonercy 3 роки тому +8

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

  • @TheSulross
    @TheSulross 2 роки тому +4

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

  • @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 ❤️

  • @evolutionalgd
    @evolutionalgd 3 роки тому +2

    Great talk. Lots to unpack from this.

  • @zonkle
    @zonkle 3 роки тому +17

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

  • @paxdriver
    @paxdriver 11 місяців тому

    This is the most informative presentation on C I've come across to date. Well done

    • @ACCUConf
      @ACCUConf  11 місяців тому

      Thank you for commenting! Pleased to hear that this was a helpful presentation.

  • @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

  • @stackoverflow2155
    @stackoverflow2155 3 роки тому +1

    This is INSANELY good!!!

  • @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 8 місяців тому +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.

  • @sriramsrinivasan2769
    @sriramsrinivasan2769 3 роки тому +2

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

  • @jonathanmoore5619
    @jonathanmoore5619 Рік тому +2

    Me. I love C. Nothing better.

  • @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 Рік тому +5

      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 9 місяців тому

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

  • @DrOggy67
    @DrOggy67 2 роки тому

    Excellent talk!!! Thx a lot to Luca for sharing his knowledge with us ;)

    • @ACCUConf
      @ACCUConf  2 роки тому

      Glad you liked it!

  • @adanjsuarez
    @adanjsuarez 2 роки тому +2

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

    • @ACCUConf
      @ACCUConf  2 роки тому

      Thank you for your comment!

  • @spinthma
    @spinthma 3 роки тому +6

    Super Cool, thanks a lot!

  • @Aaronb2245
    @Aaronb2245 2 роки тому +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  2 роки тому

      Glad it was helpful!

  • @dimitrioskalfakis
    @dimitrioskalfakis 9 місяців тому

    satisfying and sound assessment as well as interesting new features.

  • @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.

  • @icydeadcrusher
    @icydeadcrusher Рік тому +1

    Really interesting talk, thank you!

  • @ishi_nomi
    @ishi_nomi Рік тому

    This is such an awesome talk

  • @neimsaci942
    @neimsaci942 3 роки тому +2

    Great talk!

  • @septagh
    @septagh 3 роки тому +1

    Nice talk. Love the defer macro

  • @abhisohal4556
    @abhisohal4556 11 місяців тому

    Excellent talk. changed my view of the c language.

  • @Little-bird-told-me
    @Little-bird-told-me 5 місяців тому

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

  • @rohandvivedi
    @rohandvivedi 2 роки тому +1

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

  • @mafazabrar4349
    @mafazabrar4349 11 місяців тому

    amazing talk!!!

  • @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. 😢

  • @thomasaguest
    @thomasaguest 3 роки тому +1

    excellent talk thanks

  • @OLIV3R_YT
    @OLIV3R_YT 7 місяців тому

    That "defer" macro was very cool 😎

  • @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.

  • @isovideo7497
    @isovideo7497 8 місяців тому

    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.

  • @nickgennady
    @nickgennady Рік тому

    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.

  • @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.

  • @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.

  • @cemgecgel4284
    @cemgecgel4284 10 місяців тому

    Very nice!

  • @LunaticEdit
    @LunaticEdit 2 роки тому +36

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

    • @Dazza_Doo
      @Dazza_Doo 5 місяців тому

      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 2 місяці тому

      True, personally C99 is my fav

    • @jeremymcadams7743
      @jeremymcadams7743 2 місяці тому

      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

  • @multicoloredwiz
    @multicoloredwiz 3 роки тому +7

    the presenters string library looks heavenly to work with lol!

  • @Mankindux
    @Mankindux 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

      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

  • @andreffrosa
    @andreffrosa 6 місяців тому

    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.

  • @temdisponivel
    @temdisponivel 3 роки тому +6

    Good stuff

    • @ACCUConf
      @ACCUConf  3 роки тому +3

      Glad you enjoyed

  • @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

  • @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

  • @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?

  • @7alken
    @7alken Рік тому

    excellent;

  • @raydall3734
    @raydall3734 6 місяців тому

    I program EXCLUSIVELY in C, both front and back end.

  • @georgerabus9314
    @georgerabus9314 3 роки тому +4

    nice

  • @RyanWhitlie
    @RyanWhitlie Рік тому +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 9 місяців тому

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

  • @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 Рік тому

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

  • @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.

  • @diceandbricks
    @diceandbricks 3 роки тому +10

    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.

  • @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!

  • @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)

  • @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 роки тому +2

      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 2 роки тому +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 9 місяців тому +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.

  • @SerjCrimea
    @SerjCrimea 7 місяців тому

    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?

  • @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 8 місяців тому +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...

  • @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.

  • @baardi2
    @baardi2 3 роки тому +1

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

  • @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!

  • @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 ^^

  • @stelluspereira
    @stelluspereira 7 місяців тому

    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

  • @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.

  • @anjanbora7943
    @anjanbora7943 2 роки тому +2

    C language is my mother tongue 👅

  • @MDarkus3
    @MDarkus3 9 місяців тому

    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 9 місяців тому

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

  • @napent
    @napent 2 роки тому

    Where are your benchmarks and unit tests @:)

  • @a_commenter
    @a_commenter Рік тому

    Does anyone have any further reading I can do on modern C? I'm very interested

  • @lattehour
    @lattehour 3 місяці тому

    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

  • @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)

  • @ingframin
    @ingframin 2 роки тому

    I did not understand how the defer macro works 😞

  • @SteaM992
    @SteaM992 2 роки тому

    regarding vectors, it can do the trick, but what if you dynamically alocate at runtime? Defines are replaced at precompilation. Vector alocates on the heap, not on stack. To do the same job in c, it's quite a hassle..Also you have polymorphism in c++... Coming from embedded development using C, i see c++ as a much better language in some cases.

    • @alefratat4018
      @alefratat4018 Рік тому +1

      Honestly, polymorphism is not that great. Sure, it makes the code 'prettier' but also harder to follow or debug, IMHO.

  • @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.

  • @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 9 місяців тому

      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 9 місяців тому

    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 .

  • @PaulJurczak
    @PaulJurczak 3 роки тому +4

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

    • @SasLuca
      @SasLuca 3 роки тому +3

      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 :(

  • @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.

  • @porky1118
    @porky1118 Рік тому

    27:35 I hate adding prefixes and suffixes to specific names. Like "_t" to types in this case.

  • @doublex85
    @doublex85 2 роки тому +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));

  • @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)

  • @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)

  • @butsy1986
    @butsy1986 3 роки тому

    Was the old function syntax even in the first standard C90

    • @D0Samp
      @D0Samp 2 роки тому +1

      K&R C syntax has been in every standard from C89 through C11, but also declared deprecated the whole time.
      Compilers will not complain about an old-style parameter list, but may warn if any parameter type or the return type is implicitly int, for example when declaring the main function as "main(argc, argv) char **argv; { ... }".

  • @thedancingpooch4586
    @thedancingpooch4586 Рік тому

    Hi there, sorry I’m a bit late to the party but I don’t think I completely understood why your str_pop_first_splitter function takes less allocations than strtok
    I don’t really see why adding the null terminator at the end of the popped string is a bad thing in this scenario, does strtok need to realloc the tokenized string for that singular ‘/0’? Thank you

  • @Narblo
    @Narblo Рік тому +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

  • @digitalzoul57
    @digitalzoul57 7 місяців тому

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

  • @xloppyschannel4881
    @xloppyschannel4881 Рік тому

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

  • @_-martin-_
    @_-martin-_ 7 місяців тому

    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.

  • @NymezWoW
    @NymezWoW 2 роки тому +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 роки тому +3

      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

  • @IndellableHatesHandles
    @IndellableHatesHandles 2 роки тому

    C's file I/O library has seemed extremely archaic. Whenever I tried to jump between reading and writing different files, it always messed up.
    In fact, I/O in general is something that needs to be fixed. It's pretty much the only reason why I'd prefer to develop in C++. When I call I/O functions, I don't want to have to clear the input or output buffer manually, because it's confusing. Not to mention that it never tells you when it's messed up. It's a very silent failure when you mess up I/O in C.
    Aside from that, the only major problems I've had have been with libraries that don't manage memory for you. I've been very quick to adjust to malloc() and free(), but SDL, for example, really forces you to read the documentation to find out if your program will leak memory. I've run Valgrind on my programs from a few months ago and found megabytes of unfreed memory, and none of it was from malloc().
    Then again, I've had no idea about these special tricks you've put here. Generally, I manage memory and strings in C in a very simple way, which is "if I add a malloc() call, I add a free() at the exit points." I would explore that garbage-collection approach you've mentioned. It looks neat.

    • @xr.spedtech
      @xr.spedtech Рік тому

      Where were your memory leaks ?
      I use SDL2

    • @scpmr
      @scpmr 11 місяців тому

      For IO just use your operating system's API. In fact I would prefer to use it for memory management too. It's faster and gives you better control

  • @porky1118
    @porky1118 Рік тому

    You forgot to mention Scopes here.

  • @krischalkhanal2842
    @krischalkhanal2842 Рік тому

    I loved this video but, much of the things here, after getting a little familiar with rust, feels like rust has much easier way of doing all the things mentioned here. It feels rust is whole generations above C.
    I still enjoyed this video, C is an important language that paved much of the way to this modern software world, and it's nice to see, the C guys are still doing nice things, inventing nice ways to solve problems, betting better able to use the language, and stuffs.

  • @ABaumstumpf
    @ABaumstumpf 9 місяців тому

    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&.

  • @terjeoseberg990
    @terjeoseberg990 Рік тому +2

    Why are you so afraid of pointers?

  • @porky1118
    @porky1118 Рік тому

    26:10 Isn't this what monads are?

    • @homelessrobot
      @homelessrobot Рік тому

      its something you can do with monads, but monads are a strictly more general concept.