CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Dec 2012
    Posts
    18

    Casting Pointers in C style?

    This is something I'm having allot of trouble with. Casting Pointers in C Programming. I don't want to move onto implicit casts until I have this down pat.

    I'm failing to understand how casting pointers works.
    I know the below program is pointless but I am just trying to understand it.

    The line
    Code:
    int *mnt = (int*)&flt;
    if I read this correctly passes the address of flt which has been converted to an int to the pointer mnt.

    1 - When I output mnt I get a garbage value, probably because the address of flt is then converted to a pointer and passed onto mnt as a value and then reinterpreted as a memory address. (that is the first part I don't understand)

    2 - - What exactly does the (int*) cast say? Does this mean that a pointer will be returned or an address will be returned. What does the fact that the * is inside the parenthesis mean?



    Code:
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
    
      float flt=  6.5;
    
      int *mnt = (int*)&flt;
      
      cout << mnt << endl; // outputs hex memory address
      cout << *mnt << endl; // outputs garbage value
      
    
    }
    Last edited by tomadom; September 5th, 2014 at 10:44 PM.

  2. #2
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Casting Pointers in C style?

    The reason *mnt outputs garbage is that flt is typed as a float but you have casted it to an int. Using casts for pointers doesn't change the data to which the pointer points - it just says to the compiler that the data stored in memory at the address pointed to by the pointer should be treated as type xxx instead of type yyy.

    Consider this program
    Code:
    #include <iostream>
    using namespace std;
    
    int main()
    {
    int flt = 10;
    int *mnt = &flt;
      
      cout << mnt << endl; // outputs hex memory address
      cout << *mnt << endl; // outputs 10
    
      return 0;
    }
    flt is of type int. This says that somewhere in memory the compiler has allocated space to store an integer (for a 32 bit system usually 4 bytes - but sizeof(..) will return the actual number of bytes used) and that the integer value stored at this memory location is to be referred to in the program as flt. So in
    Code:
    flt = flt + 2;
    this means that the contents of the memory referred to as flt should be treated as an integer and that this value should have 2 added to it and the result written back to the memory referred to as flt as type integer.

    Code:
    &flt
    this means obtain the memory address of the variable flt - ie obtain the address of the start of the memory to which flt refers. The type of the returned value is int* as flt is of type int. This means the type is a pointer to memory that contains an integer.

    Code:
    int *mnt;
    this means the mnt is a pointer to memory (ie can be assigned a memory address) and that the memory to which mnt points will contain data that should be treated as of type int. Note that pointers contain (usually! - or NULL) a memory address and that the type of the pointer indicates what type of data is held at the address in memory to which the pointer points.

    So
    Code:
    int *mnt = &flt;
    means that mnt is a pointer to memory that contains an integer. mnt is initialised to the address of the memory referred to by flt. In this case no cast is needed as flt is of type int and so the type of &flt is of type int*.

    Now consider
    Code:
    signed int flt = 10;
    unsigned int *mnt = &flt;
    This will generate a compiler error complaining that it cannot convert a signed int * to an unsigned int *. In the case of ints, signed and unsigned ints are stored using the same bit pattern in memory but are interpreted differently if typed as signed or unsigned. So in the example above we need to cast the value of &flt from signed int * (because flt is of type signed int so the type of &flt is of type signed int *) to unsigned int *. So to cast (tell the compiler to treat a value of one type as if it were of a different type) we use the c-style cast of (unsigned int *) so we have
    Code:
    signed int flt = 10;
    unsigned int *mnt = (unsigned int*)&flt;
    mnt is of type pointer to an unsigned int, &flt is of type pointer to signed int and the c-style cast (unsigned int*) says treat the type of &flt as if it were of type pointer to unsigned int.

    note that
    [code]
    flt = flt + 2;
    [code]
    can be written as (but don't!)
    Code:
    *(&flt) = *(&flt) + 2;
    where in this case * means dereference - ie obtain the value of - the contents of memory. So &flt means obtain the address of the memory to which flt refers and *(&flt) means use the contents of the memory referenced by flt.

    In summary, a pointer variable contains a memory address and the contents of that memory should be treated as the type specified in the pointer variable definition. So
    [code]
    int *pi; // is a pointer to memory that contains an integer
    float * flt; // is a pointer to memory that contains a float
    FILE *fl; // is a pointer to memory that contains data that should be interpreted as being of type FILE.

    I hope this ramble helps. If you have any more queries, please ask.

    PS If you are using c++ then it would be better to use c++ style casts rather than c-style casts. See http://www.cplusplus.com/doc/tutorial/typecasting/ for more info.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  3. #3
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Casting Pointers in C style?

    a cast is an order/command to the compiler to ignore it's strict type system, and that your order is to be considered exactly as stated, and safe under your own personal warranty.

    if it turns out not to be safe ... "anything could happen".


    So... I'm handing you a bottle of clear liquid. The bottle has lots of warning stickers sayign "poison", "corrosive" and all such nasties.
    Yet... I'm commanding you that the bottle contains fresh water and you can safely ignore anything printed on the bottle.

    and I'm telling you to drink the bottle empty.

    that's pretty much what a cast is

  4. #4
    Join Date
    Dec 2012
    Posts
    18

    Cool Re: Casting Pointers in C style?

    Both, thanks for the explanations. 2kaud, great explanation on pointers, this will be useful.

    My main aim has been to gain a deeper understanding of the syntax surrounding casts with pointers in C programming.

    The main point of confusion has been this. See below.
    Code:
    char mychar = 'p';
    
    int *myint = new int;
    
    myint = (int*)&mychar;   // it is this line I am referring to below.

    I just don't understand why casting to an int pointer will return an address. If I place (int*) in front of the address of mychar (&mychar) then I would assume that the int returned uses the address of mychar and the * would indicate that the return value should be the thing pointed at, not the address. So the line
    Code:
    myint = (int*)&mychar;
    I would logically think should return a value and not an address for myint to absorb. I would assume (int*)&mychar returns an address because (int*) is uses parenthesis and the concept of precedence of operations comes into play somewhere here. But intuitively, I don't understand how in this case.

  5. #5
    Join Date
    Jan 2006
    Location
    Singapore
    Posts
    6,765

    Re: Casting Pointers in C style?

    Quote Originally Posted by tomadom
    I just don't understand why casting to an int pointer will return an address.
    (...)
    I would logically think should return a value and not an address for myint to absorb.
    A pointer's value is an address. Therefore, casting to an int pointer results in an address (with the specified pointer type). In this, the syntax doesn't matter; the semantics is that you get a pointer.

    Quote Originally Posted by tomadom
    If I place (int*) in front of the address of mychar (&mychar) then I would assume that the int returned uses the address of mychar and the * would indicate that the return value should be the thing pointed at, not the address.
    (...)
    I would assume (int*)&mychar returns an address because (int*) is uses parenthesis and the concept of precedence of operations comes into play somewhere here.
    The purpose of a type cast is to coerce the type of an object to the specified type. Therefore, that is what the syntax means. You are misinterpreting the syntax as if the constituent characters were to be interpreted separately, but that is not so. The int in (int*) cannot be separated from the * or even from the parentheses because together, (int*) forms a fundamental part of the syntax of the cast expression, i.e., to cast the expression on the right hand side to obtain a pointer to int.

    Put it another way, imagine that we had a function to do this instead. We might write:
    Code:
    cast(int*, &mychar)
    and get as the result a pointer of type int*, whose value is converted from &mychar.

    Of course, it turns out that we cannot pass the type int* as an argument to a function, so this is invalid, but if it were possible, this would be akin to what you are doing when you write (int*)&mychar.

    EDIT:
    Oh wait, you wrote "C Programming", but your example is C++. In that case, my hypothetical cast function can be replaced by an actual C++ cast that is valid syntax:
    Code:
    reinterpret_cast<int*>(&mychar)
    So, int* here is a type name; you probably won't confuse the * here as being the dereference operator. The parentheses look more like that of a function call (though reinterpret_cast is an operator), so you probably won't confuse it with the parentheses used for grouping of subexpressions (related to precedence).
    Last edited by laserlight; September 8th, 2014 at 11:56 PM.
    C + C++ Compiler: MinGW port of GCC
    Build + Version Control System: SCons + Bazaar

    Look up a C/C++ Reference and learn How To Ask Questions The Smart Way
    Kindly rate my posts if you found them useful

  6. #6
    Join Date
    Jul 2013
    Posts
    576

    Re: Casting Pointers in C style?

    Quote Originally Posted by tomadom View Post
    I would assume (int*)&mychar returns an address because (int*) is uses parenthesis and the concept of precedence of operations comes into play somewhere here. But intuitively, I don't understand how in this case.
    It's quite simple, types must match.

    Say you have these variables,

    char myChar; // a char
    char* myCharPtr; // a pointer to char
    int* myIntPtr; // a pointer to int

    Now, &myChar represents a pointer to char just like myCharPtr so you can do this,

    myCharPtr = &myChar; // both sides are char* so types match

    But you cannot do this because C doesn't like it,

    myIntPtr = &myChar; // left side is int* but right side is char* so types don't match

    If you still want to do it you need to cast,

    myIntPtr = (int*) &myChar; // right side is now also an int* so types again match

    So a cast does not convert the content of variables, it just equalizes the types of the variables participating in an expression. It merely plays a formal role in a blame game. If C detects a type mismatch it doesn't approve of it enforces a cast to make it perfectly clear who is to blame if something goes wrong, namely you.

    The best strategy is to let C uphold type safety and not meddle in with casting. I suggest you concentrate on becoming good at avoiding them. Casting is best viewed as an emergency exit.
    Last edited by razzle; September 9th, 2014 at 03:56 AM.

  7. #7
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Casting Pointers in C style?

    If the syntax of casting is causing confusion, c-style casting can also be expressed using a slightly different format. Consider
    Code:
    typedef int* pint;
    
    int main()
    {
    char a;
    pint d;
    
    	d = (pint)&a;
    	d = pint(&a);
    }
    d is of type int* - ie a pointer to memory whose bit pattern should be treated as representing an integer. a is of type char so &a returns the memory address of where the contents of a resides. It is of type char* - pointer to memory whose bit pattern should be treated as representing a char. So to assign the value of &a to d a cast is required. if you are using c++ then it is recommended that the c++ style casts are used. For a c-style cast you can have
    Code:
    	d = (pint)&a;
    or alternatively you could have
    Code:
    	d = pint(&a);
    which looks more like the syntax of a function call (but isn't) and which you might find easier to understand. What this means is create a temporary variable (which doesn't have a name) of type pint and assign to this temporary variable the value of &a and return a value of type pint with the value &a.
    Last edited by 2kaud; September 9th, 2014 at 03:25 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  8. #8
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Casting Pointers in C style?

    Quote Originally Posted by 2kaud View Post
    if you are using c++ then it is recommended that the c++ style casts are used.
    I do not agree (*), at least, as far as the "recommendation" is concerned. Note that a functional style cast can be easily confused with a constructor call whereas it's just a C cast in disguise, just harder to see and search for; For example,

    Code:
    int* y;
    int x(y); // won't compile, invalid conversion
    int x = int(y); // as above
    int x; x = int(y); // may compile or not depending on sizeof(int) !!!
    IMO in c++, you either don't use casts, or prefer c++ casts (static,reinterpret,...) or, if for some reason you really need C-casts then use traditional C casts so that people will know what you're doing at first sight.

    Personally, before c++11 I used the functional style only in arithemtic expressions for stylistic reasons, but now I see no reason to use them thanks to uniform initialization ( with the bonus of narrowing protection ), ie. int{x}.

    EDIT: (*) wait, if you meant to say that static_cast<>,etc... should be preferred than I do agree, of course; I thought you were referring to functional style casts that, AFAIR, are c++ specific too...
    Last edited by superbonzo; September 9th, 2014 at 04:08 AM.

  9. #9
    2kaud's Avatar
    2kaud is offline Super Moderator Power Poster
    Join Date
    Dec 2012
    Location
    England
    Posts
    7,824

    Re: Casting Pointers in C style?

    IMO in c++, you either don't use casts, or prefer c++ casts (static,reinterpret,...)
    That's what I said - use c++ style casts (rather than c style casts).

    EDIT:
    (*) wait, if you meant to say that static_cast<>,etc... should be preferred than I do agree, of course;
    That's what I meant. I should have emphasised the c++ static_cast bit etc.
    Last edited by 2kaud; September 9th, 2014 at 04:20 AM.
    All advice is offered in good faith only. All my code is tested (unless stated explicitly otherwise) with the latest version of Microsoft Visual Studio (using the supported features of the latest standard) and is offered as examples only - not as production quality. I cannot offer advice regarding any other c/c++ compiler/IDE or incompatibilities with VS. You are ultimately responsible for the effects of your programs and the integrity of the machines they run on. Anything I post, code snippets, advice, etc is licensed as Public Domain https://creativecommons.org/publicdomain/zero/1.0/ and can be used without reference or acknowledgement. Also note that I only provide advice and guidance via the forums - and not via private messages!

    C++23 Compiler: Microsoft VS2022 (17.6.5)

  10. #10
    Join Date
    Apr 2000
    Location
    Belgium (Europe)
    Posts
    4,626

    Re: Casting Pointers in C style?

    Quote Originally Posted by tomadom View Post
    Code:
    char mychar = 'p';
    
    int *myint = new int;
    
    myint = (int*)&mychar;   // it is this line I am referring to below.

    I just don't understand why casting to an int pointer will return an address.

    I think this is where you're loosing track.

    with the above bit of code.

    you are defining a variable of type char, named mychar, and initializing it with the value 'p'.
    at this point mychar is the means by which you tell the copiler you want to access the content of the variable ('p').

    note that in the 3rd line, there's a & there.
    The & is the 'address of' operator, and it takes the address of whatever follows.
    so rather than taking the variable mychar's contents, you tell the compiler you want the address of the variable, or the location in memory where the value 'p' is stored.

    The compiler knows however what the Original type is (char) and so it applies the address of to that specific type to create an address to a variable of type char. or... short a pointer to char or char*


    if on the third line you want to do
    myint = &mychar;
    the compiler complains "but a pointer to a char and a pointer to an int aren't the same, so I can't just assign the address of that char variable to a pointer to something else".

    the cast 'overrides' the compiler warning and you command the compiler to just do what you tell it to do and shut up about it because YOU, the programmer know perfectly what you are doing and you know the above will not cause any problems when actually run.

    if you are wrong and the compiler was right. "anything could happen".

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured