So C is a horrible language is it?
He never said that. he said it is a Horrible <application> Language. That is, for Application programs.
Why is it still popular?
It's not. At least a dozen other languages find far more pervasive use in Application Development.
Or should we just move on with C++ and it would be ok again?
Hmm, you seem to be considering that C++ is simply C with some extensions. this is not the case. First, C is a structured language.
That is an Old axiom. Can it work? well, yes. But the structured programming paradigm doesn't really translate well when your looking at various threads trying to communicate back and forth, window messages being sent to and fro, and so forth.
OOP, Object Oriented Programming, became popular not out of the blue, but
as a direct result of the introduction of more sophisiticated GUIs. C++ is a rather hacky OOP language, and, strictly speaking, it isn't an object oriented language. if it were, you wouldn't be able to work <without> objects. It's an OOOP- Optionally Object Oriented. Most standard C code will still compile with a C++ compiler (well, actually, that's not true, it will always require a few changes, depending on wether it was designed to be ported to C++ as well as how old it is).
Even now, we are starting to explore a area <beyond> Object Oriented- Functional Programming.
C# is a Object Oriented Language. it <HAS> to have at least one object. you cannot decide "I don't want any objects". you need at least one.
Now, with C# Version 3, it has also become a Optionally Functional Language as well.
With C, you can "emulate" Object oriented-ness by using structures, and mapping your own Vtable- you create a structure that contains function pointers to the "methods" of the object, whose first parameter is a pointer to that structure, and you give that structure memory spaces for the member variables.
In order to create an "Object" you would probably create a special function, which initializes all the function pointers in the structure (more conventionally called a V-Table (Virtual Function table)) to point to your definition of the function (usually just one). In each implementation, you manipulate the member variables of the passed in pointer.
You would then call the methods something like this:
result=pretendobject->vt->function(&pretendobject,param1,param2....) etc
note that that is just <One> possible way of doing it, conventionally, the structure itself actually contains another nested structure that holds the vtable, (as shown here by the vt member of the main structure).
This requires <pages> UPON PAGES of code to create, just a simply framework for this. with any semi-modern language, you get this free. And I haven't a clue how you would do functional programming in it.
Now, to compare Object Oriented Programming and Functional Programming. Let's say- you had an array of variables. For simplicity's sake, we'll say they represent grayscale colour: We'll define that black is 0, and pure white is 10.0.
First, our little program will increase the contrast- if the pixel is above five, we'll increase the value by 1.5 * (p – 5). If the pixel is below 5, we'll decrease the value by (p – 5) * 1.5. Further, we'll limit the range – a pure white pixel can't get any brighter and a pure black pixel can't get any darker.
Second: brighten the "image"- we'll add 1.2 to every pixel, again capping the value at 10.0.
Here it is: (C#, "object Oriented")
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
static class Program
{
private static double Limit(double pixel)
{
if (pixel > 10.0)
return 10.0;
if (pixel < 0.0)
return 0.0;
return pixel;
}
private static void Print(IEnumerable<double> pixels)
{
foreach (var p in pixels)
Console.Write(String.Format("{0:F2}", p).PadRight(6));
Console.WriteLine();
}
public static void Main(string[] args)
{
double[] pixels = new[] { 3.0, 4.0, 6.0, 5.0, 7.0, 7.0, 6.0, 7.0, 8.0, 9.0 };
Print(pixels);
for (int i = 0; i < pixels.Length; ++i)
{
if (pixels[i] > 5.0)
pixels[i] = Limit((pixels[i] - 5.0) * 1.5 + 5.0);
else
pixels[i] = Limit(5.0 - (5.0 - pixels[i]) * 1.5);
}
Print(pixels);
for (int i = 0; i < pixels.Length; ++i)
pixels[i] = Limit(pixels[i] + 1.2);
Print(pixels);
}
}
output from this program is as follows:
3.00 4.00 6.00 5.00 7.00 7.00 6.00 7.00 8.00 9.00
2.00 3.50 6.50 5.00 8.00 8.00 6.50 8.00 9.50 10.00
3.20 4.70 7.70 6.20 9.20 9.20 7.70 9.20 10.00 10.00
Now, the idea of Functional programming is often scoffed at by those used to object oriented programming. The basic idea is that you <never> "change" a variable, you only transform it. in C#, this can be accomplished using LINQ:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
static class Program
{
private static double Limit(double pixel)
{
if (pixel > 10.0)
return 10.0;
if (pixel < 0.0)
return 0.0;
return pixel;
}
private static void Print(IEnumerable<double> pixels)
{
foreach (var p in pixels)
Console.Write(String.Format("{0:F2}", p).PadRight(6));
Console.WriteLine();
}
public static void Main(string[] args)
{
double
[] pixels = new[] { 3.0, 4.0, 6.0, 5.0, 7.0, 7.0, 6.0, 7.0, 8.0, 9.0 };
Print(pixels);
IEnumerable<double> query1 =
from p in pixels
select p > 5.0 ?
Limit((p - 5.0) * 1.5 + 5.0) :
Limit(5.0 - (5.0 - p) * 1.5);
Print(query1);
IEnumerable<double> query2 =
from p in query1
select Limit(p + 1.2);
Print(query2);
}
You'll note that this version is much shorter. the output is <exactly the same>.
Basically, what we have done is "automate", or build into the language as features, what we would normally do manually. C isn't object oriented, so you have to write the framework code yourself, and wire all the functions together manually. C++ and the C++ compiler does this automatically- method calls still accept a "this" pointer, but you cannot actually see it in your code- it is hidden. The significance of this is simple.
You have to write less code.
Now some people have it in their heads some strange notion that somehow writing more code means a program is better. This is quite the opposite. a larger program is unwieldly and hard to manage and change, and most importantly, the more code there is the more bugs there will be. Instead of writing a new object framework for every object type you need (which you <would> need to do, either that, or make some complicated set of macros), you use a tested one- such as the one C++ provides.
In the same token, instead of writing your own implementation of transformations, you let the compiler do it. Many programmers consider this "unpure" and somehow think that this isn't really programming, but truly, there is no reason you should have to write a huge swathe of code just to define an object- the only reason anybody ever does this is because they sufer from hubris.
They think they can do it better. But they can't. the implementations of C++ and other object oriented compilers (and script interpreters in the case of Object oriented (optional or not) script languages) have been refined. you aren't going to find a easy to fix problem with the framework it compiles in for you. Just as you are unlikely to find a bug in the implementation of LINQ; these are well tested language features that are there to be leveraged, not shunned as "impure" simply because they make your job easier.
Using C for Application development is like building a car from teh ground up every time you need to drive it or building a house from scratch everytime you come home. you are doing more work then you need to do only in the purile self-indulgent attitude that you can do it "better". Sure, do it once, learn about the processes involved. But then leave it up the language tool.
The reason I don't use C* (* as in wildcard) is because I don't want to mess up my system by directly accessing memory or whatever.
The worst thing that happens is your program crashes. Nothing else is affected.
You cannot (in windows or Linux, at least) access a certain memory address and say corrupt kernel memory or accidentally overwrite data that belongs to explorer- that is the very definition of "protected memory" - the memory of each process is protected from writes and reads by other processes. Of course, there are ways to do that if you need to, but my point is, you aren't going to accidentally write the code to do so.
Also, since as you said, C* was a wildcard, that means that your saying the same things about C# (and a few other languages, like COBOL, heh). C# is a .NET managed language- which basically means that most of the memory management is done for you.
With C, you have to worry about freeing and allocating memory. It's certainly something all programmers should learn about, but once you understand the concepts, writing the same bloody code over and over doesn't make you a better programmer, it makes you a repetitive one. With C++, you can use pointers and allocate and free manually, but you can also use Smart Pointers (actually, not sure if that's a language feature or some kind of MS extension). in C#, you cannot even get to a pointer without a few hoops, and if your willing to jump through those hoops, you're on your own.