Tell me more ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

I am confused with the wide array of ways to implement existing data types in hardware as it all seems a bit illusory.

For example:

  1. There's no such thing as a software stack or a hardware stack; a "hardware stack" is merely an implementation of a first in, last out specification of bits, but there's no real "stack" anywhere.

  2. Arrays are pointers to a group of bits; there's no real indices sitting in memory.

  3. Hash tables are just pointers as well.

  4. Vectors are the same as arrays; they just enable the ability to change the values.

They're all illusory, and mask the bits that are there.

Why waste time with all of this when you can just manipulate the bits, the real data, and not some implementation of illusory data from some data type specification?

share|improve this question
14  
You can. Write assembly. – L0j1k Feb 27 at 22:40
28  
"Programs must be written for people to read, and only incidentally for machines to execute." - SICP – back2dos Feb 27 at 23:20
5  
@Snow: The issue is what do you mean by "exist." A data type may be thought of as a technique rather than a thing, and that we have frameworks which automate using such techniques. Underneath it is all just bits, but how we use the bits is determined by what we want to do with them. We might see an ip4 address as a data type distinct from a 32-bit int for example because we may want have things different things done to it. This is particularly important when designing new data types for PostgreSQL for example, as indexing methods may vary. – Chris Travers Feb 28 at 1:10
4  
@Snow: Yes, none of it is real, it's just layers of abstraction. That's the whole point. You can use those bits to represent anything you want. Just like the words and phonemes of human language don't really exist, we're just animals making sounds. The Great Vowel Shift of the 15th century pisses me off, but I know if I start pronouncing vowels in English as if they were in Latin, no one would understand me. The sound "YAH" means "yes" in German, "I" in Russian, and "already" in Spanish. Same sound, different meaning depending on the encoding or "data type". – Joe Ballard Feb 28 at 1:16
16  
Don't look now, but you don't exist. You're nothing but a pile of molecules, which themselves are simply cleverly arranged atoms. And your mind is even more ephemeral -- it's mere electrical patterns, barely discernable from the snow on an analog television and less organized than the bits which so disturb you. – Caleb Feb 28 at 4:16
show 16 more comments

We're looking for long answers that provide some explanation and context. Don't just give a one-line answer: please explain why you're recommending it as a solution. Answers that don't explain anything will be deleted. See Good Subjective, Bad Subjective for more information.

closed as not a real question by Robert Harvey, Eric King, Jim G., mattnz, rwong Mar 2 at 16:17

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, see the FAQ.

11 Answers

If you find it difficult to read 0s and 1s below, scroll to the bottom of the post and hover over the empty looking "spoiler" gray box.

01010100 01101000 01100101 00100000 01110010 01100101 01100001 01110011 01101111 01101110 00100000 01110100 01101000 01100001 01110100 00100000 01110000 01110010 01101111 01100111 01110010 01100001 01101101 01101101 01100101 01110010 01110011 00100000 01110101 01110011 01100101 00100000 01100100 01100001 01110100 01100001 01110100 01111001 01110000 01100101 01110011 00100000 01110010 01100001 01110100 01101000 01100101 01110010 00100000 01110100 01101000 01100001 01101110 00100000 01110010 01100001 01110111 00100000 01100010 01101001 01110100 01110011 00100000 01101001 01110011 00100000 01100010 01100101 01100011 01100001 01110101 01110011 01100101 00100000 01110010 01100101 01110001 01110101 01101001 01110010 01101001 01101110 01100111 00100000 01110100 01101000 01100101 00100000 01101000 01110101 01101101 01100001 01101110 00100000 01100010 01110010 01100001 01101001 01101110 00100000 01110100 01101111 00100000 01110100 01110010 01100001 01101110 01110011 01101100 01100001 01110100 01100101 00100000 01100010 01101001 01101110 01100001 01110010 01111001 00100000 01110100 01101111 00100000 01110100 01101000 01100101 00100000 01100001 01110000 01110000 01110010 01101111 01110000 01110010 01101001 01100001 01110100 01100101 00100000 01110011 01100101 01101101 01100001 01101110 01110100 01111001 01100011 00100000 01110100 01111001 01110000 01100101 00100000 01101001 01101101 01110000 01101111 01110011 01100101 01110011 00100000 01100001 00100000 01101101 01100001 01110011 01110011 01101001 01110110 01100101 00100000 01100011 01101111 01100111 01101110 01101001 01110100 01101001 01110110 01100101 00100000 01101100 01101111 01100001 01100100 00100000 01110100 01101000 01100001 01110100 00100000 01110111 01101111 01110101 01101100 01100100 00100000 01101101 01100001 01101011 01100101 00100000 01110000 01110010 01101111 01100100 01110101 01100011 01110100 01101001 01110110 01101001 01110100 01111001 00100000 01101110 01101111 01101110 00101101 01100101 01111000 01101001 01110011 01110100 01100001 01101110 01110100 00101110 00100000 00100000 01000110 01101111 01110010 00100000 01101001 01101110 01110011 01110100 01100001 01101110 01100011 01100101 00101100 00100000 01101001 01110100 00100000 01101001 01110011 00100000 01101110 01100101 01100001 01110010 01101100 01111001 00100000 01100011 01100101 01110010 01110100 01100001 01101001 01101110 00100000 01110100 01101000 01100001 01110100 00100000 01101110 01101111 00100000 01101000 01111101 01101101 01100001 01101110 00100000 01100010 01100101 01101001 01101110 01100111 00100000 01110111 01101001 01101100 01101100 00100000 01110010 01100101 01100001 01100100 00100000 01110100 01101000 01101001 01110011 00100000 01110100 01100101 01111000 01110100 00100000 01110111 01101001 01110100 01101000 01101111 01110101 01110100 00100000 01110101 01110011 01101001 01101110 01100111 00100000 01110011 01101111 01101101 01100101 00100000 01110011 01101111 01110010 01110100 00100000 01101111 01100110 00100000 01101101 01100001 01100011 01101000 01101001 01101110 01100101 00100000 01110100 01110010 01100001 01101110 01110011 01101100 01100001 01110100 01101111 01110010 00100000 01110100 01101111 00100000 01110100 01110010 01100001 01101110 01110011 01101100 01100001 01110100 01100101 00100000 01110100 01101000 01100101 01110011 01100101 00100000 00110001 01110011 00100000 01100001 01101110 01100100 00100000 00110000 01110011 00100000 01101001 01101110 01110100 01101111 00100000 01100001 00100000 01100100 01100001 01110100 01100001 01110100 01111001 01110000 01100101 00100000 00101000 01110100 01100101 01111000 01110100 00101001 00100000 01111100 01101000 01100001 01110100 00100000 01110100 01101000 01100101 01111001 00100000 01100011 01100001 01101110 00100000 01101101 01101111 01110010 01100101 00100000 01101101 01100001 01110011 01101001 01101100 01111001 00100000 01110101 01101110 01100100 01100101 01110010 01110011 01110100 01100001 01101110 01100100 00101110 00100000 00100000 01010011 01101111 00100000 01101001 01110100 00100000 01101001 01110011 00100000 01110111 01101001 01110100 01101000 00100000 01100001 01101100 01101100 00100000 01100100 01100001 01110100 01100001 01110100 01111001 01110000 01100101 01110011 00101110 00100000 00100000 01010100 01101000 01100101 00100000 01101000 01110101 01101101 01100001 01101110 00100000 01101101 01100101 01101110 01110100 01100001 01101100 00100000 01110000 01110010 01101111 01100011 01100101 01110011 01110011 01101001 01101110 01100111 00100000 01110100 01101111 00100000 01100011 01101111 01101110 01110110 01100101 01110010 01110100 00100000 01100001 00100000 00110011 00110010 00101101 01100010 01101001 01110100 00100000 01110010 01100101 01110000 01110010 01100101 01110011 01100101 01101110 01110100 01100001 01110100 01101001 01101111 01101110 00100000 01101111 01100110 00100000 01100001 00100000 01100110 01101100 01101111 01100001 01110100 01101001 01101110 01100111 00100000 01110000 01101111 01101001 01101110 01110100 00100000 01101110 01010101 01101101 01100010 01100101 01110010 00100000 01101001 01101110 01110100 01101111 00100000 01110100 01101000 01100101 00100000 01110010 01100101 01110000 01110010 01100101 01110011 01100101 01101110 01110100 01100001 01110100 01101001 01101111 01101110 00100000 01110100 01101000 01100001 01110100 00100000 01101001 01110011 00100000 01100001 01100011 01110100 01110101 01100001 01101100 01101100 01111001 00100000 01110101 01101110 01100100 01100101 01110010 01110011 01110100 01100001 01101110 01100100 01100001 01100010 01101100 01100101 00100000 01101001 01110011 00100000 01100110 01100001 01110010 00100000 01100111 01110010 01100101 01100001 01110100 01100101 01110010 00100000 01110100 01101000 01100001 01101110 00100000 01110100 01101000 01100101 00100000 01100101 01100110 01101110 01101111 01110010 01110100 00100000 01110100 01101111 00100000 01110100 01110010 01100001 01101110 01110011 01101100 01100001 01110100 01100101 00100000 00110000 00110000 00110001 00110000 00110000 00110000 00110000 00110001 00100000 01101001 01101110 01110100 01101111 00100000 00100111 01100001 00100111 00101110 00100000 00100000 01011001 01100101 01110100 00100000 01101110 01101111 00100000 01101111 01101110 01100101 00100000 01110111 01101111 01110101 01101100 01100100 00100000 01100010 01100101 00100000 01110111 01101001 01101100 01101100 01101001 01101110 01100111 00100000 01110100 01101111 00100000 01100100 01101111 00100000 01100101 01110110 01100101 01101110 00100000 01110100 01101000 01101001 01110011 00100000 01100101 01100001 01110011 01101001 01100101 01110010 00100000 01110100 01110010 01100001 01101110 01110011 01101100 01100001 01110100 01101001 01101111 01101110 00101110 00100000 00100000 00100000 00001010 00001010 01010100 01101000 01100101 01110010 01100101 00100000 01110111 01100001 01110011 00100000 01100001 00100000 01010100 01101001 01101101 01100101 00100000 01110111 01101000 01100101 01101110 00100000 01110000 01100101 01101111 01110000 01101100 01100101 00100000 01100100 01101001 01100100 00100000 01110111 01101111 01110010 01101011 00100000 01100100 01101001 01110010 01100101 01100011 01110100 01101100 01111001 00100000 01101001 01101110 00100000 01100010 01101001 01101110 01100001 01110010 01111001 00101100 00100000 01100010 01110101 01110100 00100000 01101001 01110100 00100000 01110111 01100001 01110011 00100000 01100001 00100000 01110100 01101001 01101101 01100101 00100000 01110111 01101000 01100101 01101110 00100000 01110000 01110010 01101111 01100111 01110010 01100001 01101101 01110011 00100000 01100100 01101001 01100100 00100000 01100110 01100001 01101001 01110010 01101100 01111001 00100000 01110011 01101001 01101101 01110000 01101100 01100101 00100000 01110100 01100001 01110011 01101011 01110011 00100000 01101100 01101001 01101011 01100101 00100000 01100011 01110010 01100101 01100001 01110100 01101001 01101110 01000111 00100000 01110000 01110010 01101001 01101110 01110100 01100101 01100100 00100000 01110011 01101001 01101110 00100000 01110100 01100001 01101010 01101100 01100101 01110011 00101100 00100000 01110000 01110010 01101111 01100111 01110010 01100001 01101101 01110011 00100000 01110100 01101000 01100001 01110100 00100000 01110100 01101111 01100100 01100001 01111001 00100000 01100001 01110010 01100101 00100000 01100001 00100000 01110100 01101000 01110010 01101111 01110111 00101101 01100001 01110111 01100001 01111001 00100000 01101111 01101110 01100101 00101101 01101100 01101001 01101110 01100101 01110010 00100000 01110100 01101000 01100001 01101110 00100000 01110100 01101111 01101111 01101011 00100000 01101000 01101111 01110101 01110010 01110011 00100000 01101111 01110010 00100000 01100100 01100001 01111001 01110011 00100000 01101111 01100110 00100000 01110100 01111000 01101111 01110101 01100111 01101000 01110100 01001110 00000000

The reason that programmers use datatypes rather than raw bits is because requiring the human brain to translate binary to the appropriate semantic type imposes a massive cognitive load that would make productivity non-existent. For instance, it is nearly certain that no human being will read this text without using some sort of machine translator to translate these 1s and 0s into a datatype (text) that they can more easily understand. So it is with all datatypes. The human mental processing to convert a 32-bit representation of a floating point number into the representation that is actually understandable is far greater than the effort to translate 00100001 into 'a'. Yet no one would be willing to do even this easier translation.

There was a time when people did work directly in binary, but it was a time when programs did fairly simple tasks like creating printed sin tables, programs that today are a throw-away one-liner than took hours or days of thought.

For comparison, above is the same text displayed translated to binary

share|improve this answer
7  
For those interested in reading the message: roubaixinteractive.com/PlayGround/Binary_Conversion/… – Mason Wheeler Feb 28 at 0:38
28  
You've made it very difficult to edit the typos. Nevertheless, brilliant answer. – Robert Harvey Feb 28 at 0:42
3  
@Chris: A null terminator isn't part of the message, it's simply one of many conventions used to tell when the message is supposed to end. (And probably the worst possible convention you could use.) – Mason Wheeler Feb 28 at 1:08
3  
@MasonWheeler It is, however, part of what we might think of as a standard data type, and the omission of any such convention, and need to correct it, explains why we need data types. – Chris Travers Feb 28 at 1:13
7  
Personally, I find the spaces between the bytes unnecessary and confusing. After all, isn't everything just a series of bits? ;) – Daniel B Mar 1 at 6:14
show 3 more comments

Data types exist to give bits some "shape." Without that shape, bits would be just so many ones and zeroes.

Everything has a shape. Imagine asking someone to look at your raw bits, instead of the picture these bit embody in the JPG format. Imagine if your arrangement of bits that comprises a picture were different from everyone else's. You would have to transmit the specifications for your bits with the bits, and perhaps the software to read those bits as well.

Array, hash tables, vectors and all other data types are all just abstractions that make your life easier as a programmer. Doubles, Ints and other numerical types allow you to say X + Y and get a meaningful answer that is correct, in a way that is well-understood by everyone else.

The life of a programmer, in large part, is dedicated to placing bits into these well-defined containers, such as classes and objects. These containers form part of the language that a programmer speaks. That language improves productivity because it occurs at a higher level than bits and bytes; it is closer to the language that we as humans speak.

These kinds of abstractions are the reason we drive cars today, and not covered wagons.

share|improve this answer
Well said. +1 for "making life easier" that answers this question so well. – L0j1k Feb 27 at 22:40
3  
Why do you take water from the tap, instead of manufacturing all of the individual water molecules yourself? – Robert Harvey Feb 27 at 22:46
1  
And the user of your hypothetical machine not know anything about all those bits. Volts don't exist either; that's just an abstraction for measuring electrical pressure. – Robert Harvey Feb 27 at 22:48
7  
I admire your passion, but it is misguided. Tools like programming languages, compilers, data structures and algorithms exist because we learned how to do a thing, then we packaged that thing into a piece of software and gave it a name, so that we wouldn't have to re-invent that thing over and over again. – Robert Harvey Feb 27 at 22:50
1  
Never ask somebody to look at your raw bits. – Craige Feb 28 at 2:35
show 7 more comments

Because you need to know the encoding.

Let me put it this way. An integer is a sequence of ones and zeroes- but you don't know what value that integer is, unless you know in advance it's two's complement or whatever. If you have a pointer to a sequence of bits, how many of those bits makes the integer you're looking at? If you don't know, how can you possibly operate on it?

Data types are what gives bits meaning and permit real operations to take place. If they don't have a type, you can't know what they represent, so they're worthless.

At the most basic level, consider pointers. If you got any random bunch of bits and tried to treat it as a pointer, not only would you get absolutely nonsense out, but you'd be virtually guaranteed to simply crash your program. Because "A sequence of bits" is not a valid pointer. You won't get a meaningful result treating a floating-point value as an integer and adding it to another float treated the same way. The result is simply irrelevant noise. You have to know whether to use FP addition or integral addition.

If you get some random sequence of bits and treat it as an integer, and you print it to the screen, then maybe it'll work, but what have you achieved? Nothing- it just prints some random shit. If you want to print something meaningful, you need to know where to find that something, which is data types all over again.

share|improve this answer

Yes, at the lowest level, it's all a sequence of bits. But people--even programmers--have a very hard time thinking about sequences of bits. The basic reason why these things exist is to make them easier for programmers to think about.

Computer software is the most complicated class of engineering ever undertaken in the history of mankind. Programs regularly end up with millions or even tens of millions of lines of code. There's simply no way for a human being to hold all of that in their head! So instead, we come up with abstractions (the technical name for the "illusions" you're complaining about) that makes it easier to relate to different levels of the issue at hand, so that it can be handled one small piece at a time, and in a way that you can come back to later, and read and understand what's going on.

If it wasn't for this, we would have no way to do anything useful with computers beyond a very small scale. Look at what computers were capable of doing before the invention of FORTRAN and COBOL, and then compare that with what they're capable of doing today. A lot of that growth in the capabilities of computing comes from advances in hardware, but a lot of it doesn't. It comes from better programming tools.

share|improve this answer

The abstractions that make you angry are all made of bits too. So, if in your perfect, non-angry world we would manipulate bits directly - guess what? We are in that perfect world because we can't not just manipulate bits directly, since everything else is just imaginary anyway.

So, relax. Look at the unicorns, take a hash table for a walk...

share|improve this answer
+1 for the unicorn reference – GlenH7 Feb 28 at 0:45
+1 This is the most insightful answer. If it's all bits, then te problem goes away, since we're just manipulating bits. – Ingo Mar 2 at 10:39

There are some extremely practical reasons why these abstractions are a Good Thing (tm) as well.

  • Without the abstractions, software development would be hard. Not just challenging, but mind-numbingly painful, like slamming your head in a car door.
  • Because of its extreme difficulty, programmer burnout would be extremely high.
  • Because of its extreme difficulty, few would choose it as their profession.
  • Because of the previous two points, programmers would be extremely rare and valuable.
  • Because of the previous three points, the entire economic system would have evolved away from the computer entirely. Computation would be stuck in the 1950's - the plaything of big government and big business, but of extremely little value to anyone, particularly the man on the street.
share|improve this answer
+1 for pointing out that without data types and structures we would be stuck in the 50s. – COME FROM Mar 1 at 10:05

Bits are not binary numbers they are bi-dimensional flip flop voltage gates.

They carry two states:"; that is why we use a binary base two nunber system to Represent them. Since they only mean what you tell them to, it is hard to tell little flip flop voltages that you want millions of things to happen directly, so we mask those voltages with data types, and these are the most basic tools in high level languages.

In assembly you do interface without data types, just bits. That is what you want to do if you want to directly interface flip flop gates or opcodes is even harder, but more intrinsic to the architecture.

share|improve this answer
This raises a very good point - a bit can only represent two states, "on" or "off". Not particularly useful on its own, unless you're controlling lights. It's only in the aggregate that they become more useful, and the meaning supplied by those higher-order aggregations. – GalacticCowboy Feb 28 at 19:27

While a many good reasons have been given already, they don't tackle the real benefits of strong typing: With strong typing you can apply all kinds of neat mathematical theorems that help to validate the correctness of statements, in the sense that a compiler can ensure, that at least from a category theoretical point of view the thing written makes sense.

Theoretical computer science is mostly math and logic and not so much "just" bit manipulation.

If you want to know what strong type systems can do, take a look at Curry-Howard correspondence and its practical applications in programming languages like Haskell.

EDIT

Why waste time with all of this when you can just manipulate the bits, the real data, and not some implementation of illusory data from some data type specification?

Do you really think that the computer is spending time on data types when executing a binary compiled program? In dynamically typed languages, yes, there is time spent on data type management. But when you execute a programm written in statically typed languages, no type management happens at runtime (unless some library that's being used implements this, for some reason).

Thinking in types is certainly no waste.

share|improve this answer
the question is not about this. strong typing != data types – gnat Feb 28 at 19:41
1  
@gnat: Well, the kind of types OP is asking about collapse down into bit manipulation at compilation as well. Any notion of a data type, and be it an array or even something fundamental like a pointer is something abstract. And technically you can apply category theory to those as well. – datenwolf Feb 28 at 19:43

In my youth I programmed a lot of assembler.

Most assembler languages have instructions to handle bytes, integers (small, big , and sometimes really big), floats and doubles. However there is no type checking so you can easily (and I mean really easily) do a floating point divide of the first four characters of your name by the first four characters of your order number. And the obedient processor will do just that.

So having worked in a totally type less environment believe me when I say strong typing is a blessing. The main advantage of modern OO program languages is that they extend type checks beyond the usual int,char, string to things like "orders" and "shipments".

share|improve this answer

It's historically untrue. In the Burroughs architecture, you could have a 48 bit double that was bitwise identical to an integer, yet distinct. Even in todays x86 architecture, instructions and data may appear bitwise identical, but an attempt to execute data or write to code would fail.

Now, there's only a limited number of distinctions you can reasonably make. Is a point {x,y} the same datatype as a direction {x,y} ? Modern CPU design reflects the limited value in precise datatyping.

share|improve this answer

Take an analogy to real life.

When you have a conversation with someone, you're only making air waves, right? But not just any old air waves. The point is, you are encoding meaning in those air waves. If you weren't, it would just be noise.

Or consider written text, like this, as opposed to ;24l5nacvpvqu43qrnqcnaop8u9 vyhcqnjk4r. What makes all those little blobs of light and dark spots make any sense is that you and I have learned that certain collections of them actually allow us to exchange meaningful information, about concepts we know.

What a datatype is is a subset of the possible bit patterns that we assign meaning to, so when we want the computer to do something we understand, we can tell it, and it will tell us the consequences of that in the same language. That requires constraining the bit patterns to the ones we've assigned a meaning to.

share|improve this answer

protected by maple_shaft Feb 28 at 23:14

This question is protected to prevent "thanks!", "me too!", or spam answers by new users. To answer it, you must have earned at least 10 reputation on this site.

Not the answer you're looking for? Browse other questions tagged or ask your own question.