I found the below warning in map file , the struct extern declaration TYPE got changed in file2.c declaration. Below warning from IAR compiler,
Please let me know what is the impact of below type cast.
what is the memory size in file2.c while link time ?
I am trying to find impacts of this implementation not the solution
"struct_tag" to "uint8"
Warning[w6]: Type conflict for external/entry "Block_01", in module file2.c against external/entry in module file1.c; different basic types
/* In module file2.c: */
uint8 NvM_Block_01;
typedef unsigned char uint8;
/* In module file1.c: */
Block_01_T Block_01;
typedef struct Block_01_Tag Block_01_T;
typedef struct Block_01_Tag
{/* 4 bytes with CRC16 */
uint16 Data_01;
uint16 Crc_01;
}Block_01_T;
File1.c
Block_01_T Block_01 = {1234,1};
File2.c
extern unsigned char Block_01;
#define RPM_BLOCK (&Block_01)
Thanks
Damodaran
In file2.c, Block_01 is given type unsigned char, which is 1 byte in size. This will access the first byte of the structure Block_01_t, which will be part of Block_01_T.Data_01.
You have two variables of the same name. Block_01 and different types. This is not allowed. You need to change one of them.
Block_01_T Block_01 = {1234,1}; // in File1.c
extern unsigned char Block_01; // in File2.c
If you want both files to refer to the same variable, you can use.
extern Block_01_T Block_01; // in File2.c
The linker generally doesn't care about the size of object, just their addresses. The compiler reserves space in the object file that defines the object. In this case, the definition is in File1.c, which declares a structure containing two uint16, so it will most reserve at least 4 bytes.
According to the C standard, the consequences are undefined when you use Block_01 in File2.. But I think it's likely that it will be equivalent to giving it the same structure type declaration, and then using *(char *)(&Block_01).
Related
I have a dsPIC33 and programming it using MPLAB X.
I have three files: main.c ADC.c ADC.h
In ADC.h I do a bunch of variable initialisation as follows:
typedef struct pinPair{
unsigned CH0:5,CH123:1,STAT:8,:2;
unsigned I:16;
unsigned V0:16;
unsigned V1:16;
unsigned V2:16;
}pinPair;
typedef pinPair PINPAIRS [5];
extern PINPAIRS pinPairs __attribute__((space(dma)));
then in my main.c file I realise the pinPairs variable:
//Define pinPairs data buffers
PINPAIRS pinPairs __attribute__((space(dma),aligned(256)));
int main(void) {
...
}
Now in my ADC.c file comes the confusing part, The variable pinPair is clearly aligned somewhere in the dam memory because if I do this:
DMA0STA=__builtin_dmaoffset(pinPairs);
the compiler just does its thing but if I do it in the way I was intending:
DMA0STA=__builtin_dmaoffset(pinPairs[pairCounter]);
I get the error:
error: Argument to __builtin_dmaoffset() is not the address of an object in a dma section;
But it is though !!!
Does anyone know what it is that this error means and how I could use the variable in the way I want ?
I can imagine multiple possibilities
The subentities of the array don't have the proper attributes set,
and the compiler doesn't lift pinpairs[pairCounter] (a pinpair
struct)
due to Paircounter being a variable, the compiler can't compute a compiletime address for value.
If the latter, a fixed value would work, if the former, then a compiler limitation that is pretty hard to workaround.
I'd try something like
DMA0STA=__dmaoffset(pinpairs)+dmacounter*uint16(&pinpairs[1]-&pinpairs[0])
(plus maybe some typecasts to get it assigned)
This seems like the sort of question that has already been covered but I can't seem to find out where.
I have come across a peculiar behaviour of gcc.
I file A I have the following definition:
struct SomeStruct {
unsigned int uiVarA;
unsigned int uiVarB;
} SomeVar;
I file B the extern decleration differs:
extern struct SomeStruct {
unsigned char filler;
unsigned int uiVarA;
unsigned int uiVarB;
} SomeVar;
In fact I can make the definition be a double and the extern decleration be an int and gcc will happily compile without so much as a warning (with -Wall and -Wextra even).
I can only conclude this must mean it is perfectly legal behaviour but how it that so?
I am aware that the linker does the job of mapping the two variables but is there no errorchecking at this stage?
Unless you include one file in the other, the compiler will not see both of your definitions.
Normally you would simply declare the struct in a header file separately and then declare variables of that type, so like:
in a.h:
struct SomeStruct {
unsigned int uiVarA;
unsigned int uiVarB;
}
In a.c you could then do: struct SomeStruct SomeVar; and in b.c extern struct SomeStruct SomeVar after including a.h. Or better yet, put the extern struct in a header file and include that in both a.c and b.c.
From the C Spec.
6.2.7 Compatible type and composite type
2 All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undeļ¬ned.
So, it is not perfectly legal behavior in that the behavior is undefined. But that doesn't mean that your linker has the ability to check for it. It is syntactically correct (as long as each declaration is in different translation units).
I've file f1.h contains huge number lines of declarations etc.
say I've variable typedef struct abc_t ABC;
I wanted to get size of the ABC in f2.c without including f1.h & utility function, since I don't want other declaration of f1.h needed in f2.c that unnecessarily increases binary size.
I just need only sizeof ABC.
Its typedef variable, how should we get its size in f2.c?
Is there any method to achieve this?
You can simply declare another variable to store the size. So in some header - not f1.h - you would have
extern unsigned size;
while in f1.c you need to define it
unsigned size = sizeof(<whatever type you want>)
extern unsigned char pkt_data[];
Here what will be the pkt_data size. How do I know the pkt_data declaration?
All that the declaration says is that there's an array named pkt_data. The size is not specified there, and unless you're the one writing that line, the specifics of it should be left to the code that actually defines it (ie: reserves space for it).
It is extern declaration. It is declaration only, not definition.
It means pkt_data will be defined in some other file or some other modules being linked.
So, see the definition of pkt_data to see its size.
You have not declared the size, extern corresponds that you will define pkt_data[] some where else but only once. you cant get the size from an extern declaration.
This declaration
extern unsigned char pkt_data[];
as well as this one
unsigned char pkt_data[];
are incomplete.
It is not possible to determine the size of an incomplete type.
How do I know the pkt_data declaration?
You know it.
extern unsigned char pkt_data[];
is the declaration.
What is missing here is the definition.
To answer the question: Search it in the sources available. It you do not have access to the definition of pkt_data there is no chance to determine the size of pkt_data.
All we know is that the address of pkt_data would have the siez of a pointer. The following statement would be perfectly valid, btw:
size_t s = sizeof(&pkt_data);
If I include the declaration of the part structure(for example) into two different files,
will part variables in one file be of the same type as part variables in the other file?
Yes, they're of the same type if the declarations are structurally the same. If this weren't true, it wouldn't be possible to call library functions that use structure parameters, since the caller and callee are in different files.
The declarations don't have to be literally the same. As long as they specify the same types in the same order, things like member names and the name of the struct type don't have to match. So if you do:
file1.c:
struct {
int i;
char c;
} var1;
and in file2.c:
typedef struct newstruct {
int v1;
char v2;
} newstruct_t;
newstruct_t var2;
then var1 and var2 are of the same type.
The full details are a bit more complex, but this is a useful approximation.
However, programming like this will be confusing. If you intend to share a type between files, you should put the declaration in a header file, and #include it in all the source files that use it.