C is not a Programming Language Anymore
I know for a fact that a lot of C Programmers and Developers are going to get super mad at me for even mentioning that this is a thing. I have been doing so much research into this article before I ever decided to publish it. So, without waiting anymore,
I know for a fact that a lot of C Programmers and Developers are going to get super mad at me for even mentioning that this is a thing. I have been doing so much research into this article before I ever decided to publish it. So, without waiting anymore, here comes my idea of C not being a programming language anymore.
I am in deep thought into the idea of C and the ABIs plus maybe even a way to fix them one day hopefully. Yet I am not even remotely sure why I dislike them or why they are pissing me off at all.
- One idea is to improve the conditions of using
Citself as a programming language for all developers. - Another idea is to improve the conditions to use literally any other programming language other an
Cnow.
If you made it this far into the article – which we could treat as an introduction per say – you are asking what the hell does this have to do with the C programming language to me right now. So now let me explain exactly what I mean.
The first issue with my take on the C programming language is that if it was actually not a programming language for developers to use. For a lot of people who do a lot of programming, C is drastically falling off the ideal programming language choice of go to languages to use, and also, it's been like this for white a long time if you keep track of these things. This is also not about that the C language is not horribly defined due to a billion implementations or its completely failed integer hierarchy.
From my experience of researching and trying to program an application in the C language, it is absolutely horrible to pick up. This stuff sucks, but while on it's own, that is not my problem with it.
My personal problem is that C language was elevated to a role of absolute prestige and power when it comes to programming languages. It feels like it's reign so absolute and eternal that it has completely distorted the way we speak to each other. Rust and Swift cannot just simply speak their native and comfortable tongues – they must instead wrap themselves in a ugly truth and act like a representation of C’s skin and try to fool people into believing people that they are the exact same.
The C programming language is the giant mixing pot or original starting point of programming. We must all speak to understand C, and then therefore C is not just a programming language anymore – it’s treated as a protocol that every general-purpose programming language needs to speak to be able to communicate.
So actually this kinda is about the whole C is an extremely hard to understand implementation-defined mess kind of thing. But only to the extent of as it makes this protocol we all have to use an even bigger nightmare for people who want to code software applications and web applications.
Let's Discuss Foreign Function Interfaces
Time to get technical with the idea I am trying to present. I just got done with creating my own programming language called OasisScript. The language's first class support for Oasis Trees, Water, and Sand. It is an absolute amazing language that's going to revolutionize the way that Java, Rust, and GoLang programmers are going to code their next programs and software projects!
Now the next goal which I need to achieve is to make it do something really useful. As in... you know... like... take user input, write output, or do anything that a developer can observe easily? If I want any programs created in my OasisScript programming language to work well with the major operating systems, then I will have to interact with the operating system's interface. I hear everyone say that everything on Linux is just a file, so let’s just open a file on Linux!
OPEN(2)
NAME
open, openat, creat - open and possibly create a file
SYNOPSIS
#include <fcntl.h>
int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);
int creat(const char *pathname, mode_t mode);
int openat(int dirfd, const char *pathname, int flags);
int openat(int dirfd, const char *pathname, int flags, mode_t mode);
/* Documented separately, in openat2(2): */
int openat2(int dirfd, const char *pathname,
const struct open_how *how, size_t size);
Feature Test Macro Requirements for glibc (see
feature_test_macros(7)):
openat():
Since glibc 2.10:
_POSIX_C_SOURCE >= 200809L
Before glibc 2.10:
_ATFILE_SOURCEWait! Wait! Wait! Um... I am sorry... what? This is OasisScript, not the C language! Where’s the OasisScript interface for my Linux distro of choice?
What do you mean there’s no OasisScript interface for Debian, Arch, CentOS, or even Ubuntu!? Ok, well, sure, it is a brand-new programming language that took about six years of development and just came out two months ago! But! You’re going to add one, right? Right… ?
Well, fuck ok. I guess we are going to have to use what they gave me to use.
I am going to need some kind of Interface that lets our language call Functions that are Foreign to it. A Foreign Function Interface – or is it called FFI for short? Yeah, I remember now! I think like the sound of that!
Oh hey there! Look at Rust! You have C language FFI too now?!!? And you too Swift? Even Python?! What the hell is going on here?
3.2.3 Parameter Passing
After the argument values have been computed, they are placed either in registers or pushed on the stack. The way how values are passed is described in the
following sections.
Definitions We first define a number of classes to classify arguments. The
classes are corresponding to AMD64 register classes and defined as:
INTEGER – This class consists of integral types that fit into one of the general
purpose registers.
SSE – The class consists of types that fit into a vector register.
SSEUP – The class consists of types that fit into a vector register and can be passed and returned in the upper bytes of it.
X87, X87UP – These classes consists of types that will be returned via the x87 FPU.
COMPLEX_X87 – This class consists of types that will be returned via the x87 FPU.
NO_CLASS – This class is used as initializer in the algorithms. It will be used for padding and empty structures and unions.
MEMORY – This class consists of types that will be passed and returned in memory via the stack.
Classification The size of each argument gets rounded up to eight bytes.
The basic types are assigned their natural classes:
Arguments of types (signed and unsigned) _Bool, char, short, int,long, long long, and pointers are in the INTEGER class.
Arguments of types float, double, _Decimal 32, _Decimal64 and _m64 are in class SSE.
Everyone had to learn to speak the C programming language to talk to the all of the different and major operating systems. Then when it came time to talk to each other... we suddenly all already spoke C language, so… why not talk to each other in terms of the C language too?
Oops! Now C is now the go to language for communication of the programming world! Oops! Now I understand that the C language isn’t just a programming language, it’s now just a protocol.
What does talking to C involve exactly?
This part took two months of research alone to figure out, so bare with me as I try to provide the details of how all of this works. So, apparently, each and every programming language has to have aspects or even learn to talk to the C Programming Language to function. This is a language that is the definition of being very well defined. I promise you that I am not hallucinating either.
So, back to the title of this section of the article. What does talking to C involve means? It means that I have to get the descriptions of the interfaces type and functions in the form to be used in a C header then... some how....
- Try to match the layouts of those types
- Doing stupid some stuff with linkers to resolve the function’s symbols as pointers instead.
- Then calling those functions with the appropriate ABI (like putting
argsin the right registers) for it to all work.
That seems all very good and everything, but there are some major issues with doing this...
- You can’t actually write a
Cparser. Cdoesn’t actually have anABI. Or even defined type layouts.
You Can’t Parse A C Header
Yes, I am genuinely saying that that parsing C is basically impossible. Even with all of the research I could do. It all comes back to it being impossible. I have had a friend mention there are lots of tools that read in C headers! Like rust-bindgen as an example he linked me to.
The answer I gave to him is Nope! Here is the reasoning behind it.
Bindgenuseslibclangto parseCandC++header files. To modify howbindgensearches forlibclang, see the clang-sys documentation. For more details on howbindgenuseslibclang, see thebindgenusers guide.
I know a lot of developers that spend massive amounts of time trying to parse C or `C++~ headers. A lot of the time I also hear them say fuck that. I quit, then ends up rage quitting to let the compiler do it for them. You should also keep in mind that to meaningfully parse a C header is more than just parsing – you usually always need to resolve #includes or typedefs and macros too! So, by this logic, you need to implement all of the platform header logic, then somehow figure out what things are DEFINED in the environment you are using! Wow, Yikes!
To provide more context and understanding, I am going to present an extreme example being using Swift. The Swift programming language has basically just about everything going for it in terms of learning and resources for the C language. Here is more of what I am meaning.
The Swift programming language is developed by Apple to mainly replace Objective C as the primary language of defining and using system APIs within their own platform. In doing so, it has taken the notion of ABI-stability and design further than anyone else.
Swift also one of the absolute most hardcore FFI supporting languages I’ve ever seen! I have saw it natively import Objective C or C++ headers and will produce a nice and native Swift interface with types getting automagically bridged to their Swift equivalents at the boundary – often transparently due to the types having identical ABIs!
In case you didn't know, Swift was also developed by many of the same people at Apple who had built and maintained the C programming language – and that includes the LLVM also. This is straight up world-leading experts in the C language. One of those people who we will mention is Doug Gregor. I want to show you his opinion on C's FFI is:

Ah, well, fuck me swinging sideways! Not even Swift has the stomach for this bull crap at all. So, what do you do if you absolutely positively do not want to have a C compiler parsing and resolving headers at compile time?
You have to hand-translate those bad boys! int64_t? Write i64. long? Write… uhhhh… oh... what’s a long?
This article is starting to get pretty long for my usual length of writings, rants, and whatever I want to tell stories about with my experience in programming, security, and web development. Here is Programming Language Anymore for Developers (Part 2) for you to continue reading.
The CoderOasis Community
Did you know we have a Community Forums and Discord Server? which we invite everyone to join us? Want to discuss this article with other members of our community? Want to join a laid back place to chill and discuss topics like programming, cybersecurity, web development, and Linux? Consider joining us today!

$ tail -f /forums
Discussion
Comments live on the community forums — sign in there to reply.