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!

Homework Help: C Structure Problem

  1. Mar 19, 2010 #1
    I have a function for my robot that reads multiple IR sensors, and I get a syntax error on the bolded lines.

    Code (Text):

    //Performs An ADC Reading On All RLS Channels
    //Reads left to right
    void ADC_All(void)
    {  
        //Reads Left Outer Sensor
        SetChanADC(RLS_LOuter);
        ConvertADC();
        while(BusyADC());
        [B]SensorsADC.RLS_LOuter = ReadADC();[/B]
           
        //Reads Left Inner Sensor
        SetChanADC(RLS_LInner);
        ConvertADC();
        while(BusyADC());
        [B]SensorsADC.RLS_LInner = ReadADC();[/B]
           
        //Reads Centre Sensor
        SetChanADC(RLS_Centre);
        ConvertADC();
        while(BusyADC());
       [B] SensorsADC.Centre = ReadADC();[/B]
           
        //Reads Right Inner Sensor
        SetChanADC(RLS_LOuter);
        ConvertADC();
        while(BusyADC());
        [B]SensorsADC.RLS_RInner = ReadADC();[/B]
           
        //Reads Right Outer Sensor
        SetChanADC(RLS_LOuter);
        ConvertADC();
        while(BusyADC());
        [B]SensorsADC.RLS_ROuter = ReadADC()[/B];
    }
     
    Pretty simple. It access a structure located in the header file for that source file. It's declared as external so that functions in other files can find it.

    Code (Text):

    //This structure contains the ADC values for each sensor           
    extern struct Sensors_ADC
    {
        int RLS_LOuter;     //Outer Left Sensor
        int RLS_LInner;     //Inner Left Sensor
        int RLS_Centre;     //Centre Sensor
        int RLS_RInner;     //Inner Right Sensor
        int RLS_ROuter;     //Outer Right Sensor
    };

    //Tag for the above structure
    extern struct Sensors_ADC SensorsADC;
     
    I get a syntax error when I try to access the structure on the lines that have been bolded in the function declaration.

    From what I can tell I haven't misdeclared anything, and the data type for the ReadADC() function matches according to the data sheet. I thought it might be cause I made a declare statement that used the same terms for each channel as the members of the structure, but I changed one of them and the error remained.

    So what's going on here?
     
    Last edited: Mar 19, 2010
  2. jcsd
  3. Mar 19, 2010 #2

    ideasrule

    User Avatar
    Homework Helper

    Why is the structure declared as Sensors_ADC even though you were referring to SensorsADC in the code? Also, you have to actually declare the structure as an object, like this:

    Sensors_ADC sensor_data;
    sensor_data.RLS_LOuter = whatever
     
  4. Mar 19, 2010 #3
    I thought that's what the tag did. I defined it as Sensors_ADC and declared it as an object called SensorsADC.

    Unless my terminology is totally wrong. Pretty much everything I know about programming is self taught.

    EDIT: Turns out that I did have some left over declares sitting around with the same names as the structure members...well that's embarrassing.

    So moving onto an actual question now. With the way I've declared the structure, will functions defined in other files be able to read the structures?
     
    Last edited: Mar 19, 2010
  5. Mar 19, 2010 #4

    ideasrule

    User Avatar
    Homework Helper

    I just looked at the code again, and it looks like I overlooked a couple of things before.

    First, you cannot use extern to declare a structure. extern is only for functions and variables. Second, you declared SensorsADC but never defined it. In your main program, you have to do:

    struct Sensors_ADC SensorsADC;

    to actually define the object. Of course, this makes the "extern struct Sensors_ADC SensorsADC;" meaningless unless you want SensorsADC to be visible from other files as well.

    I'd recommend a simple approach: remove all the extern's, remove the declaration "extern struct Sensors_ADC SensorsADC;", and just #include the header file where the structure is declared, then define SensorsADC directly.
     
  6. Mar 19, 2010 #5

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    What is the RLS_LOuter you are passing to SetChanADC() in the above code snippet? I suspect that have you #defined it to some integer value. If so, the compiler is going to be very confused by the assignment to SensorsADC.RLS_LOuter.


    The compiler might be happy with this setup, but the linker will not, and neither will the programmer. What this will do is make multiple copies of entities with the same name (SensorsADC). The linker might, and hopefully will, complain and die. Some linkers complain and take the first (or maybe last) one they come across (not good), others don't even complain.

    The consequence of declaring a variable extern (e.g., extern struct Sensors_ADC SensorsADC;) is to tell the compiler that the variable lives somewhere else. The compiler will mark uses of that external entity as a undefined references to be resolved by the linker. The reason for declaring a variable extern is to serve as a behind-the-scenes form of communication.

    Lancelot59: Those global variables will bite you, big time. Use of them is a strongly discouraged practice in many, many places. I suggest a different approach than the one you are taking:
    1. Make your SensorsADC a local variable in the function that contains your main loop.
    2. Pass a pointer to that variable to the functions that need to use it, and only to those functions.

    BTW, use of precompiler symbols will bite you too. I think that is what bit you here.
     
  7. Mar 19, 2010 #6

    ideasrule

    User Avatar
    Homework Helper

    Why would that happen? #include only inserts the struct declaration into the file. After that, a struct definition like "struct Sensors_ADC SensorsADC;" would create only 1 instance of SensorsADC.
     
  8. Mar 19, 2010 #7

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    Depends on whether the declaration was at file scope or function scope.

    This is a sensor structure for a set of sensors. There should be one instance per set of sensors in the program, and only one instance per set of sensors throughout the program. You don't want everything that needs sensor data going to the sensor to get the data.

    In fact, most things that need sensor data don't really need the raw sensor data. They need data that has been properly filtered and converted to engineering units.
     
  9. Mar 19, 2010 #8
    Well in this case I'm just taking in a raw ADC bin and comparing it to what I've defined as a threshold value. If it's over that threshold it's on the track. I that's why I have a second structure that just contains 1s and 0s depending on the status of each sensor.

    I did catch that I named the members the same as the defines of the ADC channels, that's happened a few times. Not too many though. The compiler is now just sitting at the directional_control.c/.h files because they're empty. I still need to give this robot a brain.

    But going back to the extern declaration, I've seen it being used on arrays and such, so why not structures?

    EDIT:

    I have a problem now. Nothing in any of the other files can see the structures.

    This:
    Code (Text):

    void LED_Sensor_Display(void)
    {
         setLED1(SensorsTrack.LOuter);
         setLED2(SensorsTrack.LInner);
         setLED3(SensorsTrack.Centre);
         setLED4(SensorsTrack.RInner);
         setLED5(SensorsTrack.ROuter);
    }
     
    controls a set of LEDs on the brainboard for the robot. The compiler isn't putting the two together.

    Error:
    Code (Text):

    Error - could not find definition of symbol 'SensorsTrack' in file './LED_control.o'.
     
     
    Last edited: Mar 19, 2010
  10. Mar 19, 2010 #9

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    Because it doesn't sense. The extern keyword is a storage qualifier; it applies to things that occupy memory when the program is loaded -- in other words, variables and functions. Structure definitions aren't stored.

    Example: Consider this program:
    Code (Text):

    #include <stdio.h>
    struct Foo {
       double big_array[1024][1024][1024][1024][1024][1024];
    };

    int main () {
       printf ("sizeof(Foo) = %lu\n", sizeof(Foo));
       return 0;
    }
     
    This program defines a structure, a big, huge structure (8 exabytes!) that would never fit in any existing computer's memory (physical or virtual). However, because the structure is never used to allocate memory (e.g., define a variable), the resulting program's footprint is no bigger than this program:
    Code (Text):

    #include <stdio.h>
    struct Foo {
       double number;
    };

    int main () {
       printf ("sizeof(Foo) = %lu\n", sizeof(Foo));
       return 0;
    }
     
    Now change the main in both versions so that they use the structure (other than measuring its size, which is a compile-time operation):
    Code (Text):
    int main () {
       Foo foo;
       printf ("sizeof(foo) = %lu\n", sizeof(foo));
       return 0;
    }
    The version with the 8 exabyte structure will now fail (segmentation fault on a unix machine).

    That looks like a linker error.

    Stop using global variables and a lot of your problems will go away. Using global variables is a bad practice. I suggest kicking that bad habit.
     
  11. Mar 19, 2010 #10
    I never use global variables. :/ I have the structure defined in the detector.h file, and I'm trying to make a LED control function read that structure's members.
     
  12. Mar 19, 2010 #11

    D H

    User Avatar
    Staff Emeritus
    Science Advisor

    You certainly did in the program you are describing. That is exactly what your SensorsADC variable described in the opening post is: A global variable. The sole express purpose of declaring a variable such as SensorsADC extern is to make that global variable visible within the file being compiled.

    Any variable declared at file scope that is not qualified with the static keyword is a global variable. Even those static file scope variables are, in a sense, global. They just have visibility limited to the compilation unit, as opposed to the program as a whole.
     
  13. Mar 19, 2010 #12
    Okay, then I guess I did. :/ I've taught myself most of this stuff, so my understanding isn't as clear cut.

    Anyhow, I do need that structure to be universally accessible. So how can I go about properly doing that?
     
Share this great discussion with others via Reddit, Google+, Twitter, or Facebook