Hot answers tagged

157

This depends on your definition of high-level and low-level language. When C was developed, anything that was higher-level than assembly was considered a high-level language. That is a low bar to clear. Later, this terminology shifted to the point that some would nowadays consider even Java to be a low-level language. Even within the high-level language ...


147

The problem is that #1 requires you effectively parse and interpret the entirety of the SQL variant you're working against so you know if it is doing something it shouldn't. And keep that code up to date as you update your database. Everywhere you accept input for your queries. And not screw it up. So yes, that sort of thing would stop SQL injection attacks,...


144

To answer the historical aspects of the question: The design philosophy is explained in The C Programming Language written by Brian Kernighan and C designer Dennis Ritchie, the "K&R" you may have heard of. The preface to the first edition says C is not a "very high level" language, nor a "big" one... and the introduction says C is a relatively "...


140

OOP did not invent encapsulation and is not synonymous with encapsulation. Many OOP languages do not have C++/Java style access modifiers. Many non-OOP languages have various techniques available to offer encapsulation. One classic approach for encapsulation is closures, as used in functional programming. This is significantly older than OOP but is in a way ...


117

Because immutable collections absolutely require sharing to be usable. Otherwise, every single operation drops a whole other list into the heap somewhere. Languages that are entirely immutable, like Haskell, generate astonishing amounts of garbage without aggressive optimizations and sharing. Having collection that's only usable with <50 elements is not ...


116

In short, there aren’t any particularly useful subtraction-like operations on strings that people have wanted to write algorithms with. The + operator generally denotes the operation of an additive monoid, that is, an associative operation with an identity element: A + (B + C) = (A + B) + C A + 0 = 0 + A = A It makes sense to use this operator for things ...


110

As far as I understand, pipe is a system call which shares a piece of memory between two processes where one process writes and other reads from. Actually, there is no shared memory involved. The reader and writer are NOT sharing any part of their address space, and they are not using any explicit synchronization. The reading and writing processes are ...


104

0 is false because they’re both zero elements in common semirings. Even though they are distinct data types, it makes intuitive sense to convert between them because they belong to isomorphic algebraic structures. 0 is the identity for addition and zero for multiplication. This is true for integers and rationals, but not IEEE-754 floating-point numbers: 0.0 ...


98

Writing a compiler seems like a much harder problem than an interpreter. That might be true today, but I would argue that it was not the case some 60 years ago. A few reasons why: With an interpreter, you have to keep both it and the program in memory. In an age where 1kb of memory was a massive luxury, keeping the running memory footprint low was key. And ...


80

A mutable collection is not a subtype of an immutable collection. Instead, mutable and immutable collections are sibling descendants of readable collections. Unfortunately, the concepts of "readable", "read-only", and "immutable" seem to get blurred together, even though they mean three different things. A readable collection base class or interface type ...


80

Because option 1 is not a solution. Screening and filtering means rejecting or removing invalid input. But any input might be valid. For example apostrophe is a valid character in the name "O'Malley". It just have to be encoded correctly before being used in SQL, which is what prepared statements does. After you added the note, it seems you are basically ...


75

Because the math works. FALSE OR TRUE is TRUE, because 0 | 1 is 1. ... insert many other examples here. Traditionally, C programs have conditions like if (someFunctionReturningANumber()) rather than if (someFunctionReturningANumber() != 0) because the concept of zero being equivalent to false is well-understood.


72

In its most basic form, a website serves static files. Mapping the URL path to a file path is the most obvious choice; essentially, it's a read-only FTP site. Then people wanted to change the content of the page with some scripting. The easiest way is to embed a scripting language into the page and run it through an interpreter. Again, given the already ...


69

It isn't that the goto is bad by itself. (After all, every jump instruction in a computer is a goto.) The problem is that there is a human style of programming that pre-dates structured programming, what could be called "flow-chart" programming. In flow-chart programming (which people of my generation learned, and was used for the Apollo moon program) you ...


66

Although there were older precursors, the influential French mathematician Rene Descartes is usually credited for introducing superscripted exponents (ab) into mathematical writing, in his work Geometrie which was published in 1637. This is the notation still universally used in mathematics today. Fortran is the oldest programming language widely used for ...


65

Suppose we're designing a new language and we want Sqrt to be an instance method. So we look at the double class and begin designing. It obviously has no inputs (other than the instance) and returns a double. We write and test the code. Perfection. But taking the square root of an integer is valid, too, and we don't want to force everyone to convert to ...


64

Why is goto dangerous? goto doesn't cause instability by itself. Despite about 100,000 gotos, the Linux kernel is still a model of stability. goto by itself should not cause security vulnerabilities. In some languages however, mixing it with try/catch exception management blocks could lead to vulnerabilities as explained in this CERT recommendation. ...


60

While probably not the original reason for the 80 character limit, a reason that it was accepted widely is simply reading ergonomics: If lines are too short, text becomes hard to read because you must constantly jump from one line to the next while reading. If lines are too long, the line jumping becomes too hard because you "lose the line" while ...


60

If you're trying to do string processing, then you're not really generating an SQL query. You're generating a string that can produce an SQL query. There's a level of indirection that opens up a lot of room for errors and bugs. It's somewhat surprising really, given that in most contexts we're happy to interact with something programmatically. For ...


59

Besides the void * pointer which is covered in Robert's answer, a technique like this was used (Disclaimer: 20 year old memory): #define WANTIMP #define TYPE int #include "collection.h" #undef TYPE #define TYPE string #include "collection.h" #undef TYPE int main() { Collection_int lstInt; Collection_string lstString; } Where I ...


59

The reason C# (and Java and essentially every other OO language developed after C++) did not copy C++'s model in this aspect is because the way C++ does it is a horrendous mess. You correctly identified the relevant points above: struct: value type, no inheritance. class: reference type, has inheritance. Inheritance and value types (or more specifically, ...


58

I was asked by a student if & and * were chosen because they were next to each other on the keyboard (something I had never noticed before). Much googling led me to B and BCPL documentation, and this thread. However, I couldn't find much at all. It seemed like there were lots of reasons for * in B, but I couldn't find anything for &. So following @...


50

It's always easy to link Fowler. One of the main examples that go against SESE are guard clauses: Replace Nested Conditional with Guard Clauses Use Guard Clauses for all the special cases double getPayAmount() { double result; if (_isDead) result = deadAmount(); else { if (_isSeparated) result = separatedAmount(); else { ...


50

On early microcomputers editing was line based. You couldn't just move freely around in the source code and edit. You had a single line at the bottom of the screen where you could type commands and enter code. The rest of the screen was read-only code-listings and command output. If you wanted to edit say line 90 in the program you wrote "EDIT 90", and the ...


47

The traditional way to implement generics without having generics (the reason templates were created) is to use a void pointer. typedef struct Item{ void* data; } Item; typedef struct Node{ Item Item; struct Node* next; struct Node* previous; } Node; In this example code, a binary tree or doubly-linked list can be represented. ...


Only top voted, non community-wiki answers of a minimum length are eligible