1. Limited time only! Sign up for a free 30min personal tutor trial with Chegg Tutors
    Dismiss Notice
Dismiss Notice
Join Physics Forums Today!
The friendliest, high quality science and math community on the planet! Everyone who loves science is here!

Structure Problem Continues

  1. Mar 20, 2010 #1
    I'm actually getting pretty frustrated with this now. It makes no sense.

    I have this structure defined in detector.h

    Code (Text):

    //This structure contains all raw sensor data
    struct sensor_data
    {
        //ADC Values For Each Sensor
        int ADC_LOuter;     //Outer Left Sensor
        int ADC_LInner;     //Inner Left Sensor
        int ADC_Centre;     //Centre Sensor
        int ADC_RInner;     //Inner Right Sensor
        int ADC_ROuter;     //Outer Right Sensor
       
        //Whether or not the sensor is on the track
        unsigned int Track_LOuter;      //Outer Left Sensor
        unsigned int Track_LInner;      //Inner Left Sensor
        unsigned int Track_Centre;      //Centre Sensor
        unsigned int Track_RInner;      //Inner Right Sensor
        unsigned int Track_ROuter;      //Outer Right Sensor
    };
    struct sensor_data Sensor;

     
    and the compiler is complaining that it has multiple definitions

    Code (Text):

    MPLINK 4.22, Linker
    Copyright (c) 2008 Microchip Technology Inc.
    Error - symbol 'Sensor' has multiple definitions.
    Errors    : 1
     
    This makes no sense. There is no mention of that structure anywhere else in the code. The individual values are only set to equal things of the same data type.

    What does this error mean?
     
    Last edited: Mar 20, 2010
  2. jcsd
  3. Mar 21, 2010 #2

    Mark44

    Staff: Mentor

    If there is no mention of that struct anywhere else in the code, why is it in your header file?

    The line following the struct definition --
    struct sensor_data Sensor;
    -- is creating an instance of that struct, named Sensor. It doesn't make much sense to me why that line of code is there, since the struct instance is uninitialized (i.e., filled with garbage values.

    I think that if you take a close look at your code, you might find that the name Sensor is defined somewhere else, and that seems to be what the linker is complaining about.
     
  4. Mar 21, 2010 #3
    I went though everything and the only place that the word sensor is used other than in that struct definition is in my comments describing how it works.

    Also, why doesn't it make sense for struct sensor_data Sensor; to be there? From my understanding you have to create an instance of the structure before you can use it.

    What do you mean why is it in the header file? Are you not supposed to define and instantiate structures in headers?
     
  5. Mar 21, 2010 #4

    Mark44

    Staff: Mentor

    I still believe that Sensor is declared somewhere else and you're missing it. The linker (not the compiler) is convinced that you are defining Sensor in two or more places. How about showing us your code?

    If you truly believe that Sensor isn't defined anywhere else, then I ask again, why is it in your header file? If you program isn't using it, then there is no reason for the struct definition and struct instantiation to be there. Note that these are two different things. The struct definition is a template that defines how variables of this type should be laid out in memory. The compiler doesn't allocate any memory for a struct template definition. It does, however, for a struct variable declaration.

    One thing you could do is comment out the whole struct definition and the struct variable declaration (the line struct sensor_data Sensor;).
    That's true, but your are saying that you aren't using it. Also, you are creating an uninitialized struct variable instance in your header file, which means that you have a global struct variable, which is something D H talked about in your other thread on this struct.
    When a struct is used, a header file normally contains only the struct template definition, not a struct variable declaration/definition.
     
  6. Mar 21, 2010 #5
    Well, there is a bunch of code, so I'll sort though it and paste the important bits.

    The thing is that I need that structure to be accessable by a whole bunch of functions. Also, a bunch of these functions are defined in separate files. I guess I could include the templace in the system_config.h file and instantiate it in the main before the infinite loop starts. But for some reason I can't pass stuff by reference, it gives me a syntax error.

    For example void(int& var) is invalid apparently.
     
    Last edited: Mar 21, 2010
  7. Mar 21, 2010 #6

    Mark44

    Staff: Mentor

    Include your main function and one of the functions that uses the struct.

    void fn(int& var) is valid in C++, but not in C.
     
  8. Mar 21, 2010 #7
    Ah...this is a problem. If I pass it the structure will it be pointing to that structure directly, or will it just give it the information and not be able to edit it like in C++?

    If that is the case then I need to figure out how to use pointers.
     
  9. Mar 21, 2010 #8

    Mark44

    Staff: Mentor

    If you pass the struct by reference (using & in C++ or * in C), the function can modify what is referred to. If you pass the struct by value, the function is working with a copy of the original, so cannot modify the original.
     
  10. Mar 21, 2010 #9
    Right, so I need to figure out how to make pointers work.

    If I understand this correctly, I can instantiate the structure, then create a pointer of the same structure type, and then set the address like so:

    struct sensor_data Sensors;
    struct sensor_data *SensorPoint;

    SensorPoint = &Sensors

    Then once I have that I can just pass that pointer around and have it access the original?
     
  11. Mar 21, 2010 #10

    Mark44

    Staff: Mentor

    You should still take the line struct sensor_data Sensor; out of your header.

    In the first line of your code above, you are creating an uninitialized struct variable. It will be filled with garbage values or zero values, depending on where in your code this line appears (i.e., depending on whether the struct variable is local to some function or global).

    You can combine your second and third lines of code like so:

    struct sensor_data *SensorPoint = &Sensors;

    Here SensorPoint is declared and initialized with the address of the Sensors variable.
     
  12. Mar 21, 2010 #11
    Okay, I removed the structure from the detector header. Now the definition is above the main function, and the instantiation takes place in the main function just after the first initialization function is run.

    I isolated the main function from everything else for this test:

    Code (Text):


    struct sensor_data
    {
        //ADC Values For Each Sensor
        int ADC_LOuter;     //Outer Left Sensor
        int ADC_LInner;     //Inner Left Sensor
        int ADC_Centre;     //Centre Sensor
        int ADC_RInner;     //Inner Right Sensor
        int ADC_ROuter;     //Outer Right Sensor
       
        //Whether or not the sensor is on the track
        unsigned int Track_LOuter;      //Outer Left Sensor
        unsigned int Track_LInner;      //Inner Left Sensor
        unsigned int Track_Centre;      //Centre Sensor
        unsigned int Track_RInner;      //Inner Right Sensor
        unsigned int Track_ROuter;      //Outer Right Sensor
    };

    //MAIN function performs initialization and runs the monitor function
    void main(void)
    {
        //initialize(); //Performs initialization
       
        struct sensor_data Sensor;      //Creates structure that holds all sensor data
        struct sensor_data *SensorPoint = &Sensor;
       
        printf("%c%c",0xFE,0x01);
        printf("INITIALIZATION  COMPLETE");
       
        //Two second delay
        Delay10KTCYx(200);
        Delay10KTCYx(200);
        Delay10KTCYx(200);
        Delay10KTCYx(200);
        Delay10KTCYx(200);
        Delay10KTCYx(200);
        Delay10KTCYx(200);
        Delay10KTCYx(200);
       
        printf("%c%c",0xFE,0x01);
        printf("  PATHFINDING  ");
       
        //Repeatedly calls the monitor function
        while(1)
        {
            //Calls the monitor function
            //OM NOM NOM NOM NOM
            //monitor();
        }
    }
     
    So now all I need to do is pass the pointer into other functions, like so:

    fn(SensorPoint)

    and the prototype would be
    fn(sensor_data SensorPoint)

    and to access anything

    SensorPoint.member?
     
  13. Mar 21, 2010 #12

    Mark44

    Staff: Mentor

    Is one of the functions called in main going to initialize your global struct variable?

    Inside one of the functions, you can access the struct in either of two ways:
    SensorPoint -> member_name
    or
    *(SensorPoint).member_name

    SensorPoint.member_name doesn't work because SensorPoint isn't a struct variable; it's a pointer, and pointers don't have struct fields.
     
  14. Mar 21, 2010 #13
    The main function will instantiate the structure. I'm getting a syntax error now though:
    Code (Text):

    void main(void)
    {
        initialize();   //Performs initialization
       
        [B]struct sensor_data Sensor;       [/B]//Creates structure that holds all sensor data
        struct sensor_data *SensorPoint = &Sensor;
     
    The error is on the bolded line. I'm guessed the error is actually in the initialize function somewhere, but it isn't.
     
  15. Mar 21, 2010 #14

    Mark44

    Staff: Mentor

    What's the text of the error? Is it a compiler error or a linker error? Compiler errors usually tell you the line where the error occurs.

    You're calling initialize() before creating the Sensor variable. IOW, you are apparently trying to initialize something before it actually exists.

    The scope of the Sensor variable is within main. Other functions, including initialize(), aren't aware of Sensor.

    If I understand what you're trying to do, you need to do things in this order:
    Create your struct variable.
    Initialize the struct variable.
     
  16. Mar 21, 2010 #15
    I moved the call down and it worked! Hooray for progress! :D

    I'll clean up the other functions and see how it goes.

    I'm passing the pointer like so:

    prototype: fn(sensor_data SensorPoint)
    call: fn(SensorPoint)
     
    Last edited: Mar 21, 2010
  17. Mar 21, 2010 #16
    Update:

    Alrighty, it's working ok, but I'm having an issue passing the pointer.

    In this set of code sensor_data is the name of the structure template, and S is the pointer.

    Function definition

    Code (Text):

    void monitor(struct sensor_data *S)
    {
        forward();  //Move forward
    }

     
    Function prototype
    Code (Text):

    void monitor(struct sensor_data *S);
     
    and I get this:

    Code (Text):

    monitor.c:40:Error [1109] type mismatch in redeclaration of 'monitor'
     
    They're the exact same, so I'm lost as to where this is coming from. This textbook I have says that should work.

    EDIT: I solved it, turns out I had the header included. That's probably what was giving me issues in some of the other sections.
     
    Last edited: Mar 22, 2010
  18. Mar 22, 2010 #17
    Now I'm getting an error when I try to write with that pointer.

    First I got an error with a type mismatch in a redeclaration of the function prototype:
    Code (Text):
    detector.h:14:Error [1109] type mismatch in redeclaration of 'ADC_ALL'
    Code (Text):
    void ADC_ALL(struct sensor_data *SensorPnt);
    and
    Code (Text):

    //Performs An ADC Reading On All RLS Channels
    //Reads left to right
    void ADC_ALL(struct sensor_data *SensorPnt)
    {  
        //Reads Left Outer Sensor
        SetChanADC(RLS_LOuter);
        ConvertADC();
        while(BusyADC());
        *SensorPnt.ADC_LOuter = ReadADC();
           
        //Reads Left Inner Sensor
        SetChanADC(RLS_LInner);
        ConvertADC();
        while(BusyADC());
        //Sensor.ADC_LInner = ReadADC();
           
        //Reads Centre Sensor
        SetChanADC(RLS_Centre);
        ConvertADC();
        while(BusyADC());
        //Sensor.ADC_Centre = ReadADC();
           
        //Reads Right Inner Sensor
        SetChanADC(RLS_LOuter);
        ConvertADC();
        while(BusyADC());
        //Sensor.ADC_RInner = ReadADC();
           
        //Reads Right Outer Sensor
        SetChanADC(RLS_LOuter);
        ConvertADC();
        while(BusyADC());
        //Sensor.ADC_ROuter = ReadADC();
    }
     
    I went though and there is nothing else with that name.
    When I told it to go past that I got this error:

    Code (Text):

    detector.c:62:Error [1207] tag 'sensor_data' is incomplete
    detector.c:62:Error [1207] tag 'sensor_data' is incomplete
    detector.c:62:Error [1131] type mismatch in assignment
     
    What I did was pass the pointer to the monitor() function, then it passes it through to the detector function. Do I need to make another pointer variable in monitor before I can pass it along? Or can I just continue with the current setup:

    Code (Text):

    void monitor(struct sensor_data *SensorPnt)
    {
        ADC_ALL(SensorPnt);

        forward();  //Move forward
    }
     
     
  19. Mar 22, 2010 #18

    Mark44

    Staff: Mentor

    Is ADC_ALL declared in sensor.h? Names in all caps are usually constants, so it's not a good idea to name a function with all caps.

    This line of code isn't doing what you think it is.
    Code (Text):
        *SensorPnt.ADC_LOuter = ReadADC();
     
    It calls ReadADC(), which does something and returns some value. (I have no idea what it does or what it returns.) On the left side of the assignment statement, it attempts to access the ADC_LOuter field of what it thinks is a struct, and then attempts to dereference what should be a pointer, but isn't.

    As I said a few posts ago, there are two ways to dereference a pointer to get at a member of a struct being pointed to, and the way you did it was neither of them.

    You can do this:
    SensorPnt ->ADC_LOuter = ReadADC();
    or you can do this:
    (*SensorPnt).ADC_LOuter = ReadADC();

    You can't do this:
    *SensorPnt.ADC_LOuter = ReadADC();

    In the first two, SensorPnt is dereferenced, which gives you access to the struct variable it's pointing to, and then you get access to the ADC_LOuter field of the struct variable.

    The reason things happened the way they did is operator precedence in C. The struct member operator, . , has higher precedence that the pointer dereference operator, *.

    This expression, *SensorPnt.ADC_LOuter, is exactly the same as if had been written as
    *(SensorPnt.ADC_LOuter)
    When you want a lower precedence operator to operate before a higher precedence operator, you use parentheses. In this case it would be (*SensorPnt).ADC_LOuter

    For your last question, what does forward() do? You aren't passing any arguments to it, so it doesn't know about any local variables in the function that's calling it.
     
  20. Mar 22, 2010 #19
    Oh, I tried using (*SensorPnt) and I got an error, I'll try this again and see what I get.

    ReadADC() is a function in the compiler the takes an ADC reading from the PIC's ADC port (which ever one is defined as active by the set channel function)

    forward() is a function I defined, it just makes the robot go straight forward. I created a library of functions for basic movements: forward, reverse, spin, pivot, etc.

    ADC_All is declared in detector.h
     
    Last edited: Mar 22, 2010
  21. Mar 22, 2010 #20
    Well, I fixed it, and still got the error when I commented out the function header:

    Error with prototype:
    Code (Text):
    Error [1109] type mismatch in redeclaration of 'ADC_All'
     
    Error without prototype and fixed pointer:
    Code (Text):
    detector.c:62:Error [1207] tag 'sensor_data' is incomplete

    detector.c:62:Error [1207] tag 'sensor_data' is incomplete
     
    Prototype
    Code (Text):
    void ADC_All(struct sensor_data *SensorPnt);
    Definition
    Code (Text):

    void ADC_All(struct sensor_data *SensorPnt)
    {  
        //Reads Left Outer Sensor
        SetChanADC(RLS_LOuter);
        ConvertADC();
        while(BusyADC());
        (*SensorPnt).ADC_LOuter = ReadADC();
           
        //Reads Left Inner Sensor
        SetChanADC(RLS_LInner);
        ConvertADC();
        while(BusyADC());
        //Sensor.ADC_LInner = ReadADC();
           
        //Reads Centre Sensor
        SetChanADC(RLS_Centre);
        ConvertADC();
        while(BusyADC());
        //Sensor.ADC_Centre = ReadADC();
           
        //Reads Right Inner Sensor
        SetChanADC(RLS_LOuter);
        ConvertADC();
        while(BusyADC());
        //Sensor.ADC_RInner = ReadADC();
           
        //Reads Right Outer Sensor
        SetChanADC(RLS_LOuter);
        ConvertADC();
        while(BusyADC());
        //Sensor.ADC_ROuter = ReadADC();
    }
     
    But my student version of the compiler expired, and it now omits the following:

    * Not all optimizations will be supported. Namely, procedural
    abstraction will not be supported.

    * The PIC18 Extended mode (extended instruction set and indexed with
    literal offset addressing) will not be supported.

    Is that the reason why? Because when I make the arguments void it goes past that spot fine. :/

    Also apparently monitor can't see the prototype for the detector functions even though I've included it, not can it see the prototypes for the movement functions like forward. :/
     
    Last edited: Mar 22, 2010
Know someone interested in this topic? Share this thread via Reddit, Google+, Twitter, or Facebook




Similar Discussions: Structure Problem Continues
  1. C Structure Problem (Replies: 11)

Loading...