• Support PF! Buy your school textbooks, materials and every day products Here!

C Structure Problem

  • Thread starter Lancelot59
  • Start date
  • #1
634
1
I have a function for my robot that reads multiple IR sensors, and I get a syntax error on the bolded lines.

Code:
//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:
//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:

Answers and Replies

  • #2
ideasrule
Homework Helper
2,266
0
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
 
  • #3
634
1
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:
  • #4
ideasrule
Homework Helper
2,266
0
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.
 
  • #5
D H
Staff Emeritus
Science Advisor
Insights Author
15,393
683
Code:
	//Reads Left Outer Sensor
	SetChanADC([b]RLS_LOuter[/b]);
	ConvertADC();
	while(BusyADC());
	SensorsADC.[b]RLS_LOuter[/b] = ReadADC();
    	
    ...
}
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.


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.
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.
 
  • #6
ideasrule
Homework Helper
2,266
0
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.
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.
 
  • #7
D H
Staff Emeritus
Science Advisor
Insights Author
15,393
683
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.
 
  • #8
634
1
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.
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:
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:
Error - could not find definition of symbol 'SensorsTrack' in file './LED_control.o'.
 
Last edited:
  • #9
D H
Staff Emeritus
Science Advisor
Insights Author
15,393
683
But going back to the extern declaration, I've seen it being used on arrays and such, so why not structures?
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:
#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:
#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:
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).

I have a problem now. Nothing in any of the other files can see the structures.
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.
 
  • #10
634
1
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.
 
  • #11
D H
Staff Emeritus
Science Advisor
Insights Author
15,393
683
I never use global variables.
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.
 
  • #12
634
1
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?
 

Related Threads on C Structure Problem

Replies
2
Views
1K
  • Last Post
2
Replies
31
Views
3K
  • Last Post
Replies
5
Views
2K
  • Last Post
Replies
6
Views
2K
  • Last Post
Replies
4
Views
1K
  • Last Post
Replies
3
Views
582
  • Last Post
Replies
20
Views
2K
Replies
1
Views
7K
Replies
2
Views
4K
Top