views:

83

answers:

4

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?

+5  A: 
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.

Oli Charlesworth
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
Noah Roberts
@Noah: yes, there are a few other assumptions I neglected. But the concept should be apparent...
Oli Charlesworth
@Noah: Why dereferencing would be UB. It is pointing to a valid address.Can you please explain?
Happy Mittal
@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.
Noah Roberts
@noahso 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
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.
Noah Roberts
Thanks noah.But can you please explain the term "alignment requirement" that you have used?
Happy Mittal
+1  A: 
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
This won't trash *other* data, though.
Oli Charlesworth
Jerry Coffin
@Jerry: ah yes, I suppose this is true. Depends whether you think of the array as "atomic" or not!
Oli Charlesworth
@Oli: What do you mean?
GMan
@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.
Oli Charlesworth
A: 
char unix[5]="unix";
char* first= &(unix[0]);
int * intptr= (int*) first;
*first=64;
printf("%s\n",unix); /* prints @ /*
Ken Bloom
A: 

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