Cs Biggest Mistake | Prime Reacts

Поделиться
HTML-код
  • Опубликовано: 15 ноя 2024

Комментарии • 396

  • @disgruntledtoons
    @disgruntledtoons 7 месяцев назад +8

    C was created by engineers who just wanted to get stuff done. After creating it, they used it to get stuff done.

  • @LeviShawando
    @LeviShawando Год назад +188

    Arguably this isn't C's "mistake", the issue is that C needed to be backwards compatible with B at the time, B didn't have arrays, it had "vectors" where it was just a pointer that pointed to a memory block. For B, arrays and pointers were the exact same. This is also why you can't just directly assign arrays in order to copy them. You _can_ however get both behaviors by wrapping arrays in a struct. Structs let you directly assign each other to copy and struct sizes are known at compile time.
    Moral of the Story: Backwards compatibility can hurt you badly.

    • @dickheadrecs
      @dickheadrecs Год назад +12

      moral of the story is structs are the dongles of C

    • @ErazerPT
      @ErazerPT Год назад +7

      True words. One could even argue that the root of all evil (in programming) is (bad) legacy. Be that Be that BadThingsTM that you propagated into the future or GoodThingsTM that were left out of the future because of legacy.
      One could also argue that the whole x86 both hw and sw is a clusterfsck of bad legacy, and the only good thing to do looking forward would be to design a new (proper) architecture and run legacy emulated/virtualized.
      Pains me deeply having to admit that, for all it's faults, Apple was the only (major) player to consistently tell the eco to "put up or shut up". And lo and behold, they put up and moved onward/forward.

    • @LeviShawando
      @LeviShawando Год назад +1

      @@ErazerPT Objective-C could've been done much better. They royally messed it up.

    • @amateurprogrammer25
      @amateurprogrammer25 Год назад

      computer scientists, putting the backward in backwards compatibility since the late 1960s

    • @dickheadrecs
      @dickheadrecs Год назад +1

      @@LeviShawando Obj-C is a language for NScrazy people

  • @chuckcrizer
    @chuckcrizer Год назад +180

    Walter Bright is a freaking LEGEND. He wrote the Zortech C/C++ compiler. The first such compiler for PCs in the 80s. He's the real deal.

    • @DJCloudPirate
      @DJCloudPirate Год назад +21

      Zortech was my first compiler. It came free with a C book my parents bought me in middle school. I hadn't even thought about that compiler in decades. Thanks for the shot of nostalgia!

    • @chuckcrizer
      @chuckcrizer Год назад +12

      @@DJCloudPirate I like to say that Walter Bright taught me C. I read every line of source code that came with that compiler and database supliment. I even printed out all the source files. It was just over a case of wide fanfold paper.

    • @slawtul
      @slawtul Год назад

      D lang also.

    • @k0rnburn
      @k0rnburn Год назад +1

      Also Empire game creator

  • @m4rt_
    @m4rt_ Год назад +36

    I think a language being successful is when there is a lot of people who still use it 50+ years later.

    • @realdragon
      @realdragon 5 месяцев назад +3

      It is fast, when I'm simulating orbits for a 100 years I don't want to wait 100 years for simulation to finish

    • @tempname8263
      @tempname8263 5 месяцев назад +1

      @@realdragon And when I don't want to write code for 100 years, I use something else. Beeflang for example.

    • @realdragon
      @realdragon 5 месяцев назад

      @@tempname8263 Sure, go use the thing you want or is the best for the job

  • @xBiggs
    @xBiggs Год назад +146

    I mainly use C for work. The number one thing I hate is that enums decay to the underlying type.

    • @BboyKeny
      @BboyKeny Год назад +2

      Is "enum class" different in this regard?

    • @brianb2308
      @brianb2308 Год назад +34

      @@BboyKeny enum class is c++, but yeah enum class is generally typesafe in that you can't just treat it as the underlying type without a cast.

    • @SVVV97
      @SVVV97 Год назад +19

      And yet we can't specify the underlying type (pre C23) - it's so insanely annoying

    • @brianb2308
      @brianb2308 Год назад +7

      @@SVVV97 true. C++ fixes this by allowing for syntax like
      enum MyEnum : char {A, B, C};
      But it is kind of dumb that C does get updates here and there and yet it took so long to get custom sized enums.

    • @svaira
      @svaira Год назад +3

      @@SVVV97 yes, and the biggest issue is in fact that the underlying type could be int16_t, i.e. only values up to 2^15-1 are safe

  • @ccgarciab
    @ccgarciab Год назад +28

    I only have limited C experience but I dealt with this problem by assuming arrays just don't exist, which isn't strictly true, but is enough to eliminate confusion. From then on, if I wanted a proper array I would define my own struct.
    I couldn't do much about null except programming very defensively, so that felt like a much more significant problem.

  • @jimhrelb2135
    @jimhrelb2135 Год назад +10

    I love this style of reading RFC-like articles. Such a fresh air from the common JS dev blogpost reactions.

  • @Charlyzard_ssb
    @Charlyzard_ssb Год назад +33

    As a game developer, this is the first Primeagen video I understand fully from start to finish

    • @jerichaux9219
      @jerichaux9219 Год назад +22

      As a web developer, I hate web development.

    • @MrDgf97
      @MrDgf97 Год назад

      As a neurological nanotechnologist, I shid and cummed 💀

    • @GuyFromJupiter
      @GuyFromJupiter Год назад +3

      As an electrical engineer, same (mostly)

    • @alvarohigino
      @alvarohigino 6 месяцев назад

      lol

  • @autistadolinux5336
    @autistadolinux5336 Год назад +12

    3:30 you can use a pointer to an array and its expressed as int (*foo)[N]. In fact, you can use the VLA syntax to do this:
    void add(size_t size, int (*foo)[size]);

  • @francescobrizi4940
    @francescobrizi4940 Год назад +36

    It's time to create the C** programming language, with array contents that start at A[1] and A[0] that contain the array dimention, to give new programmer more ways to fuck their code and segfault because of an unintentional change in A[0]. To make things more complicated, if A[0] does not contain enough space to store the entire lenght of the array, the compiler can randomly choose between transforming A[0] to a pointer to a bigger container or expand A[0] with A[1] without noticing, and it should be inpossible to know which of the 2 happened until a segfault happens

    • @dickheadrecs
      @dickheadrecs Год назад +15

      final boss: void** programming language where type annotations don’t exist at all, but if you get them wrong you brick your cpu

    • @isodoubIet
      @isodoubIet Год назад +7

      Somebody call the cops on this man

    • @LambdaJack
      @LambdaJack Год назад

      UNIX lredy hs tht covered.

  • @MrTact67
    @MrTact67 Год назад +25

    You should really have pointed out who Walter Bright is here -- he's the guy who created the Zortech C++ compiler. I also want to say. he wrote Turbo Linker.

    • @user-py9cy1sy9u
      @user-py9cy1sy9u Год назад +1

      The creator of D programming language

    • @homelessrobot
      @homelessrobot Год назад

      and the zortech c++ compiler was/is the first commercial c++ compiler for Windows, and maybe the first c++ compiler ever if you don't think transpilation to c counts.

  • @basione
    @basione Год назад +15

    Shoutout to Mr. Bartosz Milewski! A great academic/programmer renowned for teaching category theory to programmers.
    Definitely check him out if you're interested :)

  • @svaira
    @svaira Год назад +8

    Odin has effectively this exact feature, and even uses it with the old array syntax (T[], but you have to pass the array as f(x[:]) to give the length too, see "slice")

    • @InfiniteQuest86
      @InfiniteQuest86 Год назад +1

      Yeah I use Odin for personal stuff now, but definitely cannot for work.

  • @EsronDtamar
    @EsronDtamar Год назад +20

    Haskell is so good that it is even a brand for hair products.

  • @Gahlfe123
    @Gahlfe123 Год назад +74

    i agree with this video, null is annoying but i feel like its mangeable as long as you understand why it exists

    • @yaksher
      @yaksher Год назад +2

      I think null is a bigger problem when you venture outside of C; in C, yeah, it causes some bugs, but it's a fundamental part of how things work. In Java, for example, a fallible function is not just unidentifiable from its type signature, but also failure can be either by raising an exception or returning NULL or whatever, and since objects are implicitly references, there's less clarity about which things can even potentially be NULL vs which things are safe, etc.
      In C, errors are done through error code returns and writing output to an argument pointer or specific value returns, and you can tell which it could potentially be from the declaration, so you have to deal with much less.

    • @laughingvampire7555
      @laughingvampire7555 Год назад +1

      I agree, if you know about null you can totally control it, but requires to build good habits, and people have zero idea about how habits are made or destroyed.

    • @PoorlyMadeSweater
      @PoorlyMadeSweater Год назад +2

      @@laughingvampire7555 Its the age old "This language is great because you have to learn to be disciplined to use it" vs "If a language requires you to be disciplined to use it, it isn't great".

    • @fr0zi
      @fr0zi Год назад +2

      @@PoorlyMadeSweater every professionalist has to have some sort of discipline. Would you like to have undisciplined construction workers building your house? IOr undisciplined car engineer designing you car? I wouldn't. In many professions you have to be disciplined otherwise you are risking your or somebody else's life. Only in computer programming people think that language and compiler has to save them from every mistake.

    • @PoorlyMadeSweater
      @PoorlyMadeSweater Год назад +5

      ​@@fr0zi Yeap, thats one side of the argument. The other is the human brain isn't as capable as people like to think. Trying to entertain every possible mistake you could be making while maintaining a mental image of the entire system is impossible. Every mistake the compiler cant prevent is a land mine every pro is just one hour of missed sleep away from making.
      To use your metaphor, a *safe* language would require a buzz saw to contain a SawStop, a device that stops the blade when flesh is detected. A disciplined wood worker wouldn't argue against such a device simply because you *should* be good enough to not need one.

  • @nothke
    @nothke Год назад +16

    To me the biggest issue with C is the compilation process, the way the headers combine (and need to be manually created and maintained) and have name and macro collisions, additionally complicated thanks to lack of namespaces. Then everything else like:
    - switch requiring break (inherited by many other languages unfortunately)
    - null terminated strings
    - no array length..
    - Edit: variables uninitialized by default
    - implicit casts, not just pointers and arrays
    - lack of bools for conditions like if (int) being legal
    - shadowing (very easy to have nested for loops with same "i")
    ..etc..

    • @JuusoAlasuutari
      @JuusoAlasuutari Год назад +6

      #define when break; case
      You're welcome. Yes, this works. It's legal to put a break statement between the switch and the first case label.

    • @Sealedaway
      @Sealedaway Год назад +1

      Honestly yes, keeping headers up to date is an annoying extra step that is easy to forget. I've run into some pretty cryptic bugs when changing the type of an argument from int to size_t or something because I forgot to update the function prototype in the header. The lack of namespaces is also very annoying and practically discourages you from relying on libraries lest they clash with each other. Maybe that's why C kinda has the reputation of "you need to build all your tools from scratch". I like C for doing fast physics calculations but it sucks having to reinvent the wheel all the time.

    • @vncstudio
      @vncstudio 16 дней назад

      @@Sealedaway You can get away with using one external library at a time after somehow forcing your editor to find it. LOL.

  • @alexanderlea2293
    @alexanderlea2293 Год назад +37

    As someone who has worked primarily in C/C++ and assembly, I actually really enjoy C strings. It's the most natural from the perspective of the computer and while (*s) is effective enough for most string parsing. I'm not saying they're perfect, and there are times where I just want the string split methods that python has, but I personally would not want to see any changes. As for the array size, just pass it as another argument. Maybe I haven't worked on large enough projects to be affected by that sort of thing though.

    • @alexanderlea2293
      @alexanderlea2293 Год назад +15

      And I'll take 1 C String over the 6 "Rust" Strings any day of the week.

    • @infastin3795
      @infastin3795 Год назад +3

      ​@@alexanderlea2293same

    • @SimonBuchanNz
      @SimonBuchanNz Год назад +9

      ​@@alexanderlea2293there's str, which is a slice of UTF-8 in memory somewhere and String, which is the mutable, resizable string. Pretty uncontroversial if you're ok with memory slices and Vec both existing.
      Are you counting all the pointer types like Box, Rc etc you can wrap str in? Or are you talking about OsStr, Path, CStr and all the other weird interop types? They're occasionally useful, but not a huge deal.
      Compare with the million custom string types people create for "performance" in C++...

    • @KayOScode
      @KayOScode Год назад +4

      I have worked in a very large c++ project, and it was awful. The project started in the 80s though, so it definitely used some old patterns

    • @alexanderlea2293
      @alexanderlea2293 Год назад +1

      @@SimonBuchanNz I was talking about the catering and osstr equivalents. It's a bit crazy to have a language which requires more than one type of string to use fundamental programming tools.

  • @martygusto3056
    @martygusto3056 Год назад +3

    walter bright sounds like a genuinely smart computer engineer. I hope he does not get along with his ex student jesse fuschiaman to create a cybercrime empire specializing in blue screens of death.

  • @pepn
    @pepn Год назад +2

    Thanks for putting the article in the description !

  • @20dareason09
    @20dareason09 Год назад +2

    If you love C, you will love Odin. Odin has that idea proposed in this article, in fact it offers a bit more than that in an elegant way. Odin also has map type and a string type, and more (types). Odin keeps the simplicity of C but fastforwards to the context of modern day computer architecture.
    When I write C code I always feel like I'm in danger. When I switch to odin I feel free, and I don't have to jam all types of abstractions into my head (*ahem* C++, rust).

  • @HuxleysShaggyDog
    @HuxleysShaggyDog Год назад +1

    Null termination is a pain yes. So make a struct with a pointer and a length? 🎉

  • @donkeyy8331
    @donkeyy8331 Год назад +4

    I dunno, is it really that bad? maybe it's because I'm used to it, so everytime I use arrays in C I tend to make then dynamic, so I always have a variable with it's capacity along side it or if I only need one array at a specific place I will make it one index longer and put a "terminator" so I generally don't trip myself up.

  • @SimGunther
    @SimGunther Год назад +3

    As someone writing a simpler implementation of Monkeyscript in D, I completely stand by this article.

  • @sparky173j
    @sparky173j Год назад +4

    I'd pick switch-case requiring break.
    So many bugs have been caused by forgetting break.
    Add an explicit fall-through keyword instead.

    • @JuusoAlasuutari
      @JuusoAlasuutari Год назад +1

      #define when break; case

    • @sparky173j
      @sparky173j Год назад +2

      @@JuusoAlasuutari that's quite clever!
      In a "disgusting hack that's required to work around a poor design decision" kind of way.

    • @JuusoAlasuutari
      @JuusoAlasuutari Год назад +4

      @@sparky173j as is tradition in C ;)

    • @oleksandrnahnybida3167
      @oleksandrnahnybida3167 Год назад

      there are already -Wimplicit-fallthrough and attribute__((fallthrough))

  • @SvetlinTotev
    @SvetlinTotev Год назад +1

    In my experience with C++ 90% of the time the array size is known at compile time so I just use references to C-style arrays (typedef'd to avoid the ugly syntax). And when the size is dynamic, most of the time I need to allocate it on the heap anyways so I might as well use std::vector or std::string. All that's left are the relatively rare cases that Rust slices solve.

  • @AK-vx4dy
    @AK-vx4dy Год назад +3

    It was maybe an error but this concept is not far from Rust &str or span, readliy adopted to other langugages for speed and less allocation. Surely in safer ways but cocnept is the same.
    Even in C++ they added it again in safer form

  • @DJCloudPirate
    @DJCloudPirate Год назад +3

    Why not implement the fat pointer in overloaded malloc and free functions dedicated to arrays? In theory, the new malloc implementation could always allocate a block of memory the size required for the array but include a size_t worth of bytes before the first element in the array. It would then just return the pointer to the first array element. These pointers would be fully backward compatible with all C code since the beginning of time, but if you index from the pointer in the negative direction you will be able to access the size_t that contains the size in bytes. Since C isn't object oriented the syntax for accessing this new size information would always have been done through a new library function anyway... something like size_t length = myarr.getSize(); doesn't fit in the design of C.

    • @pierreollivier1
      @pierreollivier1 Год назад

      The simplest way I think, is to use a composite type, with typedef, you create a struct, that contains a void* data, a size_t size, and an enum for the type, that is declared with the type width, I use this a lot you just typedef it into a nice array_t, or t_array and boom you have a simple and easy to use array. you can even go a step further, and use generic functions that are only facade to fonctions pointers switch statements to redirect your array to the correct type specific functions, based on the value of your enum. ( and in some cases if the compiler is able to see that your functions are only there to redirect your array to another functions, the compiler might replace your switch statement by a look up table reducing a bit the overhead).

    • @DJCloudPirate
      @DJCloudPirate Год назад +1

      @@pierreollivier1 Yes, I think I see what you mean, and that is very much like what I proposed. This is due to the way C plays fast and loose with memory. Types in C are really just a means for calculating address offsets. Under the hood the languge doesn't really treat structs any differently than arrays... both end up doing just raw pointer math to get to what (you hope) is the desired data. The problem I see with the approach you propose is that having the void* first in your struct means that the size is dangling out at the end of the struct. In that case you actually have to do two pointer indirections to access your real data, first you have to dereference the struct to get to the void* that holds your data, then you have to compute the offset from that array head to get to the element you want. In my case there's only ever one pointer involved, the pointer to the first element in your array just like all C arrays. But in my case I leverage the fact that 99.9% of developers only ever do positive pointer offsets to sneak the extra size data in at a known offset from the pointer. That offset just happens to be negative.

    • @pierreollivier1
      @pierreollivier1 Год назад

      ​@@DJCloudPirate I understand your approach, and yes, my method is clearly a very simple one. I believe many people have used this approach at some point. However, my main point is not about the implementation details, but rather about the fact that the language already provides a way (though not optimal) to handle bounded arrays. I don't think adding more to the language would be very useful in practice. It's one of those situations where people are accustomed to the way it's done in C and may not necessarily benefit from that feature even if it were implemented. Nevertheless, I find it interesting as it reminds me of how the system keeps the heap from becoming too fragmented by adding some embedded data at each allocation.

  • @gnagyusa
    @gnagyusa 6 месяцев назад

    Yeah, I ended up implementing smart arrays in my C codebase. It was not a big deal, though. The only thing I'm missing from C is smarter function macros. I'm tired of the "\" line termination and the difficulty debugging them.

  • @xybersurfer
    @xybersurfer Год назад +2

    C offers structs to pair arrays with their length. it takes minimal effort, so i don't consider it a mistake. it being a systems programming language, it would be worse if you were forced to always have the length stored

  • @pokefreak2112
    @pokefreak2112 Год назад +16

    I always define my own "fat pointers" when I program in C. It's not just great for reducing bugs, you also get to create views/slices of larger arrays so you rarely need to allocate anything. Super nice pattern.

    • @darthvader4899
      @darthvader4899 Год назад +1

      can you please continue to cook?

    • @DFPercush
      @DFPercush Год назад +1

      I've been dealing with the Wasmer C api recently. The way they pass arrays is with a struct whatever_vec_t { size_t size; whatever* data; } It's not a bad idea, and intrinsic language support would be awesome.
      However, if you can use a C++ compiler to compile your mostly C-like code, you can use some small footprint templates to help with that. To get the size of a static array,
      template void foo( const MyType (&array)[N]) { c_function( FatPointer{array, N}); }
      I agree that being able to make sub-strings and slices without any memory allocation is great. std::string_view and std::span are staples in my code. I basically use span as the fat pointer type, as I'm sure it was intended.

    • @Sealedaway
      @Sealedaway Год назад +1

      I found that to be a fantastic feature in a physics simulation I've been working on. Minimizing the need for reallocations, instead keeping track of where the "meaningful data" is currently stored in a large buffer, does wonders for the performance. In a lot of situations it's easiest to have arrays keep track of their own size, but the fact that C doesn't do that encourages you to rethink how you handle your data and sometimes it gives you some chances to optimize for speed. As a physics major, I really appreciate C for that.

  • @jakejakeboom
    @jakejakeboom Год назад +3

    If you use all the static analysis and instrumentation your compiler provides, then C is a much safer and more usable language. Without doing that, pretty much any C program over 10k lines will have some nasty undefined behaviour lurking somewhere.

    • @stefanalecu9532
      @stefanalecu9532 Год назад

      But it won't save you from logic bugs which is even worse

  • @IantoCannon
    @IantoCannon Год назад +14

    I like the simplicity where an array with five elements is exactly five times the size of each element. Use c++ if you want a custom array type

    • @IantoCannon
      @IantoCannon Год назад +1

      Another solution is to use bounds checking in the compiler options. The code runs more slowly but it is good for testing

    • @KayOScode
      @KayOScode Год назад +3

      C is the best language in terms of its power and speed. If you look from a customers perspective, c is always the best language for any job. The problem is the limited system library and general unsafe pitfalls developers who don’t know better (and developers who do) fall into.

    • @isodoubIet
      @isodoubIet Год назад +13

      @@KayOScode " If you look from a customers perspective, c is always the best language for any job. "
      ??? C is the wrong choice for just about any job. The number of footguns is unparalleled outside of the esolang space.

    • @isodoubIet
      @isodoubIet Год назад +5

      "I like the simplicity where an array with five elements is exactly five times the size of each element."
      std::array

    • @abhinavk0929
      @abhinavk0929 Год назад +1

      ​@@isodoubIet never thought id dislike someone's comment and then like the next one lmao

  • @phitc4242
    @phitc4242 Год назад

    you code in C, I code in C, I'm just built different, so are you

  • @dziuaftermidnight
    @dziuaftermidnight 22 дня назад

    still not sure if enough people talk about the absolute beauty of a feature that C allows, that is an array pointer. if you really want to pass an array of the fixed length in the most proper way (which is, without losing it's size upon conversion to pointer), you can just pass the array pointer to the function. then, for the sake of normal syntax, you can extract the actual pointer and size of the array into different variables inside the function. only real problem with this is that you cannot pass an array of variable size, meaning you can only use it to pass arrays of certain size N across the entire program (and the size is embedded inside the array pointer).

  • @m4rt_
    @m4rt_ Год назад

    technically
    char a[]
    isn't exactly equivalent to
    char *a
    since if the length of the array is known at compile time, and not through malloc at run time, you can get the correct length with sizeof()
    ... but yeah, they are really similar.

    • @godofcows4649
      @godofcows4649 Год назад

      They are the same, though you can't change the address of a[0]. But just talking about treating them like arrays, they are the same. You're just allocating the block of bytes before run time not during; you must still keep track of the size. sizeof gets the amount of bytes during compiling because different compilers have different widths of bytes for the c's data types:
      unsigned char *a;
      a = (unsigned char*) malloc ( ARRAY_SIZE * sizeof(unsigned char) );
      going with what you said, I think structs make more sense in that context:
      typedef struct {
      unsigned int data1;
      unsigned int data2;
      unsigned long data3;
      } myCustomDataType;
      myCustomDataType twoIntsAndALong = (myCustomDataType*) malloc( sizeof(myCustomDataType) );
      if I explisedly said I wanted 8 bytes to be allocated, then it makes the code way less portable if a int or long for another compiler is not the same amount of width of bytes. Makes it more tedious too.

  • @isodoubIet
    @isodoubIet Год назад +12

    The whole "functions and arrays decay to pointers at the slightest provocation" deal is also one of the most annoying features C++ inherited from C and a big reason why std::array exists. Stuff like this is why I struggle to take opinions like "Oh C is so simple you should use C" seriously.

    • @PoorlyMadeSweater
      @PoorlyMadeSweater Год назад +9

      C is like the nunchuks of programming. Its so simple, just two sticks and a piece of string, what could go wrong?

    • @isodoubIet
      @isodoubIet Год назад

      @@PoorlyMadeSweater I used to practice with those and, ironically, they're a lot safer than C.

  • @deniyii
    @deniyii Год назад +2

    Isn’t the array decay problem fixed by passing an array pointer to a function instead of passing the array directly?

  • @warasilawombat
    @warasilawombat Год назад

    I’m really used to the void *buf, size_t size calling convention used to work around this problem, but as soon as this article pointed out this was a problem I was on board. This may not be the source of most bugs for us but it is such a huge tedious time sink to constantly need to pass the size of an array or create verbose sizeof() constructions just to deal with the problem that the size of the array is not part of the type. This is such a precise identification of a failure of C and its refreshing amongst all the bitching about modern language features.

  • @AhmetTemizTR
    @AhmetTemizTR Год назад +3

    We need C-- lang.
    a[-1] = size and a[0] = first element 😂

  • @coolworx
    @coolworx 7 месяцев назад

    Except for the occasional screeching, I'm really enjoying this channel on my headphones.

  • @sasukesarutobi3862
    @sasukesarutobi3862 Год назад +1

    You probably pronounce it like that because "char" is already a word (to burn something so that it chars), but "mut" isn't.

  • @KadenCartwright
    @KadenCartwright Год назад

    The array as a backing data structure of a string is incidental, not core to the identity of a string. Technically it could be implemented under the hood with a linked list or a tree or other more exotic things (I know this would suck in 99.9% of cases, just pointing out that strings with another backing data structure are still strings)

  • @Chris-mm
    @Chris-mm Год назад +1

    Learned haskell just so I could put the sticker on my laptop and work at a coffee shop (in Python)

  • @krisdabrowski5420
    @krisdabrowski5420 Год назад +1

    I think it's fine to pronounce char as burnt because a u8 char has almost nothing to do with an actual language characters. Coincidentally it has the latin alphabet plus some other random symbols because ASCII standard, but so much of the ASCII standard isn't language characters but things like tabs, spaces, newlines, return carriage, etc. Those aren't characters! They're dark and hidden in the ASCII standard... dark as burnt charcoal.

  • @AK-vx4dy
    @AK-vx4dy Год назад +2

    I was top one thing i envied C programmers - this mistake - in 1990 era Pascal... when i was young, brave and stupid ... now i'm only experienced stupid ;)

  • @CallousCoder
    @CallousCoder Год назад

    Assembly is code and it is data! It’s called self modifying code. I love that trick. And literally yesterday a kid asked me why to learn C. And literally my words were: “you really know how arrays works because they are not trivial to pass around.”

    • @stefanalecu9532
      @stefanalecu9532 Год назад

      So low-level Lisp/Forth?

    • @CallousCoder
      @CallousCoder Год назад

      @@stefanalecu9532 assembly language but in forth you could do the same thing since it’s a command interpreted language in which you define words. So you can generate those words based on situations and also do self modifying code.
      Although I hardly coded in forth. But in assembly 6502, 68000 and x86 I used it a lot.

  • @zytr0x108
    @zytr0x108 Год назад +1

    Can’t you just make a struct with a pointer and a size component?

  • @MrAbrazildo
    @MrAbrazildo Год назад

    7:14, the only "unsafe design" about those is that, when the vector changes its size, it's not granted to stay at the same location in memory, so the iterators keep pointing to old address. 1 just needs to "refresh" them. But this need exists only 1 time per allocation (size changing). This is not made automatically due to possible performance. It's like web pages that are always refreshing themselves vs those waiting for the user to do it: the 1st is more comfortable, but wastes performance/resources from the machine.
    The operator [] hasn't this issue, because it comes all the way from the beginning. But has a performance penalty. I personally use iterators intensively. I only had this issue once.
    8:55, agree. This is awkward because, for every 1 of the millions of f()s, the code will has this amount of lines. The way I use to do this is to write a macro only 1 time, calling it everywhere:
    #if NEWC
    #define arrpass(type, name, dim) type name[..]
    #elif C99
    #define arrpass(type, name, dim) type name[dim]
    #else
    #define arrpass(type, name, dim) type *name
    #endif
    Then f()s will be written like (doesn't matter the standard):
    extern void foo (const size_t dim, arrpass (char, a, dim));

  • @oualidel-feraoui1318
    @oualidel-feraoui1318 Год назад

    someone in the chat said "you don't talk about java. You ashamed writing it."

  • @nangld
    @nangld Год назад

    Walter Bright is that prominent person, think volumetric Terry Davis.

  • @MaxHaydenChiz
    @MaxHaydenChiz Год назад

    Re: arrays and pointers, I am pretty sure this was changed somewhat in the years since this was actually written. You can specify that a pointer argument can only have length 1 (not an array), must be not-null, that the array arg must also have an arg that specifies the length, and a few other issues.
    Compiler support for checking this statically, is hit or miss still. But it's increasingly decent.
    The string thing is horrible though. I think the way that Plan 9 handled UTF was better than any other C-library I've seen. But they aren't in widespread use and probably haven't been updated to the latest unicode standards.

  • @sergrojGrayFace
    @sergrojGrayFace 10 месяцев назад

    C's biggest mistake is relying on preprocessor. I actually love having a powerful preprocessor, but it should be a complimentary tool. In C it's used instead of proper modules and proper constants.

  • @DigitalOsmosis
    @DigitalOsmosis Год назад +1

    Alternatively you can just typedef a simple struct to achieve the same improvement without needing to change the language.
    typedef struct my_array_t {
    size_t dim;
    char * data;
    } my_array_t;
    void foo(my_array_t a);

  • @sepphuber7434
    @sepphuber7434 4 месяца назад

    The only way to fix C is being serious about static analysis. Then it's not too bad anymore.

  • @OrtiOr-in1rd
    @OrtiOr-in1rd Год назад

    this from richard mann is a concept of a helmet hacker this worst vice that the thieves have is a much worse vice than the drugs themselves and in addition to the money it is cursed to be remotely attacking other users with those intentions that this was done predators concept

  • @MaxHaydenChiz
    @MaxHaydenChiz Год назад

    Haskell isn't the top of the type complexity hill. There are Idris, Agda, Coq, and other systems that have features the Haskell people wish they had.

  • @Hector-bj3ls
    @Hector-bj3ls Год назад +1

    I'm consistent with how I say these things. Char is char with an H. Mut is like the dog. Say it how it's spelled.

  • @HrHaakon
    @HrHaakon Год назад +3

    char *a is called a char-a-starred, or charizard for short. Duh.

  • @somenameidk5278
    @somenameidk5278 11 месяцев назад

    holy shit someone finally said it, god i hate this. i'm too scared to use ever use raw arrays in c++ because it is so easy to shoot yourself in the foot with them

  • @harleyspeedthrust4013
    @harleyspeedthrust4013 Год назад +1

    lmao I wouldn't call "hasklul" the pinnacle of programming languages. idris for example is more powerful than haskell and more high level. APL is another one that's difficult but extremely powerful in a different way. i have no experience with lisp but apparently you can do crazy meta stuff with it. i do agree that rust is a step below haskell though.
    note: i'm using the blub scale here (blub programmer scale)

  • @mishaerementchouk
    @mishaerementchouk Год назад +1

    Suffices to say C does not have a built-in type "array". All it has is quite convenient syntactic sugar for operating with contiguously allocated data and the respective conceptual wrapper. That's it. If one, indeed, needs an "array", say as in linear algebra, in C, it must be properly implemented. In contrast, Fortran and Pascal (to name close languages that are still in use) had the array type before C, which makes all references to weak contemporary hardware irrelevant. So, decaying arrays to a pointer was a conscious decision. The fact that so much can be done with so little is almost a miracle and reflects how deep was that decision.

    • @MH_VOID
      @MH_VOID Год назад +3

      Seeing `#include void main() { int arr[] = {0, 42, 69}; printf("%d", 2[arr]);}` (newlines stripped) print 69 really showcases this shit to me.

    • @Sealedaway
      @Sealedaway Год назад +1

      @@MH_VOID The fact that array indexing is commutative will never cease to amuse me.

  • @davidfrischknecht8261
    @davidfrischknecht8261 8 месяцев назад

    I would say the most successful programming language is the one used in the most projects.

  • @FireDragon91245
    @FireDragon91245 Год назад

    what is it with the sagfaults
    when i first startet c it took 2 weeks of writing programms to get my 1. sagfault (a +-1 bug)

  • @k98killer
    @k98killer Год назад

    Pernacious? Wasn't he a church father from Exaldrandia?

  • @mattias3668
    @mattias3668 9 месяцев назад

    This would require that &array[index] returns an array rather than a pointer, and pointers and arrays would no longer be compatible - big fat No thank you. Also strings don't just need NUL termination because the array size is unknown, it needs it because the array may be larger than the string.

  • @quelchx
    @quelchx Год назад +1

    Rust developers are starting to sound like Python developers.

  • @replikvltyoutube3727
    @replikvltyoutube3727 Год назад

    Primagen say about Haskell programmers looking down on other ppl, but has he seen APL programmers

  • @johanngambolputty5351
    @johanngambolputty5351 Год назад

    I mean, even though you can have something like c++ with cuda or rocm, writing basically c99 for the GPU with opencl feels kinda nice.

  • @jerrygao1495
    @jerrygao1495 Год назад +1

    i use c and nim,they feels like js and react,perfect

  • @Bp1033
    @Bp1033 Год назад

    the only reason I learned C# was because of the game Space Engineers and the desire to have automatic solar arrays and mining drones.

    • @DFPercush
      @DFPercush Год назад +2

      This video is talking about C. C# is a very different animal. That's cool though, I've written a few Space Engineers scripts myself. Good motivation to learn how to code, kudos for the effort. ;)

    • @Bp1033
      @Bp1033 Год назад +1

      @@DFPercush oh, I just saw 'Cs' and was like "*.cs", I do like C. It's my home programming language.

  • @stoneHeHenge
    @stoneHeHenge Год назад +18

    So, basically Zig addresses all Cs biggest mistakes?

    • @vaisakh_km
      @vaisakh_km Год назад +1

      that's why zig born

    • @notuxnobux
      @notuxnobux Год назад +2

      Yeah, and at the same time it produces binaries that are smaller than C binaries (using musl). Hello world in zig is just 2kb. It's a sharable static binary (no runtime dependencies) on linux.

    • @krux02
      @krux02 Год назад +4

      It's not just `Zig` that have solutions for this problem. It's basically all programming languages fixed this problem. Except maybe some older ones. All fix it differently and they also added a big pile of features you never asked for.

    • @jakejakeboom
      @jakejakeboom Год назад +10

      @@krux02irrelevant when only a few languages can be a drop-in replacement for C to do systems and embedded programming.

    • @diadetediotedio6918
      @diadetediotedio6918 Год назад

      @@jakejakeboom
      Nah, there are a big bunch of pile of languages that can do systems and embedded programming.

  • @Ryan-in3ot
    @Ryan-in3ot Год назад +3

    cant you just typedef a struct with a pointer and a size_t? Or... pass in the length of the array as the second argument? I dont understand how this is "the fundamental mistake" of C.

    • @user-py9cy1sy9u
      @user-py9cy1sy9u Год назад +2

      Technically you can but the endless list of buffer overflows means people dont do that.

    • @isodoubIet
      @isodoubIet Год назад +1

      Ok now make the standard library take that instead of arrays.
      You can only go so far without environment support.

    • @Ryan-in3ot
      @Ryan-in3ot Год назад

      @@isodoubIet what functions in the c standard library even take in arrays?

    • @oleksandrnahnybida3167
      @oleksandrnahnybida3167 Год назад

      @@isodoubIet if it is not string i don’t see where is issue wifh this approach

    • @isodoubIet
      @isodoubIet Год назад

      @@Ryan-in3ot None, because you can't pass arrays with C. Functions that taken pointers meant to represent arrays though? Lots of them. scanf, strlen, strcpy, qsort, bsearch...

  • @DeathSugar
    @DeathSugar Год назад

    char stands for charcoal which is left of you stool when you've done with c's segfaults

  • @Sayan_Shankhari
    @Sayan_Shankhari Год назад

    lack of fancy libraries and bad habbits of using them in other languages

  • @DrewryPope
    @DrewryPope Год назад

    this is how you should be lit in every video. 10/10 no notes.

    • @DrewryPope
      @DrewryPope Год назад

      if you aren't a specter of light reading code to me from the ethereal realm, then i don't want to hear it.

  • @NickPaul41
    @NickPaul41 Год назад +1

    As a youtube only watcher. How do you dig up the old articles?

  • @coder_foo
    @coder_foo 4 месяца назад

    It's weird that C functions are aware of the size of lower dimensions of multi-dimensional arrays, but not the first dimension.
    Pass a 1D array to a function. The function knows the size of the objects, but the array "decays" to a pointer. Like having a string of beads, but it doesn't know how long the string is.
    Pass a 2D array. The array decays to a pointer to the first sub-array. It knows the size of that array. Like a spreadsheet, where the function knows the size of each row and cell entry, but has no idea how many rows there are.
    Pass a 3D array. Now it's a pointer to a 2D array of defined size. Like a multi-layer cake - the function knows the sizes of each layer, but no idea how many layers there are.
    Why is the first dimension the exception?

  • @pillmuncher67
    @pillmuncher67 Год назад

    Fun Fact: Bartosz Milewski is from Poland, so his name is pronounced more like Bartosh Milleffski.

  • @victorarnault
    @victorarnault Год назад +1

    Go lang was created in 2008.

  • @hld3738
    @hld3738 Год назад

    What do you mean you are coming around to Go? I thought you always liked it just for a couple things like naked returns and you can't tell everyone that you are a Rust developer.

  • @wdavid3116
    @wdavid3116 Год назад +9

    It took me a while but I really warmed up to python3's treatment of strings. Strings really aren't arrays they are the idea of textual data. That textual data can be encoded in different ways and when you encode a string it becomes an array. Of course the string has to be stored in memory and just like everything else it is a block of memory, but it conceptually is not an array.

    • @homelessrobot
      @homelessrobot Год назад

      but what does this get you? its conceptually appealing, but i don't know that i could actually generate a description of that conception other than the ole mathematicians fallacy of platonic beauty.

    • @wdavid3116
      @wdavid3116 Год назад +1

      @@homelessrobot It is similar to any other guard rail. It forces you to think about encoding and explicitly convert between the idea of text and a buffer of memory filled with encoded values. It prevents you from accidentally mixing the manipulation of text and the manipulation of an array in a way that could mess things up. It also holds your hand and makes unicode work.

  • @dovh49
    @dovh49 Год назад

    I really like V Lang. It is largely based off of Go but has built-in monads.

    • @nighteule
      @nighteule Год назад

      The V stands for Vaporware 😎

    • @dovh49
      @dovh49 Год назад

      @@nighteule I've been using it with much success! There's some features that would be nice to have. But for a newer project it works quite well.

  • @jarvenpaajani8105
    @jarvenpaajani8105 Год назад +1

    It's weird i also many times feel like writing C, but then end up feeling like shit 😂 I think its cause every time i think how something is in memory i think it as a c struct, so i unintentionally think in C

  • @sprytnychomik
    @sprytnychomik Год назад +1

    If gif is jif then git is jit and gift is jift?

    • @ThePrimeTimeagen
      @ThePrimeTimeagen  Год назад +1

      big if true
      giant will be jiant... my life is completely in shambles

  • @AvalancheGameArt
    @AvalancheGameArt 7 месяцев назад

    You are supposed to know how much data is in something you have declared.
    Pcs be like beep boop, they don't know what you want or how to do it. you tell them how to do it with what they can do.

  • @bzboii
    @bzboii Год назад

    holy shit its bartosz milewsky rearing his head bc you mentioned haskell and cpp in a video

  • @MegaMech
    @MegaMech Год назад +1

    The greatest mistake is makefile. It's the worst syntax ever written. Worse than php

  • @GiovanniCKC
    @GiovanniCKC Год назад

    C23-- the most recent version like just came out very recently lol, it is in fact very slow.

    • @JuusoAlasuutari
      @JuusoAlasuutari Год назад +1

      This makes no sense in so many different ways it's like a hypercube with all dimensions having a negative size

    • @GiovanniCKC
      @GiovanniCKC Год назад

      @@JuusoAlasuutari I'm talking about the update cycle my guy lol. Why would I be talking about literally anything else?

    • @JuusoAlasuutari
      @JuusoAlasuutari Год назад

      @@GiovanniCKC it was a little ambiguously worded

  • @br3nto
    @br3nto Год назад +1

    4:09 nooo! It’s gif as in gill… and mut as in nut and char as in charcoal… everyone one knows that… any other pronunciation is just people taking the piss

  • @mhtmhn
    @mhtmhn Год назад +3

    Coming from an embedded background (MCUs, MPUs), it's easier to visualize memory alignment using the existing implementation. I don't want any implicit bytes being used by a language feature. And what should the fatpointer's implicit 'size_t' be for 8-bit/16-bit/32-bit systems? In a system with 256 bytes of RAM(for e.g. ATtiny88), there's no need for a 32-bit size_t even if it's a uint32_t array. Standardizing this seems more of a nightmare.

  • @HappyCheeryChap
    @HappyCheeryChap Год назад

    Why no apostrophe in video title? i.e. C's

  • @Jmcgee1125
    @Jmcgee1125 Год назад +3

    I don't really get all the null hate. Having to contain an extra element with *every* pointer just seems wasteful when you can give up a single sentinel value within the pointer type. What, you actually need the zero page for data? (Sure, we could make use of the unused bits since pointers aren't actually the full 64 bits wide, but that's a lesson in "yet"). At best wrap a macro (probably as a language builtin) around the null check. Kotlin, for example, has safe calls like `val x = myArr?.length ?: -1;` - Is this the fix people rant about not having in languages like C?

    • @32gigs96
      @32gigs96 Год назад +1

      You don’t need to have extra information with every pointer. The pointer being 0 represents the empty variant in an option type so you can just use the unsigned word size representation

    • @32gigs96
      @32gigs96 Год назад +1

      This is called the “null pointer optimization” in rust

    • @Jmcgee1125
      @Jmcgee1125 Год назад

      @@32gigs96 So, a language builtin around the null check? I don't use Rust so I'm not familiar with how it does that sort of stuff.

    • @haltsmaul.
      @haltsmaul. Год назад

      Weather the programming language has an Optional, Maybe, Type? etc. doesn't matter.
      What matters is that the programming language either prevents NullPointerExceptions completely by e.g. wrapping the value in another object and having Null-Safe methods or, if added to the language retroactively, warnings and linting to alert the programmer to the danger.
      These warning should not come from programmers comments which are unreliable, but from the language itself.

    • @MH_VOID
      @MH_VOID Год назад +1

      @@Jmcgee1125 In Rust, references are never null. The generic Option enum (Rust's enums essentially being C's tagged unions, but much nicer) has two variants: Some(T), and None. The None variant is the equivalent of a null pointer, so if a function could return a null reference to a T, it'll instead return `Option` instead of `&T`. `Option.unwrap()` is the rough equivalent of forcibly deferencing - the program will crash if it's a None; Option.unwrap_unchecked() will give you the inner value without doing any checks whatsoever, making it be undefined behavior to call if the Option is the None variant. Methods like `Option.is_none()` exist, though normal usage of Options is `if let Some(foo) = fn_that_returns_an_option() { bar(foo); } else { baz(); }`. Options are part of libcore (as opposed to libstd or a 3rd party library) - even the most barebones embedded systems setup will have Options - and are used extremely extensively - they might very well be the type with the single highest usage through the entire language. Types like NonZeroU32 exist (which are just a u32/uint32_t that cannot be 0 (making one equal to 0 is undefined behavior)) with the explicit optimization that an Option is the same size as a NonZeroU32. The Rust compiler is extremely free with the optimizations it'll make (and that's half the point of all Rust's rules - the compiler can optimize in ways that other languages can only dream of), but this is an example of an explicit one you can depend on it doing.

  • @AJMansfield1
    @AJMansfield1 Год назад

    4:04 "char" is pronounced the way it is specifically so it rhymes with "star" when pronouncing that oldest most fundamental type, char*.

  • @michawhite7613
    @michawhite7613 Год назад +1

    I just pronounce "char" as "character"

  • @u9vata
    @u9vata Год назад

    Isn't Jai also fixing this?

  • @carriagereturned3974
    @carriagereturned3974 Год назад

    just started watching. I dunno why, but i will like (it's like 99% case, 1% i just don't understand or/and don't care ) it i am sure. So i hit like.

  • @notuxnobux
    @notuxnobux Год назад

    Walter Bright created the D programming language

  • @ohwow2074
    @ohwow2074 Год назад

    Lmao C++20 fixed this by giving us std::span which does the same thing but with more features coming along with it. I use it constantly in my code.

  • @chrisdaman4179
    @chrisdaman4179 Год назад +2

    GIF is pronounced like graphic. Just like char is pronounced character

    • @MH_VOID
      @MH_VOID Год назад +1

      "If God himself told me GIF is pronounced "jif", I'd say 'Okay, Jod'."

    • @ironfist7789
      @ironfist7789 Год назад

      @@MH_VOID *Zod

  • @adama7752
    @adama7752 Год назад +4

    No, a foo(char a[..]) hides the dim parameter. In C, making things explicit is the goal.

    • @InfiniteQuest86
      @InfiniteQuest86 Год назад +4

      Yeah I truly cannot understand what the complaint here is. It makes no sense. If you want a length, pass that in with the other argument. Wtf??

    • @itellyouforfree7238
      @itellyouforfree7238 Год назад

      I think the point is that if you require programmers to pass a length and a pointer as two separate arguments then they can get out of sync by accident (programmer's mistake), whereas here the suggestion is to have an array type that inherently knows its own length, which gets communicated automatically when passed as an argument. This is basically what a slice (`&[T]`) does in Rust.

    • @InfiniteQuest86
      @InfiniteQuest86 Год назад

      @@itellyouforfree7238 That seems like it has equally as many dangers. How can this be done accurately? Maybe you can track a max length...maybe. But then you still would have to pass in how much of the array you have filled in, so you don't actually get a win. In fact, by saying it tracks the length and using that field, you will introduce way more bugs when programmers rely on the length that is wrong since is not actually how much of it is used. By having to explicitly pass the length, you are telling the programmer, hey you better keep track of this and tell me the right value which avoids a ton of bugs, not introduces them.

    • @isodoubIet
      @isodoubIet Год назад

      @@InfiniteQuest86 You're conflating length and capacity.

    • @itellyouforfree7238
      @itellyouforfree7238 Год назад

      @@InfiniteQuest86 Think of it this way: "smart arrays" that own their buffer ought to have both a capacity and a length (how much is actually initialized and valid); "slices" that do not own their buffer may only have a length, since they are merely a view inside a buffer owned by someone else. At least, this is how `Vec` and `&[T]` work in Rust.