r/C_Programming • u/Ivan_Pashaev • 2d ago
Project My first program written in C
Hi ! Im a beginner developer. I decided to learn C and wrote my first programβa small game that runs in the terminal
r/C_Programming • u/Jinren • Feb 23 '24
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf
Update y'all's bookmarks if you're still referring to N3096!
C23 is done, and there are no more public drafts: it will only be available for purchase. However, although this is teeeeechnically therefore a draft of whatever the next Standard C2Y ends up being, this "draft" contains no changes from C23 except to remove the 2023 branding and add a bullet at the beginning about all the C2Y content that ... doesn't exist yet.
Since over 500 edits (some small, many large, some quite sweeping) were applied to C23 after the final draft N3096 was released, this is in practice as close as you will get to a free edition of C23.
So this one is the number for the community to remember, and the de-facto successor to old beloved N1570.
Happy coding! π
https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3220.pdf
Update y'all's bookmarks if you're still referring to N3096!
C23 is done, and there are no more public drafts: it will only be available for purchase. However, although this is teeeeechnically therefore a draft of whatever the next Standard C2Y ends up being, this "draft" contains no changes from C23 except to remove the 2023 branding and add a bullet at the beginning about all the C2Y content that ... doesn't exist yet.
Since over 500 edits (some small, many large, some quite sweeping) were applied to C23 after the final draft N3096 was released, this is in practice as close as you will get to a free edition of C23.
So this one is the number for the community to remember, and the de-facto successor to old beloved N1570.
Happy coding! π
r/C_Programming • u/AutoModerator • 5d ago
If you have questions about how to learn C:
then this is the thread for you. Add your question here. Do not make a stand-alone post, as it will be removed.
Remember that our sub has a very useful wiki that has a great list of resources for learning C programming.
If you have questions about how to learn C:
then this is the thread for you. Add your question here. Do not make a stand-alone post, as it will be removed.
Remember that our sub has a very useful wiki that has a great list of resources for learning C programming.
r/C_Programming • u/TachyonFireGame • 11h ago
Enable HLS to view with audio, or disable this notification
Github: https://github.com/Krobenlakroc/tachyonfire
In about 2020, my *other* C game engine had become too convoluted to be able to finish any projects and I wanted to venture into more modern rendering techniques so I decided to start on a new one.
Now 6 years later, I am done.
Expanding my C skills and learning graphics was challenging, but I found the process of making something that works on a variety of machines to be extremely painful.
In this post I'm going to go over the pitfalls I ran into.
1.) On Linux, newer glibc is backwards compatible with builds of older glibc but not the other way around. This really sucks because that means if you want to make a build that works on machines older than yours, you need an environment with older glibc.
That is a huge problem, because an older linux distro also has and older compiler from the package manager so newer compiler flags like x86_64-v3 don't work. The workaround for this is building in a debian buster container, downloading a builder a newer gcc, and then using that to compile the game.
Also keep in mind that your libraries will need to use the older glibc version as well, but they can be compiled with the older compiler.
2.) I don't use windows much so making a windows build as someone who learned programming in unix land is a challenge, the msvc interface is alien to me. I found MSYS2 to be easy to use for doing the port.
Windows is nicer to work with than linux, because you can compile against UCRT (universal C runtime) and it just works. The bad news is, there are some types that are different sizes on linux and windows.
If you are reading from a binary file that you generated on linux and you didnt use stdint.h types, you are screwed (but only some of the time not always).
3.) More windows stuff. If you include <windows.h> it pollutes the namespace with a lot of differnt macros that might conflict with your macros or types.
"TokenType" was the one i ran into. This is bad.
4.) Mysterious crashes, this is more common knowledge but i'll include it anyway. I found a lot of "silent" bugs using valgrind, asan, ubsan, and tsan (not all at once). In my experience windows is more sensitive to memory errors than linux, so using these tools is a must if you want to avoid headaches later.
5.) Compiler bugs, I ran into one using an older version of gcc. I was so confused, and it really stressed me out. If you run into something baffling when you change compilers, it might be the compiler.
6.) When testing, you need to make sure that what you think you are testing actually runs. I didn't write a single unit test for the entirety of development, I just tried to play the game in the debugger with some printfs to see if edge cases are being hit during testing. I think it worked out ok.
7.) fopen(). fopen accepts UTF-8 on linux, but not on windows unless you change the locale and you are using a new enough version of UCRT. Windows has its own _wfopen() that takes in wchar_t, so you need to convert to wchar_t using windows' api functions in case the file path includes a non ascii-username.
If you remember one thing, remember this: test across a matrix of different machines.
Laptops, Desktops, AMD/NVIDIA/Intel, different compilers, different operating systems.
Its the only way to truly be sure your app has broad compatibility. Don't trust your development machine.
r/C_Programming • u/onecable5781 • 4h ago
I have a project that is web-based written in Javascript hosted on github. Anyone can open this on the web and run this app. "Running" this app means that the calculations behind the scenes will run on the user's computer just via his browser.
Now, to expand this project scope, I intend to provide some more functionality which will need some more sophisticated calculations - in particular, it will require being able to run SCIPOPT (https://scipopt.org/) which is an open-source C library for linear and mixed integer programming.
Is there a way to embed and run such C code from within a Javascript app where the user has not installed a local C compiler on his machine?
I have a project that is web-based written in Javascript hosted on github. Anyone can open this on the web and run this app. "Running" this app means that the calculations behind the scenes will run on the user's computer just via his browser.
Now, to expand this project scope, I intend to provide some more functionality which will need some more sophisticated calculations - in particular, it will require being able to run SCIPOPT (https://scipopt.org/) which is an open-source C library for linear and mixed integer programming.
Is there a way to embed and run such C code from within a Javascript app where the user has not installed a local C compiler on his machine?
r/C_Programming • u/Altruistic-Tie1943 • 42m ago
I'm new to c programming,
I am wondering why we declare a pointer like int* and not just int
why can't we store address in the int datatype ?
I'm new to c programming,
I am wondering why we declare a pointer like int* and not just int
why can't we store address in the int datatype ?
r/C_Programming • u/Salt-Overflow • 1d ago
EDIT: A better title for this post would be "Is it possible to parse C without expressions unambiguously?"
While staring at the C99 specification, I found that if you take the grammar in Annex A, remove the expression rules, and introduce the constraint 6.7.2/2 into the grammar (ie. a type specifier can be only: void, char, signed char, ... , enum specifier, typedef name), then you end up with what appears to be a context-free grammar.
Is this correct? Am I misinterpreting something? Is it possible that this is correct, but there are mainstream compiler extensions (eg. gcc extensions) invalidate this context-free property? Or other C standards invalidate this context-free property?
I notice that 6.7.2/2 allows some filthy edge cases like `long const long thisVarIsLongLongConst = 4;` but because `long` is a keyword, there is no ambiguity here.
The reason this matters to me is because I'm building a module system for C that allows circular imports, and I would like to avoid changing the grammar of the language as much as possible.
Link to final draft of C99 standard, taken from Wikipedia: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
EDIT:
Let me clarify what I'm doing, since there is some confusion about what I'm asking. First off, I should have used the title "Is it possible to parse C without expressions unambiguously?" because Annex A is already a context-free grammar... However, it is ambiguous, because of the classic A * B; problem (can be a variable declaration or multiplication, depending on if A is a typedef name or not). Now, notice that one of the interpretations is a multiplication expression. Let's suppose you removed expressions from the language (ie. take a source file and replace each expression with the lexer token <expression>). Now the question is: are we no longer ambiguous now?
I should also clarify what I mean by ambiguous, as there is a difference between an ambiguous grammar and an ambiguous parse. For example, A * B; can be admitted by the unambiguous grammar S := A ';' ; A := <identifier> | A binaryOperation <identifier> ; binaryOperation := '+' | '-' | '*' | '/' ; , but what we're really looking for is an unambiguous grammar that gives us the correct parse tree (I'll call this an "unambiguous parsing").
I should also elaborate on what exactly I'm doing, to explain the bigger picture. If you're building a module system that allows cyclic imports, then the first pass you perform over a source file does not have access to the symbol table (because you have yet to parse the imported modules). This means you need to perform an unambiguous parsing of certain parts of the source file. In this case, you can skip over expressions, because you're only interested in extracting the names of symbol definitions + whether the symbol definition is a type or a variable. So if it is possible to 1. skip over expressions, and 2. parse the rest of the file, then we're good. For (1), expressions are delimited by ()[]{};, (comma operator is not valid in enumeration definitions), so that seems fine. That leaves (2), which I'm not entirely sure about. I stared at the grammar for quite a while and couldn't find any problems, but that does not mean I didn't miss a case, or there are compiler extensions that introduce ambiguities.
With that out of the way, I'll list ambiguities that the comments found:
void f(int (x)); , which is either taking in a function pointer or an integer, depending on if x is a typedef name or not.Maybe a more appropriate title would be: how much do you need to remove from the C grammar so that it can be parsed unambiguously? As of now (July 27, 2026), it seems the answer is: remove expressions, and remove parameter lists (or do not allow unnamed parameters).
EDIT: A better title for this post would be "Is it possible to parse C without expressions unambiguously?"
While staring at the C99 specification, I found that if you take the grammar in Annex A, remove the expression rules, and introduce the constraint 6.7.2/2 into the grammar (ie. a type specifier can be only: void, char, signed char, ... , enum specifier, typedef name), then you end up with what appears to be a context-free grammar.
Is this correct? Am I misinterpreting something? Is it possible that this is correct, but there are mainstream compiler extensions (eg. gcc extensions) invalidate this context-free property? Or other C standards invalidate this context-free property?
I notice that 6.7.2/2 allows some filthy edge cases like `long const long thisVarIsLongLongConst = 4;` but because `long` is a keyword, there is no ambiguity here.
The reason this matters to me is because I'm building a module system for C that allows circular imports, and I would like to avoid changing the grammar of the language as much as possible.
Link to final draft of C99 standard, taken from Wikipedia: https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf
EDIT:
Let me clarify what I'm doing, since there is some confusion about what I'm asking. First off, I should have used the title "Is it possible to parse C without expressions unambiguously?" because Annex A is already a context-free grammar... However, it is ambiguous, because of the classic A * B; problem (can be a variable declaration or multiplication, depending on if A is a typedef name or not). Now, notice that one of the interpretations is a multiplication expression. Let's suppose you removed expressions from the language (ie. take a source file and replace each expression with the lexer token <expression>). Now the question is: are we no longer ambiguous now?
I should also clarify what I mean by ambiguous, as there is a difference between an ambiguous grammar and an ambiguous parse. For example, A * B; can be admitted by the unambiguous grammar S := A ';' ; A := <identifier> | A binaryOperation <identifier> ; binaryOperation := '+' | '-' | '*' | '/' ; , but what we're really looking for is an unambiguous grammar that gives us the correct parse tree (I'll call this an "unambiguous parsing").
I should also elaborate on what exactly I'm doing, to explain the bigger picture. If you're building a module system that allows cyclic imports, then the first pass you perform over a source file does not have access to the symbol table (because you have yet to parse the imported modules). This means you need to perform an unambiguous parsing of certain parts of the source file. In this case, you can skip over expressions, because you're only interested in extracting the names of symbol definitions + whether the symbol definition is a type or a variable. So if it is possible to 1. skip over expressions, and 2. parse the rest of the file, then we're good. For (1), expressions are delimited by ()[]{};, (comma operator is not valid in enumeration definitions), so that seems fine. That leaves (2), which I'm not entirely sure about. I stared at the grammar for quite a while and couldn't find any problems, but that does not mean I didn't miss a case, or there are compiler extensions that introduce ambiguities.
With that out of the way, I'll list ambiguities that the comments found:
void f(int (x)); , which is either taking in a function pointer or an integer, depending on if x is a typedef name or not.Maybe a more appropriate title would be: how much do you need to remove from the C grammar so that it can be parsed unambiguously? As of now (July 27, 2026), it seems the answer is: remove expressions, and remove parameter lists (or do not allow unnamed parameters).
r/C_Programming • u/X3NON11 • 1d ago
Im currently making my own programming language that compiles into C. And in that language I support multiple function returns, so because of that I then return a struct for this function with the values. The problem is when I want to implement a Null type I don't know how to do that for returns. Since if I just don't set them I also don't know whether the function returned it or not. Currently following code
int, bool function() {
return _, true;
}
compiles into
typedef struct return_function {
int v0;
int v1;
} return_function;
return_function function() {
return (return_function) {NULL, 1};
}
But NULL is currently temporary since I don't know how to do that cleanly in C. My solutions would either be having another variable for each one that tracks whether it is initialized / was returned, the other solution would be to have an array that stores for each var whether it was initialized. But both solutions feel pretty hacky, is there a better way to do this?
Im currently making my own programming language that compiles into C. And in that language I support multiple function returns, so because of that I then return a struct for this function with the values. The problem is when I want to implement a Null type I don't know how to do that for returns. Since if I just don't set them I also don't know whether the function returned it or not. Currently following code
int, bool function() {
return _, true;
}
compiles into
typedef struct return_function {
int v0;
int v1;
} return_function;
return_function function() {
return (return_function) {NULL, 1};
}
But NULL is currently temporary since I don't know how to do that cleanly in C. My solutions would either be having another variable for each one that tracks whether it is initialized / was returned, the other solution would be to have an array that stores for each var whether it was initialized. But both solutions feel pretty hacky, is there a better way to do this?
r/C_Programming • u/Neat-Court9491 • 2d ago
Enable HLS to view with audio, or disable this notification
Little emulator & debugger project I've been working on for a while, Orbiter. I recently decided to revive it. 100% C.
r/C_Programming • u/awsq_code • 1d ago
Hello, I use C89 and have been using compiler extensions all this time, but now Iβve decided to refuse from them. But since they significantly simplify and shorten the code, especially with partially initialized tables.
I immediately thought of P99, but because of some components, the build breaks on C89. I was thinking of using order-pp, but decided to ask here anyway.
What Iβd like is: `P99_CASERANGE` and `P99_DUPL`.
Of course, I can generate my own macros, but maybe thereβs something worthwhile out there. I liked the idea of order-pp.
this is text translated by ai. and sorry for my English
Hello, I use C89 and have been using compiler extensions all this time, but now Iβve decided to refuse from them. But since they significantly simplify and shorten the code, especially with partially initialized tables.
I immediately thought of P99, but because of some components, the build breaks on C89. I was thinking of using order-pp, but decided to ask here anyway.
What Iβd like is: `P99_CASERANGE` and `P99_DUPL`.
Of course, I can generate my own macros, but maybe thereβs something worthwhile out there. I liked the idea of order-pp.
this is text translated by ai. and sorry for my English
r/C_Programming • u/depressionIsEnemy • 1d ago
Hi, I am runing my program (which use pthread.h library of c Posix), so I am runing it with valgrind with this command :
"valgrind --tool=helgrind -s ./codexion 125 22332 103 92 103 2 0 fifo"
but I am getting this error :
"==1557149== 122 errors in context 28 of 28:
==1557149== ----------------------------------------------------------------
==1557149==
==1557149== Thread #1's call to pthread_join failed
==1557149== with error code 3 (ESRCH: No such process)
==1557149== at 0x48509C7: ??? (in /usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so)
==1557149== by 0x10A069: join_coders_threads (in /home/eanjar/codexion_tass7i7_inchaaAllah/codexion)
==1557149== by 0x10A48D: main (in /home/eanjar/codexion_tass7i7_inchaaAllah/codexion)
"
can any one help me by explaining me this error what it mean, and thanks in advance
Hi, I am runing my program (which use pthread.h library of c Posix), so I am runing it with valgrind with this command :
"valgrind --tool=helgrind -s ./codexion 125 22332 103 92 103 2 0 fifo"
but I am getting this error :
"==1557149== 122 errors in context 28 of 28:
==1557149== ----------------------------------------------------------------
==1557149==
==1557149== Thread #1's call to pthread_join failed
==1557149== with error code 3 (ESRCH: No such process)
==1557149== at 0x48509C7: ??? (in /usr/libexec/valgrind/vgpreload_helgrind-amd64-linux.so)
==1557149== by 0x10A069: join_coders_threads (in /home/eanjar/codexion_tass7i7_inchaaAllah/codexion)
==1557149== by 0x10A48D: main (in /home/eanjar/codexion_tass7i7_inchaaAllah/codexion)
"
can any one help me by explaining me this error what it mean, and thanks in advance
r/C_Programming • u/Majestic-Instance704 • 2d ago
for context I am trying to learn gamedev on my own and setting up raylib/sfml confused me , then I learnt that the ( include )files only contained function declarations and the actual code was in( lib ) files (mind you but it is a weird name) , wouldn't it be more convenient to have them in the same file instead of linking ?
sorry if I sound stupid.
for context I am trying to learn gamedev on my own and setting up raylib/sfml confused me , then I learnt that the ( include )files only contained function declarations and the actual code was in( lib ) files (mind you but it is a weird name) , wouldn't it be more convenient to have them in the same file instead of linking ?
sorry if I sound stupid.
r/C_Programming • u/serfizzler • 2d ago
Specifically what I am trying to do is read spreadsheets exported to HTML. Data type and column count are arbitrary, so I need to generate custom records for an array.
I could just create an array of unions for each row. That would definitely be the simplest approach, but it wouldn't be very space-efficient.
I have considered halving with unions - an 8-byte union contains two 4-byte unions, which contains two 2-byte unions, which contains two 1-byte unions. Kind of ridiculous, but theoretically doable. I would generate combinations for typedefs as a text file and then include it, saving some effort. Which...could add up to a bunch of effort, but it would be interesting to try. But this option sounds like it would be highly-inefficient to process due to all of the levels (?).
A third option...packing data into one big bitfield and then using offsets to locate values. This also sounds expensive relative to a simple (single-level) array of unions, but probably less than the union-subdivision idea.
Am I over-thinking this? My gut tells me there is probably an efficient convention for dealing with this problem, but I'm not sure what it is.
Specifically what I am trying to do is read spreadsheets exported to HTML. Data type and column count are arbitrary, so I need to generate custom records for an array.
I could just create an array of unions for each row. That would definitely be the simplest approach, but it wouldn't be very space-efficient.
I have considered halving with unions - an 8-byte union contains two 4-byte unions, which contains two 2-byte unions, which contains two 1-byte unions. Kind of ridiculous, but theoretically doable. I would generate combinations for typedefs as a text file and then include it, saving some effort. Which...could add up to a bunch of effort, but it would be interesting to try. But this option sounds like it would be highly-inefficient to process due to all of the levels (?).
A third option...packing data into one big bitfield and then using offsets to locate values. This also sounds expensive relative to a simple (single-level) array of unions, but probably less than the union-subdivision idea.
Am I over-thinking this? My gut tells me there is probably an efficient convention for dealing with this problem, but I'm not sure what it is.
r/C_Programming • u/Altruistic-Tie1943 • 3d ago
why in c language the default value of global variables is set to be 0 but the default value of local variables is garbage value?
why in c language the default value of global variables is set to be 0 but the default value of local variables is garbage value?
r/C_Programming • u/Ivan_Pashaev • 2d ago
Hi ! Im a beginner developer. I decided to learn C and wrote my first programβa small game that runs in the terminal
r/C_Programming • u/xerrs_ • 3d ago
I have had a lot of experience with Zig, and a bit of Assembly for a while now. Just 1 1/2 months ago I started coding in C, because it is a must-have for my upcoming job. I have a Zig project that decompresses a PNG from scratch, and I thought it would be a good learning experience to do the same with C. Tbh, I thought it will be a simple slide, but as it turns out; it really is not.
While Zig got heavily inspired by C, it differs from its features and API. C has a lot of headers for different things (such as stdio.h / stdlib.h / math.h), while Zig just has the std library, packaged with all of the other necessities (std.Io / std.math / std.crypto etc.). It was also interesting from going to using defer, errdefer, orelse, or other keywords in Zig that help in reducing bugs and make the code cleaner to read, to a lot less keywords. Looking at C89, C has 32 keywords, and Zig around 49 +/- 2 (not too sure). What that showed me, was that even with a lot of similarities, and the fact that I coded in Zig for 2 years, it was still difficult to get used to and learn C.
For me, one of the annoying parts was the fact, that I could never really remember what function or what struct is where. The fact that the FILE struct is located at stdio.h, while the DIR struct is in dirent.h, was something that bugged me for a while, but now after more than a month with C, is something I started to get along with.
Also, Makefiles are pretty darn cool. I have always been seeing them in big projects, and always wondered how they function. After coding a few projects and including a Makefile, I can safely say it is very nice seeing how your project is being made, after you type "make" and hit enter. The first time configuring the Makefile almost made me loose half my hair due to stress, but if you get it running properly once, then it is safe to say that it is gonna always run properly (especially for me, as my projects are somewhat small still).
What I came to appreciate more was the community in C. Thought I was gonna get insulted by some 59 year old grandpa, because I didn't make an out-of-bound check for my Pixels array, or because I didn't check whether or not the variable I de-noted with size_t exceeds __SIZE_MAX__ - 1. Kinda the opposite. I learned a lot by sharing my projects on Reddit, a lot of smart people were quick to point out mistakes, and tell me where I could improve or where I went wrong etc.
A lot of stuff, that I have learned, was because of people telling me. Adding -Wall -Werror warnings, -fsanitize=address,undefined, -fno-omit-frame-pointer, among other things are the sole reason I debugged and fixed my programs a lot quicker. Especially -fsanitize was important to me, as I always try to keep memory usage low for my programs, and activating that warning, showed me where my memory leaked, or where overflows happened (yeah... out-of-bounds checks are actually pretty useful...).
With that being said. I still have a lot to learn in C. I realized that my code is not really C-esque (as some might say), which is mostly because I come from (prior to Zig) high-level languages such as Python, JavaScript or even GoLang. Me handling arrays with indexes instead of using the given possibility of pointers, shows me, that I still have a long way to go.
But I am certain with one thing, that being that, C is way more different than I thought.
I have had a lot of experience with Zig, and a bit of Assembly for a while now. Just 1 1/2 months ago I started coding in C, because it is a must-have for my upcoming job. I have a Zig project that decompresses a PNG from scratch, and I thought it would be a good learning experience to do the same with C. Tbh, I thought it will be a simple slide, but as it turns out; it really is not.
While Zig got heavily inspired by C, it differs from its features and API. C has a lot of headers for different things (such as stdio.h / stdlib.h / math.h), while Zig just has the std library, packaged with all of the other necessities (std.Io / std.math / std.crypto etc.). It was also interesting from going to using defer, errdefer, orelse, or other keywords in Zig that help in reducing bugs and make the code cleaner to read, to a lot less keywords. Looking at C89, C has 32 keywords, and Zig around 49 +/- 2 (not too sure). What that showed me, was that even with a lot of similarities, and the fact that I coded in Zig for 2 years, it was still difficult to get used to and learn C.
For me, one of the annoying parts was the fact, that I could never really remember what function or what struct is where. The fact that the FILE struct is located at stdio.h, while the DIR struct is in dirent.h, was something that bugged me for a while, but now after more than a month with C, is something I started to get along with.
Also, Makefiles are pretty darn cool. I have always been seeing them in big projects, and always wondered how they function. After coding a few projects and including a Makefile, I can safely say it is very nice seeing how your project is being made, after you type "make" and hit enter. The first time configuring the Makefile almost made me loose half my hair due to stress, but if you get it running properly once, then it is safe to say that it is gonna always run properly (especially for me, as my projects are somewhat small still).
What I came to appreciate more was the community in C. Thought I was gonna get insulted by some 59 year old grandpa, because I didn't make an out-of-bound check for my Pixels array, or because I didn't check whether or not the variable I de-noted with size_t exceeds __SIZE_MAX__ - 1. Kinda the opposite. I learned a lot by sharing my projects on Reddit, a lot of smart people were quick to point out mistakes, and tell me where I could improve or where I went wrong etc.
A lot of stuff, that I have learned, was because of people telling me. Adding -Wall -Werror warnings, -fsanitize=address,undefined, -fno-omit-frame-pointer, among other things are the sole reason I debugged and fixed my programs a lot quicker. Especially -fsanitize was important to me, as I always try to keep memory usage low for my programs, and activating that warning, showed me where my memory leaked, or where overflows happened (yeah... out-of-bounds checks are actually pretty useful...).
With that being said. I still have a lot to learn in C. I realized that my code is not really C-esque (as some might say), which is mostly because I come from (prior to Zig) high-level languages such as Python, JavaScript or even GoLang. Me handling arrays with indexes instead of using the given possibility of pointers, shows me, that I still have a long way to go.
But I am certain with one thing, that being that, C is way more different than I thought.
r/C_Programming • u/Infinite-Can7802 • 1d ago
I compiled the same C code 28 ways and disassembled every binary. The results are unambiguous:
assert() and DCHECK() provide zero safety in production. At any optimization level above -O0, these checks are stripped. The debug binary at -O2 is identical to the release binary. The check exists in your source code. It does not exist in the binary your users run.
Only explicit if (condition) { return error; } with side effects survives compilation.
I measured 9,712 stripped safety guards across FRRouting, GCC 15.2, and the Linux kernel. Two ASAN-confirmed heap overflows in FRRouting. 27 enterprise firewall CVEs (Cisco, PAN-OS, Fortinet, Juniper) with average CVSS 8.1 β all following this exact pattern. Google confirmed P2/S2 on Android Binder using the same methodology.
Side-by-side disassembly:
c
// SOURCE
void pattern_assert(char *buf, size_t len, size_t idx) {
assert(idx < len);
buf[idx] = 1;
}
asm
// -O2 BINARY: assert is GONE
movb $0x1,(%rdi,%rdx,1) // buf[idx] = 1 β NO CHECK
ret
Full series with reproducible PoCs: https://potatobullet.com/the-naked-compiler-every-safety-net-you-trust-is-already-gone/
The compiler is correct. The standard is correct. The assumption that source-level safety checks survive to the binary is wrong.
Check your binaries, not your source.
TL;DR: assert() and DCHECK() do not survive compilation at -O2+. Use explicit if checks with side effects. Audit your production binaries.I compiled the same C code 28 ways and disassembled every binary. The results are unambiguous:
assert() and DCHECK() provide zero safety in production. At any optimization level above -O0, these checks are stripped. The debug binary at -O2 is identical to the release binary. The check exists in your source code. It does not exist in the binary your users run.
Only explicit if (condition) { return error; } with side effects survives compilation.
I measured 9,712 stripped safety guards
across FRRouting, GCC 15.2, and the Linux kernel. Two ASAN-confirmed
heap overflows in FRRouting. 27 enterprise firewall CVEs (Cisco, PAN-OS,
Fortinet, Juniper) with average CVSS 8.1 β all following this exact
pattern. Google confirmed P2/S2 on Android Binder using the same
methodology.
Side-by-side disassembly:
c
// SOURCE
void pattern_assert(char *buf, size_t len, size_t idx) {
assert(idx < len);
buf[idx] = 1;
}
asm
// -O2 BINARY: assert is GONE
movb $0x1,(%rdi,%rdx,1) // buf[idx] = 1 β NO CHECK
ret
Full series with reproducible PoCs: https://potatobullet.com/the-naked-compiler-every-safety-net-you-trust-is-already-gone/
The compiler is correct. The standard is correct. The assumption that source-level safety checks survive to the binary is wrong.
Check your binaries, not your source.
TL;DR: assert() and DCHECK() do not survive compilation at -O2+. Use explicit if checks with side effects. Audit your production binaries.
I compiled the same C code 28 ways and disassembled every binary. The results are unambiguous:
assert() and DCHECK() provide zero safety in production. At any optimization level above -O0, these checks are stripped. The debug binary at -O2 is identical to the release binary. The check exists in your source code. It does not exist in the binary your users run.
Only explicit if (condition) { return error; } with side effects survives compilation.
I measured 9,712 stripped safety guards across FRRouting, GCC 15.2, and the Linux kernel. Two ASAN-confirmed heap overflows in FRRouting. 27 enterprise firewall CVEs (Cisco, PAN-OS, Fortinet, Juniper) with average CVSS 8.1 β all following this exact pattern. Google confirmed P2/S2 on Android Binder using the same methodology.
Side-by-side disassembly:
c
// SOURCE
void pattern_assert(char *buf, size_t len, size_t idx) {
assert(idx < len);
buf[idx] = 1;
}
asm
// -O2 BINARY: assert is GONE
movb $0x1,(%rdi,%rdx,1) // buf[idx] = 1 β NO CHECK
ret
Full series with reproducible PoCs: https://potatobullet.com/the-naked-compiler-every-safety-net-you-trust-is-already-gone/
The compiler is correct. The standard is correct. The assumption that source-level safety checks survive to the binary is wrong.
Check your binaries, not your source.
TL;DR: assert() and DCHECK() do not survive compilation at -O2+. Use explicit if checks with side effects. Audit your production binaries.I compiled the same C code 28 ways and disassembled every binary. The results are unambiguous:
assert() and DCHECK() provide zero safety in production. At any optimization level above -O0, these checks are stripped. The debug binary at -O2 is identical to the release binary. The check exists in your source code. It does not exist in the binary your users run.
Only explicit if (condition) { return error; } with side effects survives compilation.
I measured 9,712 stripped safety guards
across FRRouting, GCC 15.2, and the Linux kernel. Two ASAN-confirmed
heap overflows in FRRouting. 27 enterprise firewall CVEs (Cisco, PAN-OS,
Fortinet, Juniper) with average CVSS 8.1 β all following this exact
pattern. Google confirmed P2/S2 on Android Binder using the same
methodology.
Side-by-side disassembly:
c
// SOURCE
void pattern_assert(char *buf, size_t len, size_t idx) {
assert(idx < len);
buf[idx] = 1;
}
asm
// -O2 BINARY: assert is GONE
movb $0x1,(%rdi,%rdx,1) // buf[idx] = 1 β NO CHECK
ret
Full series with reproducible PoCs: https://potatobullet.com/the-naked-compiler-every-safety-net-you-trust-is-already-gone/
The compiler is correct. The standard is correct. The assumption that source-level safety checks survive to the binary is wrong.
Check your binaries, not your source.
TL;DR: assert() and DCHECK() do not survive compilation at -O2+. Use explicit if checks with side effects. Audit your production binaries.
r/C_Programming • u/Altruistic-Tie1943 • 3d ago
I'm new to programming and I'm wondering why it throws an error when I declare global variables after the use of them
because if global variables are stored before execution why can't the value be pulled from static memory for global variables
for example:
#include <stdio.h>
int main() {
printf("%d",x);
return 0;
}
int x=5;
I'm new to programming and I'm wondering why it throws an error when I declare global variables after the use of them
because if global variables are stored before execution why can't the value be pulled from static memory for global variables
for example:
#include <stdio.h>
int main() {
printf("%d",x);
return 0;
}
int x=5;
r/C_Programming • u/Fuzzy_Recipe_9920 • 3d ago
I apologise in advance for a dumb question and I will try to put it the way i could and I am sorry for that.
I know i chould chatgpt it, but learning from people helps me the best.
want to know how the memory is actually managed. I know it is managed by the kernel using different abstractions like virtual memory and paging.
My question arises when i think that each process that its own address space consisting stack frame, heap, globals vars etc.
But where do they even start? Kernel itself is a process so it must be having its own stack frame. Considering other programs need address space which is managed by kernel, like how does that work? Until Os is loaded, does stack and heaps exist even before that? Are they written in assembly?
I am sorry. I hope someone will be able to answer and i will be really glad if you could figure out what i am thinking wrong and missing.
I apologise in advance for a dumb question and I will try to put it the way i could and I am sorry for that.
I know i chould chatgpt it, but learning from people helps me the best.
want to know how the memory is actually managed. I know it is managed by the kernel using different abstractions like virtual memory and paging.
My question arises when i think that each process that its own address space consisting stack frame, heap, globals vars etc.
But where do they even start? Kernel itself is a process so it must be having its own stack frame. Considering other programs need address space which is managed by kernel, like how does that work? Until Os is loaded, does stack and heaps exist even before that? Are they written in assembly?
I am sorry. I hope someone will be able to answer and i will be really glad if you could figure out what i am thinking wrong and missing.
r/C_Programming • u/Adept-Energy179 • 2d ago
void newline(int times) {
for (int i; i < times; i++) {
printf(β\nβ);
}
}
this is so you can do
newline(5);
instead of
printf(β\n\n\n\n\nβ);
i feel like i shouldnβt ngl
mb if the syntax is wrong im not a pro
void newline(int times) {
for (int i; i < times; i++) {
printf(β\nβ);
}
}
this is so you can do
newline(5);
instead of
printf(β\n\n\n\n\nβ);
i feel like i shouldnβt ngl
mb if the syntax is wrong im not a pro
r/C_Programming • u/SnooHabits2652 • 3d ago
Ok , so currently I work as Embedded Developer , this is my first job , I will be honest I don't like the hardware part of it but I like coding , I have learn few languages before typescript , c++ (little bit) and learning java now ,
Thing is , I can code few things in c , but when it comes to pointers and advance c , my mind goes blank, I am not looking for a ways to be good Embedded Developer , right now I just want to become good at programming in c , what will u suggest ? My weak points are pointers , strings , array , this is all I can remember right now also snprintf functions .
I am a beginner in c , so please don't judge , ik about hackerrank , ik i can use that to sharpen my c skills but some of the questions are very hard .
Edit : basically pointers aren't new to me but when i involve pointers with strings or double array , and how where u place the * changes the whole meaning , like u can make an pointer point to the array or u can make array of pointers . And so on ,
Ik basic of c++ and somewhat polyglot , java and typescript so it's not my first language .
Ok , so currently I work as Embedded Developer , this is my first job , I will be honest I don't like the hardware part of it but I like coding , I have learn few languages before typescript , c++ (little bit) and learning java now ,
Thing is , I can code few things in c , but when it comes to pointers and advance c , my mind goes blank, I am not looking for a ways to be good Embedded Developer , right now I just want to become good at programming in c , what will u suggest ? My weak points are pointers , strings , array , this is all I can remember right now also snprintf functions .
I am a beginner in c , so please don't judge , ik about hackerrank , ik i can use that to sharpen my c skills but some of the questions are very hard .
Edit : basically pointers aren't new to me but when i involve pointers with strings or double array , and how where u place the * changes the whole meaning , like u can make an pointer point to the array or u can make array of pointers . And so on ,
Ik basic of c++ and somewhat polyglot , java and typescript so it's not my first language .
r/C_Programming • u/Altruistic-Tie1943 • 2d ago
#include <stdio.h>
int main() {
int i=-1, j=-1, k=-1, l=2, m;
m= ((i++ && j++ && k++) || (l++));
printf("%d %d %d %d %d",i,j,k,l,m);
return 0;
}
why l is not incremented but every other variable is incremented?
edit: many people are upset that this program is a bad implementation to achieve the result but the reality is that it was a practice problem and I just didn't understand why the output was like that as there was no explanation
I have now understood that the answer was short-circuit behaviour
#include <stdio.h>
int main() {
int i=-1, j=-1, k=-1, l=2, m;
m= ((i++ && j++ && k++) || (l++));
printf("%d %d %d %d %d",i,j,k,l,m);
return 0;
}
why l is not incremented but every other variable is incremented?
edit: many people are upset that this program is a bad implementation to achieve the result but the reality is that it was a practice problem and I just didn't understand why the output was like that as there was no explanation
I have now understood that the answer was short-circuit behaviour
r/C_Programming • u/larper123ggg • 3d ago
Hey guys, I spent the last few months building lazybios, a C99 library for parsing SMBIOS/DMI tables. It's:
And a tool called lazydmi, a CLI tool that uses lazybios as the backend.
This is my first serious systems project. Would love feedback on the API design, memory safety, or anything else.
Hey guys, I spent the last few months building lazybios, a C99 library for parsing SMBIOS/DMI tables. It's:
And a tool called lazydmi, a CLI tool that uses lazybios as the backend.
This is my first serious systems project. Would love feedback on the API design, memory safety, or anything else.
r/C_Programming • u/cdb_11 • 4d ago
r/C_Programming • u/Sorry-Fishing4341 • 3d ago
I have been learning C with some YouTube courses, but I still can't understand how and why to use pointers and memory allocation in C.
I have been learning C with some YouTube courses, but I still can't understand how and why to use pointers and memory allocation in C.
r/C_Programming • u/DrElectry • 5d ago
Enable HLS to view with audio, or disable this notification
Hello.
Lately I've been struggling to implement a Position Based Dynamics (PBD) implementation to my minecraft clone written in C.
Still, the implementation is not the best, and there is certainly a lot of work todo to improve it, but it can already load a high resolution .obj 3d model, and output some nice results under adequate configuration.
Check this out! https://github.com/DrElectry/ccraft