0

I have read in a book that specifies this :

//: C03:SimpleCast.cpp
int main() {
int b = 200;
unsigned long a = (unsigned long int)b;
} ///:~

"Casting is powerful, but it can cause headaches because in some situations it forces the compiler to treat data as if it were (for instance) larger than it really is, so it will occupy more space in memory; this can trample over other data. This usually occurs when casting pointers, not when making simple casts like the one shown above."

Now can You please provide an example where casting pointer can trample other data?

Happy Mittal
  • 3,667
  • 12
  • 44
  • 60

4 Answers4

5
int main(void)
{
    short int a = 5;
    short int b = 7;
    *(long int*)&a = 0;
}

Assuming sizeof(long) > sizeof(short), and assuming the compiler puts a on the stack before b, b will be trashed.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • 2
    and if the compiler puts b on the stack before a, something else will be trashed, like your return address or your caller's saved frame pointer. – Ken Bloom Jun 02 '10 at 19:00
  • 2
    b isn't guaranteed to be trashed. What you've done is a reinterpret_cast (as I always say, this is why you really need to use C++ casts, so you know what you're doing). Dereferencing it causes UB. Furthermore, there's no guarantee that &b == &a + sizeof(a) even if b comes after a. – Edward Strange Jun 02 '10 at 19:43
  • @Noah: yes, there are a few other assumptions I neglected. But the concept should be apparent... – Oliver Charlesworth Jun 02 '10 at 19:46
  • @Noah: Why dereferencing would be UB. It is pointing to a valid address.Can you please explain? – Happy Mittal Jun 03 '10 at 09:23
  • @happy - forgive me, it's "unspecified". 5.2.10/7: "A pointer to an object can be explicitly converted to a pointer to an object of different types. ...the result of such a pointer conversion is unspecified." Dereferencing it thus may or may not cause UB depending on whether the implementation generates a valid pointer out of the operation. – Edward Strange Jun 03 '10 at 15:50
  • @noah so does it mean whenever a pointer to one type is converted to another, the result is unspecified? Then what about reinterpret_cast where we do this pointer conversion? – Happy Mittal Jun 03 '10 at 22:07
  • The result of casting one unrelated pointer type to another is indeed unspecified. This is what a reinterpret cast is so that's exactly what I'm already talking about. If you explicitly do a reinterpret_cast on related types then it also is unspecified. The only thing that is guaranteed by the standard is that reinterpret casting from T1* to T2* and back to T1* will result in the original T1* iff alignment requirements for the two types are the same. – Edward Strange Jun 03 '10 at 22:20
  • Thanks noah. But can you please explain the term "alignment requirement" that you have used? – Happy Mittal Jun 03 '10 at 22:24
1
int main() { 
    char a[] = "This is a string.";

    *(long *)a = 12345678;  // will typically overwrite first four or eight bytes of a.

    std::cout << a;
    return 0;
}
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • This won't trash *other* data, though. – Oliver Charlesworth Jun 02 '10 at 19:05
  • @Oli:yes and no. It uses the address of the beginning of the array, and overwrites bytes other than the first. Perhaps it would be more obvious if I used `&a[0]` instead of just `a`, but the two mean the same thing. – Jerry Coffin Jun 02 '10 at 19:16
  • ah yes, I suppose this is true. Depends whether you think of the array as "atomic" or not! – Oliver Charlesworth Jun 02 '10 at 19:38
  • @GMan: I mean that I see the above code as modifying what is expected; i.e. the array `a`. Jerry's intepretation is that only modification of `a[0]` is "expected", and that `a[1]` etc. are now unexpectedly trashed. – Oliver Charlesworth Jun 02 '10 at 20:19
0
char unix[5]="unix";
char* first= &(unix[0]);
int * intptr= (int*) first;
*first=64;
printf("%s\n",unix); /* prints @ /*
Ken Bloom
  • 57,498
  • 14
  • 111
  • 168
0

Since this was tagged as C++, not C, I also recommend reading up on C++ style casts over C style casts:

static_cast<Derived *>(pBase)->DMethod();
if (dynamic_cast<Derived *>(pBase)) dynamic_cast<Derived *>(pBase)->DMethod();
const_cast<CRect &>(constRect).x = 3;
int *pInt = reinterpret_cast<int *>(charbuff);

I highly recommend Scott Myer's book Effective C++, 55 Specific Ways to Improve Your Programs and Designs, 3rd Edition that explains these very well. Make sure you get the 3rd Edition, although the 2nd Edition may also have covered C++ style casts too.

Basically, if you are using C++ and your compiler was written within the last 10 years, NEVER use C-style casts. Use C++ style casts.

franji1
  • 3,088
  • 2
  • 23
  • 43