I've committed to going through the entirety of The C Programing Language in my free time over the next month and compiled my first program in it...

I've committed to going through the entirety of The C Programing Language in my free time over the next month and compiled my first program in it, praise me senpai

Thalidomide Vintage Ad Shirt $22.14

Black Rifle Cuck Company, Conservative Humor Shirt $21.68

Thalidomide Vintage Ad Shirt $22.14

  1. 2 months ago
    Anonymous

    >inb4 "why bother"
    Up to this point, my only tools of choice I've gotten particularly proficient at have been Python and JavaScript. This is fine for a lot of what I do, and yet I think I've determined that there'd be value in adding C to the list.
    How do neural network libraries like ggml actually work? What about browsers and Chromium? How do operating systems work? What about CPython itself? In order to gain insight into any of this, I have to be comfortable reading and editing the languages they are written in, and on a more philosophical level, understanding what the computer is actually doing.
    High-level languages abstract a lot of what's needed to grasp at fundamental programming, which is exactly what solving some of the biggest software problems currently out there demand. ML model packaging/quantization and cybersecurity easily comes to mind.
    Even when I go back to Pythonshit, it may be easier to tackle bugs and performance problems with understanding of what the computer is actually doing.
    And in another way, it's also a wedge to explore things like Rust and Go in the future, which just makes it easier to adapt to new project requirements. I don't think good programmers are complete specialists.

    • 2 months ago
      Anonymous

      Honestly you'd be better off getting a book on computer architecture and design. You'll still likely learn C along the way but it's the actual functioning of the hardware itself that matters, not the syntax of C. Also the way C deals with memory and such is clarified through an understanding of the underlying hardware.

    • 2 months ago
      Anonymous

      >High-level languages abstract a lot of what's needed to grasp at fundamental programming
      Then why are you thinking of learning c? It is also a high level language. If you want low, learn assembly.

  2. 2 months ago
    Anonymous

    You can learn the whole language in one afternoon.

    • 2 months ago
      Anonymous

      this, 99% of what you would use in C can be learnt in one day, gcc is a good compiler so if you dont remember trivial things you will learn by force.
      >but when i say C what i mean is the low level of programmjng and hardware!
      ok then

  3. 2 months ago
    Anonymous

    Never omit the braces on for/while/if/else. You also no longer need to declare variables separately from initialising them, so you write stuff like:
    int upper = 300;

    • 2 months ago
      Anonymous

      Don't listen to this anon he's a fricking moron. Everyone cringes to single line statements with brackets

      • 2 months ago
        Anonymous

        >Everyone cringes to single line statements
        >cringes to
        sirs…

    • 2 months ago
      Anonymous

      Don't listen to this anon he's a fricking moron. Everyone cringes to single line statements with brackets

      >Everyone cringes to single line statements
      >cringes to
      sirs…

      It's not recommended for beginners but it's fine if you know what you're doing. It's to avoid (phoneposting so this might look bad):

      for(i = 0; i < end; i += increment)
      do_thing(i);
      this_is_not_in_the_loop();

      https://i.imgur.com/3l5fDEj.png

      I've committed to going through the entirety of The C Programing Language in my free time over the next month and compiled my first program in it, praise me senpai

      Worth noting that C89, the ANSI standard the book teaches (with the book predating the standard iirc, if only by a little bit), requires variable declarations at the start of the scope, which is also helpful for organization - when I optimize C code I first look at the variables being used, then how they're being used, then what the return value is of the function. Unless you're working with old C compilers you're probably fine.

      • 2 months ago
        Anonymous

        >for(i = 0; i < end; i += increment)
        >do_thing(i);
        >this_is_not_in_the_loop();
        More error-prone when immediately expanded upon.
        If you have the freedom to decide, I'd always enforce them.

  4. 2 months ago
    Anonymous

    inshallah you do the same tomorrow and the day after tomorrow and the day after the day after tomorrow
    good luck brother and never give up!

  5. 2 months ago
    Anonymous

    anon it's like 5 symbols and the most basic of syntax, if it takes you a month to learn it, then you're unironically ngmi.

  6. 2 months ago
    Anonymous

    Stop being a baby and learn the entirety of the C++ language, that will change your life.

    • 2 months ago
      Anonymous

      Is learning the entirety of the C++ language achievable natty?

      • 2 months ago
        Anonymous

        no, you need to juice with hrt

      • 2 months ago
        Anonymous

        >natty
        ngmi, you think this is natty?

        • 2 months ago
          Anonymous

          Why'd you post photoshopped version?

          • 2 months ago
            Anonymous

            >Dorf goes programming

  7. 2 months ago
    Anonymous

    anon@anon:~/Downloads$ cat fahr.c
    #include <stdio.h>
    int main(void) {
    int temp = -20;
    while ((temp += 20) < 320) {printf("%4dF => %6.1fCn", temp, (temp - 32) * 5.0 / 9.0);}
    return 0;
    }
    anon@anon:~/Downloads$ gcc -o fahr fahr.c && chmod +x fahr && ./fahr
    0F => -17.8C
    20F => -6.7C
    40F => 4.4C
    60F => 15.6C
    80F => 26.7C
    100F => 37.8C
    120F => 48.9C
    140F => 60.0C
    160F => 71.1C
    180F => 82.2C
    200F => 93.3C
    220F => 104.4C
    240F => 115.6C
    260F => 126.7C
    280F => 137.8C
    300F => 148.9C

    All of it intentional.
    When dividing integers into floats, you want the integer to be a big as possible to have the minimum-resolution aliasing-biases cancelled out. But ignore what I just said.

    • 2 months ago
      Anonymous

      Alternatively, you could
      int temp = 0;
      do {...} while ((temp +=20) < 320);

      if starting at -STEP is just too weird a concept for you.

      • 2 months ago
        Anonymous

        https://godbolt.org/z/snvrfvYKx
        Seems to be two jumps less in assembly than using a straight while.
        I mean, you have the assurance of the problem given that you can guarantee the first input is sane by means of setting it, which allows you to perform the first iteration without a conditional preclause.

    • 2 months ago
      Anonymous

      and

      https://godbolt.org/z/snvrfvYKx
      Seems to be two jumps less in assembly than using a straight while.
      I mean, you have the assurance of the problem given that you can guarantee the first input is sane by means of setting it, which allows you to perform the first iteration without a conditional preclause.

      >https://godbolt.org/z/snvrfvYKx
      produce identical code when compiled with -O3, lol.

  8. 2 months ago
    Anonymous

    Fricking cniles when will they learn
    fn main() {
    (0..=300)
    .map(|f| (f, (5. / 9.) * (f as f32 - 32.*~~
    .for_each(|(f, c)| println!("{}F =>t{:.01}C", f, c))
    }

    Let me guess, writing a shitty for loop really taught you computers.

    • 2 months ago
      Anonymous

      Don't make fun of this kid for trying to learn
      Read the thread you horse's ass

    • 2 months ago
      Anonymous

      What are you talking about, little Rustlet? That's basically just the glorified version of

      anon@anon:~/Downloads$ cat fahr.c
      #include <stdio.h>
      int main(void) {
      int temp = -20;
      while ((temp += 20) < 320) {printf("%4dF => %6.1fCn", temp, (temp - 32) * 5.0 / 9.0);}
      return 0;
      }
      anon@anon:~/Downloads$ gcc -o fahr fahr.c && chmod +x fahr && ./fahr
      0F => -17.8C
      20F => -6.7C
      40F => 4.4C
      60F => 15.6C
      80F => 26.7C
      100F => 37.8C
      120F => 48.9C
      140F => 60.0C
      160F => 71.1C
      180F => 82.2C
      200F => 93.3C
      220F => 104.4C
      240F => 115.6C
      260F => 126.7C
      280F => 137.8C
      300F => 148.9C

      All of it intentional.
      When dividing integers into floats, you want the integer to be a big as possible to have the minimum-resolution aliasing-biases cancelled out. But ignore what I just said.

      .
      Also, look at that syntax, I mean, my coding style is obviously notorious, but your is basically standard Rust coding style, and it looks just as bad as C++'s, if not, worse.

      • 2 months ago
        Anonymous

        Almost nobody actually uses for_each, this is enthusiast code golfer style. If I had to review this code I'd ask to extract the calculation into a function and use a for loop.

        • 2 months ago
          Anonymous

          it's this moron:

          [...]

          >loops are basically a code smell
          meanwhile in the real world
          https://doc.rust-lang.org/std/iter/trait.Iterator.html#method.for_each
          >It’s generally more idiomatic to use a for loop
          >for_each may be more legible when processing items at the end of longer iterator chains

          • 2 months ago
            Anonymous

            NTA but for loops are usually state mutation, it is a code smell.

          • 2 months ago
            Anonymous

            lol

            what does the spec have to do with compiler optimization?

            can you guarantee that your code is going to compile down to a simple loop at the hardware level? this is NOT how iterators are defined in the standard library, so you're relying on compiler magic to make your code as fast as a for loop

          • 2 months ago
            Anonymous

            Why would you want a simple loop instead of unrolling?

          • 2 months ago
            Anonymous

            you don't want to unroll 300 println statements (you should see how it looks after the macro is expanded, lmao)
            but that's besides the point, the definition of a for loop matches the assembly output while iterators do not, the compiler has to figure out what you meant and transform it into something completely different

          • 2 months ago
            Anonymous

            So does the spec enforce the lack of unrolling or not?

          • 2 months ago
            Anonymous

            a for loop is performant without optimization
            iterators aren't, so you need some sort of guarantee that the compiler will optimize them for you

            I've found the compiler reliable enough for this

            that's great, no one will write a competing compiler because it might optimize code differently than rustc and make your code run like shit
            read this if you want a headache: https://rustc-dev-guide.rust-lang.org/building/bootstrapping.html

          • 2 months ago
            Anonymous

            >a for loop is performant without optimization
            lmao

          • 2 months ago
            Anonymous

            Inlining and monomorphization can do a lot. The more creative optimizations are actually implemented in the standard library. I haven't heard any worries about this for GCC-rs or the various non-LLVM rustc backends. C++ developers also seem to trust that a lot of their abstractions will get optimized away by any reasonable compiler, they love their zero cost abstractions.
            I have no clue how that bootstrapping process is supposed to relate to compiler optimizations. I've gone through it before since I contribute to Rust sometimes.

          • 2 months ago
            Anonymous

            >the definition of a for loop matches the assembly
            Does it, now? Please entertain me with few more of your utterly clueless takes, cnile brainlet.

          • 2 months ago
            Anonymous

            >Does it, now?
            yeah? clang is obviously trying to be clever here, but if you disable optimizations it literally compiles down to a cmp+jge+jmp

            >a for loop is performant without optimization
            lmao

            for loops are syntactic sugar for while loops which can be directly expressed in machine code

          • 2 months ago
            Anonymous

            >if you disable optimizations
            And what if the user wants optimizations?
            Can you tell me the involvement of the spec in all these?

          • 2 months ago
            Anonymous

            is your "clever" feature usable as defined without optimizations? if you're python the answer is always yes
            if you're a "systems language" i would like some sort of guarantee at least, tell me how iterators will be transformed when compiling
            language specs often mandate these sorts of things when the idiomatic style hurts performance, like scheme requiring tail call optimization

            Inlining and monomorphization can do a lot. The more creative optimizations are actually implemented in the standard library. I haven't heard any worries about this for GCC-rs or the various non-LLVM rustc backends. C++ developers also seem to trust that a lot of their abstractions will get optimized away by any reasonable compiler, they love their zero cost abstractions.
            I have no clue how that bootstrapping process is supposed to relate to compiler optimizations. I've gone through it before since I contribute to Rust sometimes.

            >C++ developers also seem to trust that a lot of their abstractions will get optimized away by any reasonable compiler, they love their zero cost abstractions
            i haven't said a single good thing about C++
            >I've gone through it before since I contribute to Rust sometimes
            makes sense why you would be so eager to defend it then
            i hope you aren't doing unpaid labor for the rust foundation in their quest to kill the GPL

          • 2 months ago
            Anonymous

            C++ has lots of problems that C++ developers will readily admit to and this does not seem to be one of them. Like, you expect this to be a problem, and I see why you expect it, but in practice it's not a big deal.

            Fixing your bugs (step by 20) and better code (I think):
            fn main() {
            (0..=300).step_by(20)
            .map(|f| (f, 5. / 9. * (f - 32) as f32))
            .for_each(|(f, c)| println!("{f:4}F => {c:6.1}C"))
            }

            [...]
            I think in this case, because it's simple, it looks worse in a for loop as it's more lines and creates an additional variable which is not used later
            fn main() {
            let temps = (0..=300).step_by(20)
            .map(|f| (f, 5. / 9. * (f - 32) as f32));

            for (f, c) in temps {
            println!("{f:4}F => {c:6.1}C");
            }
            }

            Also turning the closure into a function doesn't really make sense here because it returns a tuple which is part of an esoteric computation, not the temperature in Celsius. If it only returned the Celsius then it would be okay as a function but you'd need to recreate the range to print properly

            My suggestion is to drop the map, write an explicit top-level function for the conversion, and do the conversion in the loop body.

          • 2 months ago
            Anonymous

            (a top-level function that takes a f32 and returns a f32, not a tuple, to be clear)

          • 2 months ago
            Anonymous

            >you expect this to be a problem, and I see why you expect it, but in practice it's not a big deal
            it will be a problem when you're 10 years in the future, rust has won and you're writing code for some obscure microcontroller with a proprietary compiler
            i want my languages to be minimal, simple and predictable, which rust and C++ most definitely are not
            a language like C, maybe with go-like syntax and a rust-like borrow checker would be great, but that's never going to get made because it's not flashy or marketable

          • 2 months ago
            Anonymous

            Oh, Rust may be a poor fit for microcontrollers, I can believe that. I've fixed some code size snafus that are merely unfortunate on the platforms I target but would be much more problematic if you have that little storage. (There's decent tooling for finding those issues at least.)
            My hope would be that if Rust is unsuitable for those platforms it doesn't get adopted there. It's a great tool for my own use cases.
            I would also love to see better simple languages in addition to better complex languages.

          • 2 months ago
            Anonymous

            >i want my languages to be minimal, simple and predictable, which rust and C++ most definitely are not
            C isn't either.

          • 2 months ago
            Anonymous

            It is compared to C++ and Rust.
            Most importantly it's possible to write a pretty simple and predictable C compiler. C++ and Rust compilers are necessarily very complex. There are very complex C compilers with unpredictable optimizations but the language doesn't require it (despite the complexity of the standard).
            t. Rust enthusiast

          • 2 months ago
            Anonymous

            Yeah I realised after lol. This is closer to the C version but I still used a closure in order not to have to type it but also I guess there wouldn't be a need to have it available to every other function, idk:
            fn main() {
            let celsius = |f| 5. / 9. * (f - 32) as f32;
            for f in (0..=300).step_by(20) {
            println!("{:4}F => {:6.1}C", f, celsius(f));
            }
            }

            Idk which is better

            Fixing your bugs (step by 20) and better code (I think):
            fn main() {
            (0..=300).step_by(20)
            .map(|f| (f, 5. / 9. * (f - 32) as f32))
            .for_each(|(f, c)| println!("{f:4}F => {c:6.1}C"))
            }

            [...]
            I think in this case, because it's simple, it looks worse in a for loop as it's more lines and creates an additional variable which is not used later
            fn main() {
            let temps = (0..=300).step_by(20)
            .map(|f| (f, 5. / 9. * (f - 32) as f32));

            for (f, c) in temps {
            println!("{f:4}F => {c:6.1}C");
            }
            }

            Also turning the closure into a function doesn't really make sense here because it returns a tuple which is part of an esoteric computation, not the temperature in Celsius. If it only returned the Celsius then it would be okay as a function but you'd need to recreate the range to print properly

          • 2 months ago
            Anonymous

            anon@anon:~/code/1t$ cat floop.c
            #include <stdio.h>
            int f1(int a, int b) {
            int sum = 0;
            for (int i = a; i < b; i++) {sum += i;}
            return sum;
            }
            int f2(int a, int b) {
            int span;
            if ((span = b - a) > 0) {int ret = span * a; while (--span) {ret += span;} return ret;} else {return 0;}
            }
            int main(void) {
            int a = 2, b = 11;
            printf("%dn", f1(a, b));
            printf("%dn", f2(a, b));
            return 0;
            }
            anon@anon:~/code/1t$ gcc -o floop floop.c && chmod +x floop && ./floop 16
            54
            54

            Godbolt with -O3:
            https://godbolt.org/z/zax3vYGs6

            Looks the same at first glance, but f2 uses .jle instead of .jbe in the entry, so it's definitely not identical.

          • 2 months ago
            Anonymous

            Oh yeah, obviously this is just wankistry, unless there is a CPU instruction to give me the sum of all numbers leading up to n.
            There's a math term for it, it's not faculty, that's product, not sum.

          • 2 months ago
            Anonymous

            >faculty
            *factorial

          • 2 months ago
            Anonymous

            int f3(int a, int b) {
            int sum = 0;
            while (a < b) {sum += a++;}
            return sum;
            }

            Derp. I wonder if it's possible to increment in the conditional by presetting a or maybe b around a bit, but that's just wankistry as well.
            https://godbolt.org/z/M5YEr3oe3

          • 2 months ago
            Anonymous

            >while (a < b) {sum += a++;}
            Oh yeah, consider a and b are both unsigned (and therefore, everything about them is well-defined in the standard, i.e. including overflow) and b is MAX_INT 0xf....f and you use <=, it would infinite loop, hence the habit of avoiding LE/GE and preferring LT/GT.

            You may ask yourself why use unsigned, well, the function int sum(int a, int b) {return a+b;)} technically produces UB because it is left up to the implementation (the compiler) what to do when the result would be bigger than the biggest number that can be contained in an int. That case is called an overflow and in unsigned, it is defined to wrap around, meaning it has no UB-issues inherent to it.
            This is super-1337-advanced level shit, so ignore that if you're a noob and it confuses you.

            Yes, yes, if you ask me, defaulting to signed instead of unsigned was a big mistake we have to live with now.
            That's what you can take away.

          • 2 months ago
            Anonymous

            int f3(int a, int b) {
            int sum = 0;
            while (a < b) {sum += a++;}
            return sum;
            }

            Derp. I wonder if it's possible to increment in the conditional by presetting a or maybe b around a bit, but that's just wankistry as well.
            https://godbolt.org/z/M5YEr3oe3

            All three f1, f2 and f3 have unique ASM assembly fingerprints, at least on -O2.
            With -O3, it seems some sort of vectorization starts to take hold and the picture is somehwat muddier.

            All three have their uses and implementations:
            If you can do f1, you can write good and solid C code. Keep it simple.
            If you can do f2, you can do game engine black magic, it's looped instructions are the shortest at the cost of having the longest function entry setup.
            If you can do f3, you've got them embedded smarts.

          • 2 months ago
            Anonymous

            LLVM magic

          • 2 months ago
            Anonymous

            I've found the compiler reliable enough for this

        • 2 months ago
          Anonymous

          There are increasing gains to be made with scale and scope when for_each and map/apply/lamda/whatever can be assumed to be vectorizable.
          It doesn't apply to this simple algorithm, but they have their place where the tradeoff of using a higher-level abstracted language instead of manually doing it all in C is an acceptable one.
          Juggling around with text data from config files and JSONs is certainly something I'd rather do in Python than in C.

          • 2 months ago
            Anonymous

            >It doesn't apply to this simple algorithm
            Because the slowest part of the code is the repeated printf() call, but it is rather used as a debug of the code than the intention of the algorithm.
            It would be faster, in both C and Rust I would assume, to concatenate the total output text, which would mean working on an array of values, etc., etc., ultimately, in C, with this problem you'd just printf the final output as one call as the ultimate optimization, since everything about input and output is known, lol.

          • 2 months ago
            Anonymous

            I like iterator chains and use them a lot, to be clear, I was commenting on this specific code. They can make things more clear, performance aside.

            >It doesn't apply to this simple algorithm
            Because the slowest part of the code is the repeated printf() call, but it is rather used as a debug of the code than the intention of the algorithm.
            It would be faster, in both C and Rust I would assume, to concatenate the total output text, which would mean working on an array of values, etc., etc., ultimately, in C, with this problem you'd just printf the final output as one call as the ultimate optimization, since everything about input and output is known, lol.

            >It would be faster, in both C and Rust I would assume, to concatenate the total output text, which would mean working on an array of values, etc., etc.
            In Rust you could write into a BufWriter to get this, C does it implicitly if stdout is not a terminal

        • 2 months ago
          Anonymous

          >Almost nobody actually uses for_each
          I use it all the time.
          for-loop syntax isn't the same.

          • 2 months ago
            Anonymous

            It's not fully equivalent and not superfluous but in my local cargo index I have 40 times as many for loops as for_each calls, it's not the usual way to write that code

    • 2 months ago
      Anonymous

      lol this Black person again
      that's 600 function calls (excluding the println macro soup)
      >b-but the compiler will optimize it!!!
      maybe, who knows? is that in the spec? oh right, rust doesn't even have a formal specification

      • 2 months ago
        Anonymous

        >FUNCTION BAD BECAUSE.... BECAUSE IT'S JUST BAD OKAY??
        Cry harder cnile brainlet

        • 2 months ago
          Anonymous

          don't forget to thank your branch predictor for his service

      • 2 months ago
        Anonymous

        what does the spec have to do with compiler optimization?

    • 2 months ago
      Anonymous

      Fixing your bugs (step by 20) and better code (I think):
      fn main() {
      (0..=300).step_by(20)
      .map(|f| (f, 5. / 9. * (f - 32) as f32))
      .for_each(|(f, c)| println!("{f:4}F => {c:6.1}C"))
      }

      Almost nobody actually uses for_each, this is enthusiast code golfer style. If I had to review this code I'd ask to extract the calculation into a function and use a for loop.

      I think in this case, because it's simple, it looks worse in a for loop as it's more lines and creates an additional variable which is not used later
      fn main() {
      let temps = (0..=300).step_by(20)
      .map(|f| (f, 5. / 9. * (f - 32) as f32));

      for (f, c) in temps {
      println!("{f:4}F => {c:6.1}C");
      }
      }

      Also turning the closure into a function doesn't really make sense here because it returns a tuple which is part of an esoteric computation, not the temperature in Celsius. If it only returned the Celsius then it would be okay as a function but you'd need to recreate the range to print properly

  9. 2 months ago
    Anonymous

    That book is pure soul.
    I have no idea why it costs $50 tho.

  10. 2 months ago
    Anonymous

    Good job anon, learning things is always useful and fun. Don't listen to any naysayers and hope you do great

  11. 2 months ago
    Anonymous

    cniles don't understand how compilers work.

    • 2 months ago
      Anonymous

      >says the guy who uses std::vector functions
      yeah the compiler optimize those...

  12. 2 months ago
    Anonymous

    >the entirety of The C Programing Language
    It's a short book. But I suppose the exercise can be challenging if you are a complete beginner.
    It terms of content and programming style it is quite dated at this point but as a book it's still superb so I wouldn't necessarily recommend something else.
    Best of luck to you.

  13. 2 months ago
    Anonymous

    You all need to calm the frick down.

  14. 2 months ago
    Anonymous

    I don't want to be mean but there is literally nothing "C" about this code if you know what I mean. The exact same code (with minimal syntax changes) would run in almost every high level programming language. You didn't learn C, you learned how to write JavaScript or Python or whatever in C syntax, which doesn't help you understand or write real C code.

Your email address will not be published. Required fields are marked *