10 ms·
Hacktical C: practical hacker's guide to the C programming language
- kelsey978126 2y ago[flagged]
- qsort 2y agoIt's the original meaning of the word. This complaint is kind of ironic considering the site you're posting on :)
- akdev1l 2y ago> Microsoft has unfortunately chosen to neglect C for a long time, its compilers dragging far behind the rest of the pack. Is this still true? MSVC is pretty good at compiling C++ nowadays
- chaosite 2y agoMSVC always focused on C++, and C was treated as an afterthought.
- pjmlp 2y agoThe irony is that Microsoft was the very last MS-DOS compiler vendor to support C++ in their C tooling with Microsoft C/C++ 7 in 1992, that changed with the release of Visual C++ in 1993.
- qsort 2y agoI think he's referring to C specifically, not C++. It's true that modern versions of MSVC are compliant (and they're also typically faster at implementing features than gcc and clang), but for the longest time there were subtle differences in their C library. To this day I don't think they support VLAs, which are technically standard C (At least until recently, I'm not sure about the latest versions, hopefully someone more knowledgeable can say more).
- akdev1l 2y agoI see. I kind of assumed improving the C++ compiler required improving the C parts as well. VLA situation seems complex: https://stackoverflow.com/questions/55696680/in-which-versions-of-the-c-standard-are-variable-length-arrays-not-part-of-the-l https://stackoverflow.com/questions/55696680/in-which-versio...
- DobarDabar 2y agoCompare performance, features or anything of Clang and MSVC and you'll see the differences.
- shakna 2y agoFor C (not C++), MSVC got C17 in 2020, apart from VLAs - which are never planned. No real roadmap for if/when it will get C23 - which is not just fully implemented in GCC, but the default used standard.
- pjmlp 2y agoThey are talking about C not C++, for Microsoft C was done, it was about time to move into C++. This was the official position in 2012, https://herbsutter.com/2012/05/03/reader-qa-what-about-vc-and-c99/ https://herbsutter.com/2012/05/03/reader-qa-what-about-vc-an... However after the Microsoft reboot with Satya, there was a change of heart regarding C, back in 2020, with C11 and C17 being supported, https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-support-arriving-in-msvc/ https://devblogs.microsoft.com/cppblog/c11-and-c17-standard-... And 2022 https://devblogs.microsoft.com/cppblog/c11-atomics-in-visual-studio-2022-version-17-5-preview-2/ https://devblogs.microsoft.com/cppblog/c11-atomics-in-visual... However there is no official roadmap regarding C23 support, and now with the whole safety discussion going on and Secure Future Initiative, probably will never happen. Additionally clang is a blessed compiler at Microsoft, it is included on Visual Studio, so whatever MSVC doesn't support can be done in clang as alternative.
- HexDecOctBin 2y agoThey have added one feature (typeof) from C23, so maybe they will add the rest when they release C++26. Or maybe they won't. Microsoft is an expert in inflicting the cruelty of providing just enough hope.
- pjmlp 2y agoC++26? There are having issues with delivering C++23, since the whole change in security focus with Rust, Go, C#, Java first, C and C++ for existing codebases, and most likely one of the reasons Herb Sutter is no longer at Microsoft. https://developercommunity.visualstudio.com/t/Implement-C23-Standard-features-in-MSV/10777419 https://developercommunity.visualstudio.com/t/Implement-C23-... https://developercommunity.visualstudio.com/t/Implement-C26-Standard-features-in-MSV/10777423?q=C%2B%2B26 https://developercommunity.visualstudio.com/t/Implement-C26-... Security changes, https://azure.microsoft.com/en-us/blog/microsoft-azure-security-evolution-embrace-secure-multitenancy-confidential-compute-and-rust/ https://azure.microsoft.com/en-us/blog/microsoft-azure-secur... https://blogs.windows.com/windowsexperience/2024/11/19/windows-security-and-resiliency-protecting-your-business/ https://blogs.windows.com/windowsexperience/2024/11/19/windo...
- camel-cdr 2y agoMicrosoft took 30 years to implement a C89 compatible preprocessor: https://docs.microsoft.com/en-us/cpp/preprocessor/preprocessor-experimental-overview?view=msvc-170 https://docs.microsoft.com/en-us/cpp/preprocessor/preprocess...
- lou1306 2y ago> Using a stricter language helps with reducing some classes of bugs, at the cost of reduced flexibility in expressing a solution and increased effort creating the software. First of all, those languages do not "help" "reducing" some classes of bugs. They often entirely remove them. Then, even assuming that any safe language with unsafe regions (Rust, C#, etc) would not give you comparable flexibility at a fraction of the risk... if your flexible, effortless solution contains entire classes of bugs, then there is no point in comparing "effort". You should at least take into account the effort in providing a software with a high confidence that those bugs are not there.
- immibis 2y agoIf the language has unsafe regions, it doesn't entirely remove classes of bugs, since they can still occur in unsafe regions. (Predictable response: "But they can only occur in unsafe regions which you can grep for" and my response to that: "so?")
- guappa 2y agoUsually they can also happen outside, if you did something wrong in the unsafe region. edit: I'm sorry that my captain obvious moment is turning out to be some truth bomb for some. Please keep downvoting as a way to regain your inner peace.
- Hackbraten 2y ago> if you did something wrong in the unsafe region. *you or anyone else in your chain of dependencies that use unsafe
- sjamaan 2y agoI suppose the better response is that it removes those classes of bugs where they are absolutely unnecessary. Tricky code will always be tricky, but in the straightforward 80% (or more) of your code such bugs can be completely eliminated. It's unfortunate that C has so many truly unnecessary bugs which are only caused by stupid overly "clever" exploitation of undefined behaviour by compilers.
- throwaway7894 2y ago#define hc_task_yield(task) do { task->state = __LINE__; return; case __LINE__:; } while (0) That's just diabolical. I would not have thought to write "case __LINE__". In the case of a macro, using __LINE__ twice expands to the same value where the macro is used, even if the macro has newlines. It makes sense, but TIL.
- veltas 2y agoCredit to Simon Tatham https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html https://www.chiark.greenend.org.uk/~sgtatham/coroutines.html
- makeset 2y agoI knew the name sounded familiar: Simon Tatham's Portable Puzzle Collection https://www.chiark.greenend.org.uk/~sgtatham/puzzles/ https://www.chiark.greenend.org.uk/~sgtatham/puzzles/
- dwattttt 2y agoAlso author of PuTTy
- quietbritishjim 2y ago> no commonly used high level language supports the coroutine call primitive Shows how old this post is. In fact I remember reading it well over 10 years ago, maybe more like 20. archive.org says that it's at least as old as 2001. A great article. I'm very excited to see he's published a new article on C++20 coroutines. I've read (or maybe skimmed...) a few introductions and not really got them, despite having used C# and Python coroutines a lot with no problems (even making changes to an async runtime for Python). Given how clear his C coroutine article is, I'm optimistic about the C++ article. > So, after the course, I went away and studied on my own, and wrote the introduction to C++ coroutines that I’d have liked to see. https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/coroutines-c++20/ https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/corou...
- pjmlp 2y ago> The reason I believe C is and always will be important is that it stands in a class of its own as a mostly portable assembler language, offering similar levels of freedom. When your computer is a PDP-11, otherwise it is a high level systems language like any other.
- pornel 2y agoLess controversially, when you write C, you write for a virtual machine described by the C spec, not your actual hardware. Your C optimizer is emulating that VM when performing symbolic execution, and the compiler backend is cross-compiling from it. It's an abstract hardware that doesn't have signed overflow, has a hidden extra bit for every byte of memory that says whether it's initialized or not, etc. Assembly-level languages let you write your own calling conventions, arrange the stack how you want, and don't make padding bytes in structs cursed.
- aninteger 2y ago> Less controversially, when you write C, you write for a virtual machine described by the C spec, not your actual hardware. Isn't this true for most higher level languages as well? C++ for instance builds on top of C and many languages call into and out of C based libraries. Go might be slightly different as it is interacting with slightly less C code (especially if you avoid CGO).
- bmandale 2y agoThese are all such nonsensical misinterpretations of what people mean when they say C is "low level". You absolutely don't write C for the C abstract machine, because the C spec says nothing about performance, whereas performance is one of the primary reasons people write C. The existence of undefined behaviour isn't proof that there is a C "virtual machine" that code is being run on. Undefined behaviour is a relaxation of requirements on the compiler. The C abstract machine doesn't not have signed overflow, rather it allows the compiler to do what it likes when signed overflow is encountered. This is originally a concession to portability, since the common saying is not that C is close to assembly, but rather that it is "portable" assembler. It is kept around because it benefits performance, which is again one of the primary reasons people write C.
- 9d 2y ago> C doesn't try to save you from making mistakes. It has very few opinions about your code and happily assumes that you know exactly what you're doing. Freedom with responsibility. I love C because it doesn't make my life very inconvenient to protect me from stubbing my toe in it. I hate C when I stub my toe in it.
- OCASMv2 2y agoNo, it just makes it inconvenient to try to protect yourself from stubbing your toe in it.
- codr7 2y agoC doesn't make anything inconvenient, that's its major appeal. Some things are convenient by design, yes, but it's not trying to prevent you from doing anything. That's a feature.
- OCASMv2 2y ago> C doesn't make anything inconvenient Other than writing memory safe code, as history has shown.
- codr7 2y agoDifficult, not inconvenient. Because it allows things that are difficult, like writing your own memory allocators. If you don't like working at that difficulty level, then C programming isn't for you. And that's fine.
- OCASMv2 2y agoIt doesn't allow me to write my own memory allocator, it forces me to. This line of argumentation reminds me of this: Advertise and promote a shortcoming or a fault as a virtue. For example, ultra-cheap single-use film cameras are advertised as "No Focusing Required." The truth is, no focusing is possible, because those cameras have cheap plastic fixed-focus lenses that won't move and can't be focused. What is a serious shortcoming for a camera — the inability to properly focus on the subject — is sold as a convenience: "You don't have to bother with focusing." https://orangepapers.eth.limo/orange-propaganda.html#make_virtue https://orangepapers.eth.limo/orange-propaganda.html#make_vi...
- throwaway7894 2y agoAs someone who has a file with similar hacks, I will say this: I am not a C++ fan, but if you find yourself writing C code where you simulate methods via structs with function pointers often, just use C++ as a basic "C with classes" at that point. You want methods anyway, you have to go through a pointer dereference to call the function, it's just not worth the code weirdness. If you have the grit to use structs with function pointers everywhere, you have the grit to stick to the simpler subset of C++.
- uecker 2y agoWhy? I do not find the syntactic sugar C++ adds very helpful and it misses other C features.
- ryao 2y agoPerhaps he wants to jump through hoops to avoid function pointers, even when doing that in C++ for optional functions like is done in the VFS requires gymnastics: https://godbolt.org/z/4GWdvsz6z https://godbolt.org/z/4GWdvsz6z That is the closest I can get it to implementing an optional function via a C++ class member function instead of a function pointer. It is not only insane, but also masochistic in comparison to how it would be done via function pointers: https://godbolt.org/z/qG3v5zcYc https://godbolt.org/z/qG3v5zcYc
- unclad5968 2y agoI'm torn. The step from C to any c++ is big. Now if you want anybody to be able to use your code they need to be using c++ or you have to provide a C api anyway. On the other hand, manually implementing vtables is annoying. Ive been sticking to pure C and haven't been bothered enough to go back to any c++ yet (about 6 months on my current project). I mostly only miss templated containers so far.
- ryao 2y agoIt is more annoying to want to implement an optional function in a class and then have no simple way to check if that optional function is implemented in the object without, having to edit code that guards the call sites every time you add a derived class that implements it, or having to implement your own way of querying the object to know if it is supported.
- steinuil 2y agoSome points about the introduction, but otherwise this seems like an interesting collection of (slightly deranged?) patterns in C. > The truth is that any reasonably complicated software system created by humans will have bugs, regardless of what technology was used to create it. "Drivers wearing seatbelts still die in car accidents and in some cases seatbelts prevent drivers from getting out of the wreckage so we're better off without them." This is cope. > Using a stricter language helps with reducing some classes of bugs, at the cost of reduced flexibility in expressing a solution and increased effort creating the software. ...and a much smaller effort debugging the software. A logic error is much easier to reason about than memory corruption or race condition on shared memory. The time you spend designing your system and handling the errors upfront pays dividends later when you get the inevitable errors. I'm not saying that all software should be rewritten in memory-safe languages, but I'd rather those who choose to use the only language where this kind of errors regularly happens be honest about it.
- codr7 2y agoDebugging from specific classes of bugs, yes. I'm not trying to hide anything, just help shift the balance back to common sense.
- _false 2y agoHonest q: after skimming through the book it's unclear how it's targeted towards hackers (c.f. academics)?
- codr7 2y agoDefined as practical, curious problem solvers, I'm aware the word has other interpretations.
- talles 2y agoAny quick way to make a PDF out of this?
- theiasson 2y agoYou'll need pandoc and xelatex $ pandoc --pdf-engine=xelatex --toc README.md {macro,fix,list,task,malloc1,vector,error,set,malloc2,dynamic,stream1,slog}/README.md -o book.pdf
- teo_zero 2y agoBeware that the second section about fixed-point arithmetic is actually about floating point with exponent in base 10. Besides, the operations are all wrong and only work for trivial values of the exponents, like 0, 1 and 2.
- Calwestjobs 2y ago"These days; many programmers will recommend choosing a stricter language, regardless of the problem being solved. Most of those programmers wouldn't trust themselves with the kind of freedom C offers, many haven't even bothered to learn the language properly." Same thing people said about other people not compiling by hand lol.
- hresvelgr 2y agoThe people I've met who have made similar remarks about C have authored some of the most heinous pointer tomfoolery I've ever seen in my life. It's a remark indicative of a hubris that has remained unchecked or worse, in denial.
- siev 2y agoI like the sentiment, I love C. But this book seems riddled with errors and baffling decisions. First of all, the fixed points are LITERALLY NOT FIXED POINTS. They're decimal floats. Fixed points are just integers that re-scale when multiplied or divided. There is no exponent field, no nothing. The author seems to have confused the notion "fixed points allow for precise calculations of monetary values" to mean that they're decimal. They're not. That section of the book contradicts itself constantly and also the code is wrong. Also an ordered vector is used to implement a map/set. Because: > Most people would likely instinctively reach for hash tables, and typically spend the next few months researching optimal hash algorithms and table designs. > A binary searched vector is as simple as it gets and performs pretty well while being more predictable. A basic hash table or hash set[1] is both simpler and faster than this solution. And I don't see what's stopping someone from spending the next few months researching optimal dynamic array growth and searching algorithms instead. This line of reasoning just doesn't make any sense. And "Once nice advantage is that since they don't need any infrastructure, they're comparably cheap to create." What? It needs a dynamic array! [1] https://github.com/skeeto/scratch/tree/master/set32 https://github.com/skeeto/scratch/tree/master/set32
- exceptione 2y agoThanks for sparing us bad information. What would you recommend as a source instead?
- codr7 2y agoThanks for sharing your opinions, I don't agree.
- nesarkvechnep 2y agoUnpopular opinion but the BSDs are better OS for learning and hacking C. Super stable, amazing documentation, predictable, nice libraries included.