Fixing Syntax Error in C Structure for Robot IR Sensor Reading

  • Thread starter Thread starter Lancelot59
  • Start date Start date
  • Tags Tags
    Structure
Click For Summary

Discussion Overview

The discussion revolves around a syntax error encountered in a C function designed to read multiple infrared (IR) sensors for a robot. Participants explore issues related to the declaration and usage of a structure intended to hold sensor data, as well as the implications of using the `extern` keyword with structures.

Discussion Character

  • Technical explanation
  • Debate/contested
  • Conceptual clarification

Main Points Raised

  • One participant reports a syntax error when accessing a structure in their function and questions the validity of their declarations.
  • Another participant points out a potential inconsistency between the structure name `Sensors_ADC` and the variable name `SensorsADC` used in the code.
  • It is suggested that the structure needs to be defined as an object in the main program for proper access.
  • Concerns are raised about the use of `extern` with structures, with one participant stating that `extern` is only for functions and variables, not for structure definitions.
  • There is a discussion about the implications of having multiple copies of a variable with the same name and how this might confuse the linker.
  • One participant mentions the need for proper filtering and conversion of raw sensor data, suggesting that not all functions require direct access to raw data.
  • Another participant expresses confusion about the inability of other files to access the structures, indicating a potential issue with visibility or scope.
  • There is a clarification that `extern` can be used for variables, including arrays, but not for structure definitions themselves.

Areas of Agreement / Disagreement

Participants express differing views on the proper use of `extern` with structures, with some asserting it is inappropriate while others question the rationale behind it. The discussion remains unresolved regarding the best practices for structuring the code and ensuring proper access to the sensor data across multiple files.

Contextual Notes

There are limitations in the discussion regarding the assumptions made about variable scope and the visibility of structures across different files. The implications of using the `extern` keyword are also not fully resolved, leading to potential confusion in the implementation.

Lancelot59
Messages
640
Reaction score
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:
Physics news on Phys.org
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
 
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:
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.
 
Lancelot59 said:
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.


ideasrule said:
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.
 
D H said:
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.
 
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.
 
D H said:
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:
Lancelot59 said:
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
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
Lancelot59 said:
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
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?
 

Similar threads

Replies
31
Views
4K
  • · Replies 3 ·
Replies
3
Views
3K
  • · Replies 7 ·
Replies
7
Views
2K
  • · Replies 3 ·
Replies
3
Views
6K
Replies
10
Views
2K
  • · Replies 15 ·
Replies
15
Views
3K
  • · Replies 5 ·
Replies
5
Views
4K
  • · Replies 75 ·
3
Replies
75
Views
7K
  • · Replies 14 ·
Replies
14
Views
3K
Replies
9
Views
2K