When comparing C vs Bash (Bourne-Again SHell), the Slant community recommends C for most people. In the question“What is the best programming language to learn first?” C is ranked 3rd while Bash (Bourne-Again SHell) is ranked 34th. The most important reason people chose C is:
Learning C forces you to grapple with the low-level workings of your computer (memory management, pointers, etc.) in ways that the other languages abstract away. Without an understanding of these low-level aspects of computer programming you will be limited if you try to develop an application that needs to run in a memory or performance constrained environment. Other languages like Python can obscure a lot of details, so your foundation may be weaker.
Specs
Ranked in these QuestionsQuestion Ranking
Pros
Pro Understanding of computers
Learning C forces you to grapple with the low-level workings of your computer (memory management, pointers, etc.) in ways that the other languages abstract away. Without an understanding of these low-level aspects of computer programming you will be limited if you try to develop an application that needs to run in a memory or performance constrained environment.
Other languages like Python can obscure a lot of details, so your foundation may be weaker.
Pro Helps with learning other languages later
A lot of languages used in the industry have a C-like syntax (C++, Java, Javascript, C#, PHP) and starting with C will help new developers to be familiar with it's syntax and by extensions with the syntax of many popular languages.
Pro Industry standard
C is the industry standard programming language, moreover, it is the most popular programming language to use. C is the language used for most Windows, UNIX and Mac operating systems.
Pro Portable
C is portable between most hardware. Generally a C compiler is made for any new architecture, and already exists for existing architectures.
C is portable between all operating systems (Windows, UNIX, Mac, etc.) and only needs a program to be recompiled to work. This allows anyone on any operating system to learn about the language and not be held back by intricacies of their operating system.
With this said, C's portability these days is not quite what it used to be. Much of said portability relies on the POSIX standard in particular, and as time passes, the compliance of a given system with that standard is becoming less certain; especially in the case of Linux. Most things will still be portable (or at least emulatable) between Windows, Linux, and FreeBSD for example; but you will at times need to make use of platform-specific support libraries and APIs as well.
Pro Must-have
Capability to program in C is greatly appreciated in developers, creates an image of competency, and many programmers will learn it at some point in their careers.
Pro Low level of abstraction
While higher level languages languages like Java and Python provide possibilities to be "more expressive" per line of code, it's much more convenient to start with "less efficient" (get me right) language, in order to get initial concepts of how things behave at lower level.
Actually C is a good starting point moving to both higher and lower levels of abstraction, the good example here would be learning C before Assembler, as for general use the Assembler quite hard to understand due to low level of its abstraction (like getting the understanding on how loops work in C before trying to implement them on Assembler).
Pro More control over the code
Pro The king of languages, imitated, extended but never equalled
Made of a small set of keywords and rules, only your imagination is the limit. Above all, when it comes to 'pro' programming, C is the only one to rely on.
Pro Teaches good practices
Writing in C will require you to understand how things are done. C implies using and understanding the fundamentals. Learning a higher-level language after is much easier.
Pro Portable between CPU architectures
C was designed to be independent of any particular machine architecture, and so with a little care, it is easy to write "portable" programs (see here). By design, C provides constructs that map efficiently to typical machine instructions, and therefore it has found lasting use in applications that had formerly been coded in assembly language like operating systems or small embedded systems.
Pro C is simple with lesser rules than any other language
C is standardized and it is the go-to language when you have to speed things up.
Pro Ubiquitous
There is a C compiler available for probably every computer system in existence today.
Pro Easy to drop down to assembly
Sometimes you really need to program directly in assembly. C’s ABI and common compiler extensions make this a piece of cake.
Pro If you can't grok C you should not be a professional programmer
It sets an early bar that if you can't hurdle you might as well do something other than programming and not waste any more of your time.
Pro Basic concepts can be applied to accelerate learning any other language
You can easily pivot knowledge learned here and apply it to almost every other language.
Pro Foundational, difficult but important
Learning C will teach valuable skills and transferrable understanding of computing. While learning a scripting language may be easier, students will not understand system constraints and performance problems, nor what features like garbage collection are actually doing in other languages.
Pro Low level langauge
Pro Default shell on most systems
Bash is the default shell on virtually every UNIX system. Making it very portable across different systems and once you get used to it, you can use it everywhere.
Pro Plenty of examples and tutorials
Since this is very mature shell there is a lot of great examples and other resources describing how to do almost everything.
Pro Rich scripting capabilities on a single line
Want to run something 5 times? Write a throw-away loop: for i in 1 2 3 4 5; do date; done
If you need it 100 times? Not a problem: for i in {1..100}; do date; done
or: for ((i=0; i<100; ++i)); do date; done
How about emailing yourself when remote server is back online? Sure thing: while ! ping -c1 example.com &>/dev/null; do date; sleep 5; done && mailx -s 'server is back!' me@myself.com
Pro POSIX compatible
Pro Emacs-like keyboard control
By default, BASH uses shortcuts and concepts very similar to Emacs, so learning one often results in familiarity with the other.
Pro Rich built-in features
By default, there are many built-in features. They make really complex and reliable programs possible. In comparison to dash, for example, you can do the same tasks in less time and fewer lines of code.
Pro Variables and aliases are listed the way they are built
alias
and set
will list aliases and variables in a format that can be run directly with no modifications. Even if the values contain \n.
This is handy if you want to modify a value.
Pro Recursive globbing
ls **/*.log
for example is supported by Bash if you set shopt -s globstar
.
Pro Man page is a trove of wonders
While the manual "page" is nearly a hundred pages long, it is actually surprisingly succinct and stuffed with good information. It is often better than Googling for answers when writing shell scripts. The way it is written makes it easy to stumble upon useful new programming features just by flipping through it .
NOTE: If you find it dense and hard to read at the command line, look for the PDF version.
Pro vi mode is more comprehensive than on other shells
Vi editing mode works without a glitch. "_" will print you the last argument of the latest command (zsh won't). VI mode is fast off the bat - You don't have to reset any variable (like "KEYTIMEOUT" in zsh) for that.
Pro Copyright license is GPL 3+
Bash is licensed under the GNU General Public License ≥3, which gives much stronger assurances that the right to use it can't be restricted.
For example, Microsoft would not be able to claim in court that, even though they've distributed Bash with the GPLv3, a license that explicitly grants people freedom, now Bash is essentially proprietary due to software patents and everyone who uses Bash owes them money. (This may sound ludicrous to those who were not alive when Microsoft tried a similar scheme against Linux fifteen years ago).
The GPLv3 is a license that reflects the genuine ethical issues that arise when people give their time and skills to collaboratively build software. While most people wouldn't insist that their UNIX shell is licensed under the GPLv3+, it does matter and is a big PRO for Bash.
Pro Built-in 'help'... helps a lot
Built-in 'help' provides quick and efficient help on builtins and keywords.
Pro Rich scripting capabilities
BASH scripting is a rich and robust language.
Cons
Con Languages is full of corner cases and undefined behaviors
Undefined behavior in a program can cause unexpected results, making it hard to debug. With UB, program behavior may vary wildly depending on optimization settings. There are many cases that invoke UB, such as signed overflow, invalid dereferences, large integer shifts, uninitialized variables, etc. These serve to frustrate novice programmers when they could be learning other concepts.
Con Requires memory management
Learning programming is already hard enough when you don't have to worry about memory leaks.
Con Completely lacks type safety
The C standard library is not type safe, and the language itself does not promote type safety built into the language, which leads to error-proneness of the language. If anything, it would be recommended that those interested in C to instead put their time in D, which actually includes a complete copy of the C standard library rewritten to be fully type safe.
Con C will require you to learn concepts too advanced for most beginners
While other programmers will learn algorithms and structures and will do magic tricks and awesome applications, you will learn trash info that you should know maybe after 5-7 years experience in software development, not earlier. It's like going the first time as a seven year old kid to first school class, and your teacher tells you to learn you about Discrete Math, without basic math and how to do 2x2.
If you wish to be a really good programmer, C for sure will be in your portfolio, but not as a first language, and this programming language is used only for very hard and very limited tools which require a lot of professional skills from the programmer.
Con Does not support modules; header file annoyances
Header files are a poor man's implementation of modules. Modern programming languages make use of modules which eliminate the need for C includes and header files and the many issues caused by them, such as the complete lack of dependency checking. Header files often contain even more include statements that point to other header files which also point to even more which drastically increases compile time. Modules only have to be compiled once, and when importing those modules into your software project, you only have to pull in the module that you are using, which is often times already precompiled. This way, the compiler knows exactly what it needs before beginning to compile your project and can automatically compile the few dependencies it needs in advance rather than recursively compiling every header file it runs across as in C.
Con Steep learning curve
While the language compliments knowledge of computer components very well, and gives a deeper understanding, it is also quite difficult to learn, and to use correctly, especially without aforementioned knowledge.
Con Low-level
Depending on the purpose this can be either a pro or a con. If the task is to learn how to program, low-level of C will impend learning important concepts. Furthermore, C is rather limited in ways of building abstractions.
"Low-levelness" of C can be a pro feature in learning system programming.
Con Other languages can do it easier or better
There are languages like Rust, Object Pascal, D, Golang, Vlang, Odin, Zig, Jai, etc... that can be used instead. The other languages are easier to understand, use, and/or about as fast.
Con Compiles procedurally rather than intelligently
In the same manner that C recursively compiles header files ad infinitum without any sort of dependency checking, C source code is also compiled in the same manner. If you attempt to call a function before it is declared, the compiler will fail because the function was not compiled before it was caled.
Con Lack of support for first class strings
C does not support the string type, nor does it support UTF-8 strings that modern languages are employing today. Instead of strings, C makes use of the *char type which is a pointer to a character array.
Con Arrays are not first class objects
When an array is passed to a function, it is converted to a pointer, even though the prototype confusingly says it's an array. When this conversion happens, all array type information gets lost. C arrays also cannot not be resized, which means that even simple aggregates like a stack are complicated to implement. C arrays also cannot be bounds checked, because they don't know what the array bounds are.
Con Undefined behaviors and weak limited type safety
Subtle errors can render the entire program "undefined" by the complicated C standard. The standard imposes no requirements in such cases. Thus C compiler is free to ignore the existence of such cases and Bad Things are prone to happen instead. Even experts can't reliably avoid undefined cases in C, so how can beginners be expected to do so? C allows for non-type safe operations such as logic errors, wild pointers, buffer overflow, etc. UB and type safety issues create a large number of bugs and security vulnerabilities.
Con The need for C developers in the current market is very low, and trending downward
Older languages, like C, are no longer in their hay day. Even if you do learn it as your first language, you are only setting yourself up to need to learn another language in the long run. If you want a skill that you can not only learn from, but also potentially build a career on, C should not be your first choice.
Con Isn't truly portable or cross platform
The C programming language is not portable to other operating systems, and even different compilers, because the C language does not provide any reference cross platform libraries or compilers. Different platforms and compilers provide their own implementation of the C standard library which may not be compatible with the implementation in another compiler or platform. Without cross platform libraries and tools, one cannot state that C is portable. This is in stark contrast to modern programming languages that provide their own cross platform libraries and compilers, such as D, Go and Rust.
Con Only offers basic support for source code split into multiple files
Modern programming languages are capable of compiling split source code files by concatenating them together efficiently at compile time before compiling them. However, C requires the developer to resort to messing with header files and makefiles to get similar functionality.
Con C structs are very weak and outdated
C structs lack a lot of modern capabilities that are vital in programming languages of today, such as assigning member functions to structs to give them object-oriented capabilities, constructs, deconstructors and RAII. Great care must be used when using structs in C to prevent memory leaks and ridiculously slow structs.
Con Includes require obscene resources to compile
All the modern languages have resulted in ditching the ancient deprecated model of #include statements and have instead adopted the superior model of modules. When compiling software written in C, the programmer is forced to also compile X headers which contain Y headers which contain Z headers and so forth -- drastically increasing the number of lines that need to be compiled. In order to compile something as simple as "Hello, World", for example, 18K lines of code needs to be compiled. This can be very taxing on RAM and CPU resources, causing compile times to quickly absorb a large portion of the programming process.
Con Heavily outdated programming concepts
C lacks a large majority of programming concepts that modern languages make use of today. The existing functionality of C makes use of outdated and deprecated methodologies which can be of great annoyance to the modern day programmer.
Con Extremely complicated and inconsistent rules
In Bash, exceptions are the rule, not even all being described by the main page.
There are a grand total of 5 different ways of quoting, sometimes even when one does not want to, for instance in command substitutions. These are all based around preserving the literal meaning of every character, with an exception list. There is even an exception list to the exception list in 4 of the 5, regarding how the backslash behaves! The behavior of the backslash is also one of the quoting rules, so naturally, it also has an exception in how it works when it stands before a newline as compared to other characters.
Bash has several layers of interpretations, all to be kept in mind:
The ~ expands to the home of the current user. So if you store it in a variable, can you use it that way? Nope: tilde expansion comes before variable expansion.
Aha, so that's how it works! Then, since applying quotation happens after redirections are set up, it must mean that redirecting within quotes works, right? Nope: there is an exception! If a redirection symbol is not quoted, quotation around the symbol is observed, but is not removed. So, since variable expansion also comes after setting up redirections, and no exceptions are described here in the man page, getting the name of a file from a variable and using it as a target should not work, right? No: redirection does not actually take place when the symbols are being read, the symbols are merely removed and are noted for later, right before when the actual command runs.
Apart from 5 types of quotation, there are basically 2 quoting phases, 2 word splitting phases (with only one being controllable), and a tokenization phase on top of that.
If you have a command, it could be an alias, a special built in, a non-special built in, a symbolic link to a file, a regular file, a function, with different rules regarding how they can be overridden, if redirection happens before or after arguments have been passed (what does "time my_command 2>&1 >log_file" do?), etc.
This list is admittedly long, but it doesn't even scratch the surface of the bloat, complexity and inconsistencies of Bash.
Con GPL3 is not compatible with Apple's lawyers
Apple, one of the largest distributors of UNIX systems, only ships an ancient version of bash that predates the iPhone.
No one knows why as Apple hasn't said, but the version Apple includes in MacOS is from right before the license was updated to version 3 of the GNU GPL (General Public License). Other major companies (IBM, Microsoft) have had no problem shipping the latest version of bash
, so it's unclear what Apple's lawyers are averse to. The GPL has always said that if you distributed a program, you granted everyone the right to use it freely. The biggest change in version 3 was the addition, "...and that includes software patents."
This was necessary because back in 2006 Microsoft was demanding that any company that uses Linux pay them or get sued for infringing on their patents. They even took some companies, like TomTom, to court. No software which can be restricted retroactively like that is truly free, so GPL 3+ includes a clause saying that if you distribute the program, then you are also granting license to any patents you own that are necessary to run it.
What patents Apple has that bash could possibly infringe on is a mystery, but the bigger question is, Why does Apple even care? So what if they are granting people the right to run bash without being sued by Apple. It's not like they were planning on doing that, right?
Even though it is not bash's fault that it is not Apple Lawyer-approved, this is a CON for it because a lot of people use Apple products. While there are methods like brew
to install a current version of bash, Apple does not make it obvious to their customers what they are missing.
Con Compatibility can be a curse
One of bash's claims to fame is compatibility with previous versions of itself and historic shells. But, doing that means that new features are often written in tortured, awkward syntax that is not easy to learn. For example, bash uses the POSIX way of doing arithmetic: to add 5+3 you must put the numbers in double parentheses with a dollar sign at the start: x=$((5+3)). It is true that many shells suffer from this same CON, but since bash is such an important shell, it has less wiggleroom to ditch clunky ideas that might break existing scripts.
Con Lags behind on features compared to ZSH and Fish
People who wants power features or to customize their shell experience use zsh or fish.
Con Filename expansion is not consistent
filename expansion is not consistent. "echo *" will print the names of the files in your current dir, if there are any... and will print "*" if there are none.
Con Non-intuitive shell expansion in for loops
If there are no .sh files, this will print mask itself:
for filename in *.sh; do
echo $filename
done
Con No out-of-the-box command autocompletion
To have command autocompletion in bash you need to install third-party plug-ins.
Con One of the most dangerous languages around
What it is mostly used for are file system operations. Guess what it is bad at? Operating on files. It automatically splits and carries out filename expansion on every single string resulting from variable expansion and command substitution unless quoted, by default on whitespace, whilst spaces are very common in filenames.
Before that, it even does pathname expansion, so woe to anywone who does not want to actually operate on files, but has a globbing metacharacter stored anywhere in a variable.
This means what you store in a variable is not going to be what will ACTUALLY be accessed.
If an empty variable is unquoted, it disappears completely due to word splitting, sometimes leading to applications signalling a missing parameter at a wrong position.
If quoted however, said variables cannot be iterated over in a loop, no matter what character one uses for word splitting.
If you use any globbing pattern with a command, be sure to use -- after the option arguments or if none are present, before starting the pattern with a mandatory ./
Otherwise, another Bash script run gone wrong or a hacker can create files named like an option ("-f", for instance) and your program will happily accept it as such, if it results from globbing.
For interactive use, it is convenient. For programming, it is a no-go.