Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Question on pointers (ROOT TTree example)

  1. Jul 29, 2015 #1

    ChrisVer

    User Avatar
    Gold Member

    Code (C):

    TTree* inputTree = (TTree*)source->Get( "<YourTreeName>" );
     
    Could someone please explain me what the above statements mean? I don't understand what " (TTree*) " does (source is a TFile). Thanks.
     
  2. jcsd
  3. Jul 29, 2015 #2

    ShayanJ

    User Avatar
    Gold Member

    It seems to me that TTree is a class name. The part "TTree* inputTree" creates a pointer to a TTree object. Then this pointer is assigned to point to a TTree object whose pointer is given by "Get" method of the object "source" which means source is an object from a class that has a TTree member variable(probably as a pointer).
    For more information, its better to take a look at the definition of the classes.
     
  4. Jul 29, 2015 #3
    The TTree structure is a block of memory that contains all of the information for the TTree. a TTree * tells you the memory location of the struct.

    Is this C or C++? I'm assuming C based on the tag and the C cast.
     
  5. Jul 29, 2015 #4

    ChrisVer

    User Avatar
    Gold Member

    I don't think that the definition of these classes could help.
    I had problem understanding the meaning of (TTree*) and not what TTree is used for/how and what methods it has.
     
  6. Jul 29, 2015 #5

    ChrisVer

    User Avatar
    Gold Member

    and it's C++ I guess (since ROOT is using C++). But I think it's a general concept that may appear when you deal with pointers to write something like:

    int * p = (int*)a->(method in int)
     
    Last edited: Jul 29, 2015
  7. Jul 29, 2015 #6
    Okay, forget the TTree and go to int, ints are easy.

    You know that your int is stored in memory right? Memory is laid out in a massive block (actually two of them, stack and heap) and everything gets stored there. Okay, so you make an int.

    Code (Text):
    int one = 1;  //int on the stack, value of 1
    Now you have an int, and any time you use it, you will get the value 1. How does the computer know that? Because it's stored a 32 representation of that bit in memory somewhere, your compiled program knows exactly where that memory is, it couldn't care less what you call your variable. To you, your variable is called "one" to the computer, your variable is called "top of stack + offset" where those are memory locations. If you want to know that memory address yourself, you take it's pointer. That will create a separate variable, whose value will be the value of "top of stack + offset"

    Code (Text):
    int * oneptr = &one;//pointer on the stack, value of the location of "one"



    I recommend looking elsewhere for examples, where ever you got your code from is fairly poor. You have a cast form one type of pointer to another after the method call, good code will just return the correct type. You also have a C cast in C++ code. Probably an easier way to learn about pointers is to learn how strings work in C.
     
  8. Jul 29, 2015 #7
    C and C++ are strongly typed languages.
    What that means is each and every variable must have a type (int, float, char etc), and conversion between types has to follow strict rules.

    What you have in your code is you are creating a variable in the local scope that is a pointer to TTree named input tree
    Code (Text):
    TTree* inputTree   //create a variable named inputTree of type TTree pointer
    You are assigning to this variable the returned value from the call to source->Get.
    It is likely that source->get returns a TTree* already. However it is always good coding practice to explicitally cast returned pointers to what type it is.
    That is done with the (TTree*).

    Hope that make sense!
     
  9. Jul 29, 2015 #8
    This is extremely incorrect. It is good coding practice to do exactly the opposite and use the -Wall option in the compiler to make sure it's what you expect, these languages are very strongly typed on purpose. Other languages let you go back and forth between types willy-nilly because the concept of a variable is abstract, in C/C++ they are coupled directly to the structure of memory.

    Even if you do perform casting from time to time, in c++ you should never use that style cast, here is why:

    Code (C):
    int i = 10;  //32 bits
    long j = 100L;  //64 bits
    long * jp = (int *)jp;  //C cast, no checking, telling the compiler that you know better
    *jp = 100L;  //Write 64 bit constant to 32 bit memory chunk.  Holy, memory corruption!
    Properly written code
    Code (C):
    int i = 10;
    long j = 100L;
    long * jp = static_cast<int *>(jp);  //Proper style of cast, will not compile
    *jp = 100L;
     
    Last edited: Jul 29, 2015
  10. Jul 29, 2015 #9
    First off you'll notice I said RETURNED pointers.
    It has everything to do with readability of the code.

    Imagine this situation:
    you've done nothing to affect the operation of the code. You've cast an int* to an int*.
    But 6 months later when you're reviewing the code for whatever reason you won't need to search through the code to figure out what myPointer is supposed to be.
     
  11. Jul 29, 2015 #10
    Documentation should provide you with hints as to what things are supposed to be, your IDE will also usually both be able to tell you and return you back to the definition of your variable. Returned pointers are no different than any other ones, and the cast itself IS a function, so you do have a returned value. Programmers will not sacrifice code safety for readability.

    Here is a difference maintenance nightmare for you. Your code now requires a 64 bit long to replace that 32 bit int. Change the function, but forget to change a single cast, and suddenly you have a very difficult to track down bug. If you had not done any casts, your compiler will tell you what you did wrong, if you used a proper C++ cast, it'll do the same, using a C cast will not hinder compilation, just produce weird behavior. When you start getting into inheritance you start getting ever worse issues.

    There is no reason to EVER use a C cast in C++ code.

    Code (Text):
    //Assume Child inherits publically from Parent and getObjectByName is implemented elsewhere

    Parent * getObjectByName(const char * name);

    Child * mychild = getObjectByName("child");  //Will not compile because the return type and assigned type are not the same INVALID!

    Child * mychild = (Child*)getObjectByName("child");  //mychild is valid ONLY if it were created with the Child() constructor  UNSAFE!

    Child * mychild = reinterpret_cast<Child *>(getObjectByName("child"));  //mychild is valid ONLY if it were created with the Child() constructor  UNSAFE!

    Child * mychild = static_cast<Child*>(getObjectByName("child"));  //Will not compile because of reason above INVALID!

    try {
         Child * mychild = dynamic_cast<Child *>(getObjectByName("child"));  //mychild is valid if it were created with the Child() constructor OR you've defined a conversion SAFE!
    } catch (const std::bad_cast& e) { }
     
  12. Jul 29, 2015 #11

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    I'm with @newjerseyrunner on this. This is very widely regarded as a poor programming practice. Many C++ projects make it a rule to compile with -Wold-style-cast compilation flag so that (TTree*)source->Get("<YourTreeName>") gets flagged with a warning (or with an error if you've enabled -Werror).

    This forces one to use new style casts (e.g., reinterpret_cast<TTree*>(source->Get("<YourTreeName>")) instead of C-style casts. Those new style casts do not enhance readability. They are instead a big red flag that the programmer may be doing something underhanded. Which is a good thing. Those new-style casts are easy to find using something like grep.
     
  13. Jul 30, 2015 #12

    ChrisVer

    User Avatar
    Gold Member

    Is it a big problem that I find it difficult to follow the conversation from Post8 and on?
     
  14. Jul 30, 2015 #13
    Memory is divided up by 1 byte chunks. Each 1 byte chunk of memory has an address, which is just a number that refers to it. A pointer in C or C++ is just a variable for holding a memory address of one of these 1 byte chunks of memory. Types are associated with the pointer in C or C++, because variables may be represented with more than one byte and may need to be stored or parsed differently. An int is typically 4 bytes for example. If you have a pointer to an int, then the compiler knows that the value in memory is represented with the 4 consecutive bytes of memory, starting with the byte referred to by the pointer, and that it is an integer.

    There is also the void pointer, which is just the address, without the type information. This is used, usually in C, to allow functions to be general enough to allow different types of variables to be passed or returned from the same function. For example, to pass a variable to a function as a void pointer and then use it, you first cast it to a void *, (void*), which would be necessary as this would be the type of the parameter of the function, then in the function, you would cast back to a pointer to the actual type, e.g. (Root *), before using it.

    In C++, this technique is usually not used, because features exist to accomplish the same things, such as templates, and functors. But in C++ there is also polymorphism, which is one source of a need to typecast pointers from one type to another, and may be what's going on in the code you posted. If you are unfamiliar with Polymorphism in C++, then I suggest reading something on it.

    Code (C):
    TTree* inputTree = (TTree*)source->Get( "<YourTreeName>" );
    source is a pointer to an Object which has a function Get, that takes a string as input and returns a pointer to something. In this code snippet, whatever type of pointer it returns, is type casted to a pointer to the type Tree, before it is assigned to TTree, which is redundant because it's just a number that is assigned, and TTree* is the type of the variable, which cannot be changed, but requiring it makes it more clear what may be going on, and helps the compiler to warn you, or optionally generate errors for things that may be unsafe.
     
    Last edited: Jul 30, 2015
  15. Jul 31, 2015 #14
    I apologize, that may be my fault. There was a minor issue with what you posted I wanted to clarify about typecasting, but as for your question @tAllan's explanation of pointers is very good. A pointer just points to a block of memory. In your case that block of memory represented a TTree.
     
  16. Aug 1, 2015 #15

    jim mcnamara

    User Avatar

    Staff: Mentor

    @ChrisVer --
    What they are talking about above is undefined behavior, the nasty child of
    C and C++ runtime possibilities, along with it's ugly cousin, unspecified behavior.

    Undefined behavior for a program is just that: abort, corrupt data, do something
    you could never expect: reformat your hard drive or send a picture of your
    family to the Mars Lander. You may think that's funny. I worked for DOE in
    Germantown MD long ago. We were debugging garbage code that had problems. We hit
    a problem, and Voila! there we were sitting at the console prompt of another
    machine. That was no joke. We panicked, shut everything down and reported it to
    security. We thought we were safe on the local machine. Nope.

    You may think the Mars Lander thing above is hyperbole, and it probably is, but it
    makes the point.

    Undefined behavior is the concept behind hacker code exploits to take over a
    machine. What happened in the "long ago" example was to unintentionally
    overwrite the return address on the stack, and then when the function ended,
    return to some other wildly different place in computer memory. Instead of
    staying in the current process memory. Undefined behavior.

    So, if you are coding C or C++ you should be aware of this, especially if you
    are downloading code from everywhere.

    C++ has many more creative ways to demonstrate undefined behavior than does C.

    Getting your head around the C++ issue set is a huge task, so for C here is
    CERT on C secure programming:
    https://www.securecoding.cert.org/confluence/display/c/SEI+CERT+C+Coding+Standard

    Floating point examples:
    (for purists who know about IEEE-754 2008 this page assumes you have commodity computers and are coding C)
    https://www.securecoding.cert.org/confluence/pages/viewpage.action?pageId=158237216

    https://www.securecoding.cert.org/c...nt+numbers+when+precise+computation+is+needed

    Why? You seem to work in Physics extensively. You can see examples of fp operations that give
    incorrect results and how to fix them. Check out the last link for an example.
     
  17. Aug 1, 2015 #16

    jim mcnamara

    User Avatar

    Staff: Mentor

  18. Aug 4, 2015 #17

    strangerep

    User Avatar
    Science Advisor

    Sorry Chris -- I don't often look in this forum. (Maybe I should check more often to see if there's C++ questions here.)

    Your original code is obviously C++ (since it involves member function). C++ is strongly typed, C is not (though this can depend on one's precise definition of "strongly"). The expression (TTree*) is a cast operator, forcibly converting whatever the "Get(...)" mbr fn returns into a TTree*.

    BTW, someone said that "always casting" in this way is good practice. Sorry, but that's rubbish. In C++, if you need to cast, then something is deficient about the overall class structure.
    In this context, you said earlier:
    ...it could indeed help to know the type (class) of which "source" is an instance, hence what type is returned by "source->Get(...)" .

    If your question is still not answered then try re-phrasing it. Have you got Bjarne Stroupstrup's definitive tome(s)?
     
    Last edited: Aug 4, 2015
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Question on pointers (ROOT TTree example)
  1. Pointer question (Replies: 2)

  2. A pointer value question (Replies: 13)

Loading...