Live data from Hacker News

How to Think About Variables in C

denniskubes.com

41–50 of 66 posts

Re: How to Think About Variables in C

#41
post #39

> C is memory with syntactic sugar and as such it is helpful to think of things in C as starting from memory. http://en.wikipedia.org/wiki/Lie-to-children > A lie-to-children, sometimes referred to as a Wittgenstein's ladder (see below), is an expression that describes the simplification of technical or difficult-to-understand material for consumption by children. The word "children" should not be taken literally, bu…

Thank you.

Re: How to Think About Variables in C

#42

There are some subtle problems with the model as explained in this article. If you use this as your mental model, you will probably run afoul of undefined behavior without realizing it. If you read the C standard, you'll notice it doesn't talk much about "memory" (the word only appears 13 times in C99); it mostly talks about "objects" (mentioned 735 times in C99). These objects aren't OO-objects -- obviously C doesn'…

If a variable were just a memory address and assignment were just a memory copy, this would be a valid operation. It's a valid operation regardless of whether a standards body says it's not. uint32 x = 5; uint16 y = *(uint16*)&x; The effect is to set y to the first two bytes of memory from x. Values assigned to x are serialized into memory in either big endian or little endian order. Those are the only two cases you…

The reason it's useful to explicitly "break the rules" like this is because it's important to know what assumptions you can in fact rely on, regardless of what standards bodies have to say about it.

Given that compilers do break when programmers violate aliasing rules, you should recheck what assumptions you think you can rely on. Non-strict aliasing is not one of them. Unless you want to slow everything down with compiler-specific flags like -fno-strict-aliasing.

    uint8_t foo[4]; *(uint32_t*)foo = 0;
Besides even without strict aliasing, the above is not at all guaranteed to work since not all architectures support unaligned loads. (and if you think "well but no one uses them, just like no one uses 1's complement architectures anymore", keep in mind that this includes ARM)

(also use stdint types already)

Re: How to Think About Variables in C

#43

There are some subtle problems with the model as explained in this article. If you use this as your mental model, you will probably run afoul of undefined behavior without realizing it. If you read the C standard, you'll notice it doesn't talk much about "memory" (the word only appears 13 times in C99); it mostly talks about "objects" (mentioned 735 times in C99). These objects aren't OO-objects -- obviously C doesn'…

If a variable were just a memory address and assignment were just a memory copy, this would be a valid operation. It's a valid operation regardless of whether a standards body says it's not. uint32 x = 5; uint16 y = *(uint16*)&x; The effect is to set y to the first two bytes of memory from x. Values assigned to x are serialized into memory in either big endian or little endian order. Those are the only two cases you…

> It's a valid operation regardless of whether a standards body says it's not.

Whoa there, cowboy. You may not feel personally beholden to standards bodies, but compiler vendors are following their lead. The major compilers are getting more and more aggressive about optimizing away undefined behavior every year.

> The effect is to set y to the first two bytes of memory from x.

No, it's really not. It's undefined behavior and the compiler is free to do absolutely whatever it wants.

> One source of confusion is that int and short are essentially, for all intents and purposes, undefined -- they are of course defined by the standards, but their implementation is allowed to vary so much that no programmer can make any assumptions about their size (in bytes) at runtime.

I agree with this, and have made this argument before: http://blog.reverberate.org/2013/03/cc-gripe-1-integer-types...

But this is an entirely separate issue.

Re: How to Think About Variables in C

#44
post #42

Earlier quoted context omitted.

If a variable were just a memory address and assignment were just a memory copy, this would be a valid operation. It's a valid operation regardless of whether a standards body says it's not. uint32 x = 5; uint16 y = *(uint16*)&x; The effect is to set y to the first two bytes of memory from x. Values assigned to x are serialized into memory in either big endian or little endian order. Those are the only two cases you…

The reason it's useful to explicitly "break the rules" like this is because it's important to know what assumptions you can in fact rely on, regardless of what standards bodies have to say about it. Given that compilers do break when programmers violate aliasing rules, you should recheck what assumptions you think you can rely on. Non-strict aliasing is not one of them. Unless you want to slow everything down with co…

[deleted]

Re: How to Think About Variables in C

#45

There are some subtle problems with the model as explained in this article. If you use this as your mental model, you will probably run afoul of undefined behavior without realizing it. If you read the C standard, you'll notice it doesn't talk much about "memory" (the word only appears 13 times in C99); it mostly talks about "objects" (mentioned 735 times in C99). These objects aren't OO-objects -- obviously C doesn'…

If a variable were just a memory address and assignment were just a memory copy, this would be a valid operation. It's a valid operation regardless of whether a standards body says it's not. uint32 x = 5; uint16 y = *(uint16*)&x; The effect is to set y to the first two bytes of memory from x. Values assigned to x are serialized into memory in either big endian or little endian order. Those are the only two cases you…

[deleted]

Re: How to Think About Variables in C

#46

Earlier quoted context omitted.

If a variable were just a memory address and assignment were just a memory copy, this would be a valid operation. It's a valid operation regardless of whether a standards body says it's not. uint32 x = 5; uint16 y = *(uint16*)&x; The effect is to set y to the first two bytes of memory from x. Values assigned to x are serialized into memory in either big endian or little endian order. Those are the only two cases you…

> It's a valid operation regardless of whether a standards body says it's not. Whoa there, cowboy. You may not feel personally beholden to standards bodies, but compiler vendors are following their lead. The major compilers are getting more and more aggressive about optimizing away undefined behavior every year. > The effect is to set y to the first two bytes of memory from x. No, it's really not. It's undefined beha…

No, it's really not. It's undefined behavior and the compiler is free to do absolutely whatever it wants.

The point is that compilers do some specific thing, regardless of the fact that the standards bodies say they're free to reboot your computer.

As long as all you care about is x86/x86_64/PowerPC (and probably ARM as well), then you can trust that the compiler is going to generate code which copies the first two bytes of x into the memory occupied by y.

Re: How to Think About Variables in C

#47
post #44
post #42

Earlier quoted context omitted.

The reason it's useful to explicitly "break the rules" like this is because it's important to know what assumptions you can in fact rely on, regardless of what standards bodies have to say about it. Given that compilers do break when programmers violate aliasing rules, you should recheck what assumptions you think you can rely on. Non-strict aliasing is not one of them. Unless you want to slow everything down with co…

[deleted]

[deleted]

Re: How to Think About Variables in C

#49
post #42

Earlier quoted context omitted.

If a variable were just a memory address and assignment were just a memory copy, this would be a valid operation. It's a valid operation regardless of whether a standards body says it's not. uint32 x = 5; uint16 y = *(uint16*)&x; The effect is to set y to the first two bytes of memory from x. Values assigned to x are serialized into memory in either big endian or little endian order. Those are the only two cases you…

The reason it's useful to explicitly "break the rules" like this is because it's important to know what assumptions you can in fact rely on, regardless of what standards bodies have to say about it. Given that compilers do break when programmers violate aliasing rules, you should recheck what assumptions you think you can rely on. Non-strict aliasing is not one of them. Unless you want to slow everything down with co…

  uint8_t foo[4]; *(uint32_t*)foo = 0;
Besides even without strict aliasing, the above is not at all guaranteed to work since not all architectures support unaligned loads.

So, the interesting thing about this example is that it does work. It's in fact very, very difficult to find a platform where that example won't work (i.e. crashes the program). For example, any C library involving image manipulation is likely going to have code similar to what you've described, and those libraries work on almost every platform.

Standards are a good and useful thing. All I'm saying is that it's important to know which rules you can safely violate.

Re: How to Think About Variables in C

#50

Earlier quoted context omitted.

> It's a valid operation regardless of whether a standards body says it's not. Whoa there, cowboy. You may not feel personally beholden to standards bodies, but compiler vendors are following their lead. The major compilers are getting more and more aggressive about optimizing away undefined behavior every year. > The effect is to set y to the first two bytes of memory from x. No, it's really not. It's undefined beha…

No, it's really not. It's undefined behavior and the compiler is free to do absolutely whatever it wants. The point is that compilers do some specific thing, regardless of the fact that the standards bodies say they're free to reboot your computer. As long as all you care about is x86/x86_64/PowerPC (and probably ARM as well), then you can trust that the compiler is going to generate code which copies the first two b…

>As long as all you care about is x86/x86_64/PowerPC (and probably ARM as well), then you can trust that the compiler is going to generate code which copies the first two bytes of x into the memory occupied by y.

That's the thing that haberman is trying to tell you, you can't trust that any more, even with architectures you think you know. What you said was true about 10 years ago, but things have changed. Go read about "-fno-strict-aliasing" [1].

[1] http://thiemonagel.de/2010/01/no-strict-aliasing/

Post reply on HN