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

Structure Problem Continues

  • Thread starter Lancelot59
  • Start date
  • #1
634
1
I'm actually getting pretty frustrated with this now. It makes no sense.

I have this structure defined in detector.h

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

Answers and Replies

  • #2
33,503
5,190
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.
 
  • #3
634
1
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?
 
  • #4
33,503
5,190
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.
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;).
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.
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.
What do you mean why is it in the header file? Are you not supposed to define and instantiate structures in headers?
When a struct is used, a header file normally contains only the struct template definition, not a struct variable declaration/definition.
 
  • #5
634
1
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:
  • #6
33,503
5,190
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 wide variety of functions, and for whatever reason when I try to pass stuff by reference it gives me a syntax error.

For example void(int& var) is invalid apparently.
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.
 
  • #7
634
1
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.
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.
 
  • #8
33,503
5,190
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.
 
  • #9
634
1
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?
 
  • #10
33,503
5,190
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?
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.
 
  • #11
634
1
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:
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?
 
  • #12
33,503
5,190
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.
 
  • #13
634
1
The main function will instantiate the structure. I'm getting a syntax error now though:
Code:
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.
 
  • #14
33,503
5,190
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.
 
  • #15
634
1
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:
  • #16
634
1
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:
void monitor(struct sensor_data *S)
{
	forward();	//Move forward
}
Function prototype
Code:
void monitor(struct sensor_data *S);
and I get this:

Code:
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:
  • #17
634
1
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.
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:
detector.h:14:Error [1109] type mismatch in redeclaration of 'ADC_ALL'
Code:
void ADC_ALL(struct sensor_data *SensorPnt);
and
Code:
//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:
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:
void monitor(struct sensor_data *SensorPnt)
{
	ADC_ALL(SensorPnt);

	forward();	//Move forward
}
 
  • #18
33,503
5,190
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:
	*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.
 
  • #19
634
1
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:
  • #20
634
1
Well, I fixed it, and still got the error when I commented out the function header:

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

detector.c:62:Error [1207] tag 'sensor_data' is incomplete
Prototype
Code:
void ADC_All(struct sensor_data *SensorPnt);
Definition
Code:
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:
  • #21
33,503
5,190
What type does ReadADC return?

The messages that the compiler is emitting might be part of your problems.
 
  • #22
634
1
It returns an int, so that's not the issue. I even made a random test variable and set it equal to one in it's place and that caused the same issue.

The problem is this I think
Code:
59:Error [1207] tag 'sensor_data' is incomplete
And according to the manual:

Code:
1207: tag '%s' is incomplete
An incomplete struct or union tag cannot be referenced by the member
access operators. Common causes include a misspelled structure tag
name in the symbol definition.
But you can see from the code that everything is spelled correctly.
Code:
	struct sensor_data SensorData;					//Creates structure that holds all sensor data
	struct sensor_data *SensorPnt = &SensorData;	//Creates a pointer for SensorData
I passed it to monitor like so:
Code:
monitor(SensorPnt);
and it passed to adc
Code:
void monitor(struct sensor_data *SensorPnt)
{
	adc(SensorPnt);
}
I do get a warning in main.c
Code:
main.c:112:Warning [2054] suspicious pointer conversion

which apparently means that:
2054: suspicious pointer conversion
A pointer has been used as an integer or an integer has been used as a
pointer without an explicit cast.
where I pass monitor the pointer. I don't get it.
 
  • #23
634
1
I'm still getting this error:
Error [1207] tag 'sensor_data' is incomplete

what the crap is happening here?

Code:
struct sensordata SensorData;					//Creates structure that holds all sensor data
struct sensordata *SensorPnt = &SensorData;		//Creates a pointer for SensorData
Code:
struct sensordata
{
	//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
	
	//Times flags for each of the sensors
	int FLAG_LOuter;		//Outer Left Sensor
	int FLAG_LInner;		//Inner Left Sensor
	int FLAG_Centre;		//Centre Sensor
	int FLAG_RInner;		//Inner Right Sensor
	int FLAG_ROuter;		//Outer Right Sensor
};
everything is clean, so what the hell can it possibly be complaining about?
 
  • #24
33,503
5,190
You have struct sensordata in one place, and struct sensor_data elsewhere. That's a big problem.
 
  • #25
634
1
I cleared all that out, and I'm still getting the error.

I'm having to comment out the prototype for adc which I now call Scan_All() because it gives me another error.

detector.h:14:Error [1109] type mismatch in redeclaration of 'Scan_All'


which again I don't see the cause of because the prototype is:

void Scan_All(struct sensor_data *);

and the head of the definition is:

void Scan_All(struct SensDat *SensorPnt)
 

Related Threads on Structure Problem Continues

Replies
2
Views
1K
  • Last Post
Replies
5
Views
2K
  • Last Post
Replies
4
Views
1K
  • Last Post
Replies
11
Views
2K
  • Last Post
Replies
6
Views
2K
  • Last Post
Replies
2
Views
3K
  • Last Post
Replies
0
Views
4K
Replies
2
Views
4K
Replies
1
Views
7K
Replies
1
Views
3K
Top