What's the difference between these C external definitions? - c

I ran into this problem debugging an AVR microcontroller:
I have a main.c file with numerous variable definitions, amongst them an array of structs, like this:
struct mystruct mystruct_array[COUNT];
In another .c file I refer to this array as external, but I left away the array brackets and size so I wouldn't repeat myself and just declared the variable as a pointer (because arrays are essentially pointers, aren't they?):
extern struct mystruct *mystruct_array;
But when I checked the address of the array using printf("%p\n", mystruct_array);I got a null pointer instead of the array's location in memory. Also if I would access the subsequent items in the array, like printf("%p\n", &(mystruct_array[n])); it would print address 0 plus n times sizeof(struct mystruct).
Only after I changed the definition to
extern struct mystruct mystruct_array[COUNT];
(exactly the same as in main.c), I got the true address of the array.
My question: Why does this make a difference to the compiler (in my case avr-gcc)?

That's a fun one.
When you write :
struct mystruct mystruct_array[COUNT];
You create a global array of mystruct structs, there are COUNT of them, and since you didn't initialize it, it'll be filled with zeros.
When you then write:
extern struct mystruct *mystruct_array;
You tell the compiler that there's a variable called mystruct_array somewhere and that it's a pointer. But it's not, it's an array. So the compiler is going to read the content of the array as if it were a pointer.
So when you try to output the value of that pointer, the compiler goes fetch mystruct_array in memory and outputs its content as if it were a pointer. Since it's actually an array full of zeros, you're seeing a null pointer in the output.
Instead you should write something like:
extern struct mystruct mystruct_array[];
So the compiler knows the correct type of your variable. You can specify the length in the square brackets here, but you don't have to.
I'd recommend you go read up on the differences between pointers and arrays to make sure you don't confuse them in the future.

The ideal way to do this is to put an extern declaration in a header file, and a definition in exactly one file. For example,
header.h
extern struct mystruct mystruct_array[];
/* or extern struct mystruct mystruct_array[COUNT] */
main.c
#include "header.h"
#define COUNT 10
/* should have an initializer to be a definition: */
struct mystruct mystruct_array[COUNT] = { 0 };
/* ... */
other.c
#include "header.h"
/* ... */
printf("%p\n", mystruct_array);
That saves you repetition, and limits the places where you might need to make changes. Note that if your header does not define the number of elements in the array, then you cannot apply the sizeof operation to that array in files other than the one that also provides the array definition.
Note, too, that although arrays are not pointers, in most contexts in C source code, an array name is converted to a pointer to the first element of the array. This is the source of the misapprehension that arrays are pointers. Although they are not pointers, in many ways they act as if they were.

The declaration of extern means that the declared object is global in an other C file. Then, when you generate the object file, it is generated also if the declared object (in this case the structure) is not present.
If you declare:
extern struct structname * s;
means that in the other C module there's a global visible pointer to a structure structname s.
If you declare:
extern struct structname s;
means that in the other C module there's a global visible structure structname s!
When you will link the program, if you don't indicate to the linker to link the object that contains the structure, you will get an Undefined reference!

Related

C - Structure and user variables share same memory - possible?

Sorry for newbie question in C. I have following problem.
Let's say I have a structure of:
struct foo {
char var_a;
char var_b;
char var_c;
};
And a list of variables:
foo j;
char a, b, c;
I want to make sure, that in all moments of time j.var_a is equal to a, j.var_b equals to b and j.var_c equals to c. E.g I want that structure members would be also accessible like normal user variables at any moment. I thought that struct members just need to share the same memory locations with defined user variables, so assumed that something from this has to be defined as pointer and tried this:
foo *j;
char a, b, c;
And in main() function:
j = &a;
With the aim of assigning address of structure pointer to address of a and with assumption that a,b,c will be located in adjacent memory spaces. But compiler throws error obviously because I can't point pointer of one type to address of other type. I also feel this is unsafe as it relates to the order of variables in memory.
So is there a safe way to achieve this goal without manual reassignment each time when any of variables are changed and additional memory copying? I have an embedded target, so would like to save memory and processor time.
You're correct that j = &a will not do what you expect for the reasons you gave.
What you can do instead is define the members of struct foo to be pointers:
struct foo {
char *var_a;
char *var_b;
char *var_c;
};
char a, b, c;
foo j = { &a, &b, &c };
char a, b, c; local variables are't guaranteed to be contiguous, in-order, and to exit in memory.
There's no way to robustly overlay a struct over them.
The closes thing you could do to pretending some local variables overlay a struct is to make those "local variabled" macros:
struct foo {
char var_a;
char var_b;
char var_c;
};
int main(void)
{
struct foo j;
#define a j.var_a
#define b j.var_b
#define c j.var_c
/*now a,b,c are sort of like contiguous locals
that overlay j */
#undef a
#undef b
#undef c
}
Although there are some circumstances when it would be useful to be able to use "ordinary variable" syntax to access members of a structure (among other things, it may improve performance, allow code that saves/restores a program's state to be reduced to a single structure write/read, etc.) the closest C comes to allowing that is allowing the use of #define macros to replace the "variable" name with a reference to the structure.
For example,
struct foo { int foo_woozle, foo_moozle; } myFoo;
#define woozle myFoo.foo_woozle
#define moozle myFoo.foo_moozle
Unfortunately, this approach requires that the "variable" names not appear as tokens in any other context within the compilation unit. If, for example, one tried to declare a structure with a member named woozle, the structure declaration would fail because its name would get replaced with myFoo.foo_woozle.
On some implementations it may be possible to do something like:
extern int woozle,boozle;
extern volatile struct foo myFoo;
and then use code written in another language (e.g. assembly) to overlay the objects as desired. Unfortunately, this is likely to be unreliable unless optimizations are disabled or the objects are all qualified volatile. The approach using #define will thus be able to generate more efficient code, but is unfortunately saddled with the ugly semantic limitations of macro substitution.

Declare Global Struct Variable With Variable Size In C

I have a struct that looks like this.
struct MyStruct1 {
int (*fn)();
int b;
}
And another struct that looks like this.
struct MyStruct2 {
int a;
struct MyStruct1 b[0];
}
I would like to declare a global variable of type MyStruct2, somewhat like this.
int func1() { return 1; }
int func2() { return 2; }
struct MyStruct2 a = { 1, { func1, 5 }, { func2, 6 } };
However, I get a "Initializer Element is not a compile-time constant".
I would like to know (a) if it is even possible to globally declare a variable sized struct (or at least define a chunk of space, of the correct size, to have the values inserted into later), and (b) if it is, what am I doing wrong?
It is not possible to declare a variable-size struct, neither locally nor globally. Every type has a fixed size determined at compile time.
The error message you report is surprising, however. If all the declarations you gave are at file scope, in the same file, in the order you gave them, then the initializer for variable a is a compile-time constant. However, it is not a proper initializer for a struct MyStruct2,
because it specifies more elements than that struct type has members,
because the initializer element for a.b is an initializer for a struct MyStruct1 instead of for an array of such, and
because even if you converted the last two initializer elements into one array initializer, it has more elements than there are elements in a.b (i.e. more than zero).
If you want a dynamically-sized array, whether as a variable in its own right or as a member of a struct, then you must declare a pointer to it, and allocate memory for the elements dynamically. In that case, the elements are not themselves part of the struct; only the pointer to them is. (That is different, by the way, from a fixed size array whose size is implicit in its initializer; these are possible only for independent types, though, not for types of struct or union members).
EDIT:
C99 flexible arrays are a possible alternative, as ShafikYaghmour commented. These are similar, but not identical, to a struct element that is a pointer to a dynamically-allocated array. In that case, however, you not only cannot statically declare the array elements, you also cannot statically declare instances of the struct itself, so this wouldn't at all get around your initializer issue. There are several other quirks and limitations. Personally I see few advantages to flexible arrays, but they do make it a bit easier to properly free struct instances.
You cannot create arrays of size 0 in C legitimately. In C99 or C11, you can use a 'flexible array member' like this:
struct MyStruct2 {
int a;
struct MyStruct1 b[];
};
but structures that have a flexible array member can only usefully be created with dynamic memory allocation (other forms of allocation give you an unusable flexible array of size 0).
The older 'struct hack' version of a structure with a variable size array uses an array of size 1 in the structure. You can create global versions of such a structure with an array of size 1.
But basically, you are trying to do what the language prohibits you from doing, and not very surprisingly, you are failing.
What you do about this depends on what you need. Global variables are inherently somewhat undesirable, so there's an element of "you should be trying to avoid doing this". That said, the rules apply to file scope (static) variables too, and those have many uses.
You can use an explicit pointer in place of the array, and have separate allocations of the body of the struct MyStruct2 and its array of struct MyStruct1 members. You can forgo the global variable and use dynamically allocated structures with a flexible array member.
struct MyStruct2 *ms2 = malloc(sizeof(*ms2) + N * sizeof(ms2->b[0]));
This creates an struct MyStruct2 (as shown at the top of this answer) with N members in the array. Without any further changes, you can use ms2->b[0] through ms2->b[N-1] (well, apart from error checking that the malloc() succeeded).

typedef stuct with forward declaration in C

I have something like:
typedef struct Data DATA, *DATA_PTR;
typedef struct Units UNITS, *UNITS_PTR;
struct Data
{
double miscData;
UNITS units;
};
struct Units
{
double x[2];
double y[2];
double z[2];
};
in my project_typedef.h file.
In another file, I have something like:
void fileInput(DATA_PTR data)
{
//usual declarations and other things
data->miscData = 0; //Works!
data->units.x[0] = 5; //Doesn't work
//etc...
}
However, this doesn't work since units is declared after data in project_typedef.h (if I switch the order it works). The error that i get is "left of '.x' must have struct/union type". I thought that the forward declaration would fix this issue. Why not?
When you define Data, all members must be complete types. Since UNITS isn't a complete type at that point, this doesn't work. (By contrast, UNITS_PTR would be fine, since pointers to incomplete types are complete types.)
Simply put the Units definition above the Data definition and you should be fine.
(As #cnicutar already noted, you're also using the array x wrong.)
The forward declaration allows you to use its name in context where an incomplete type is allowed. Declaring a struct member is not one of such cases, the complete definition must be known as it contributes to the struct layout.
for a struct definition you should always use complete types for all members in a structure... but this is not the case with UNITS units in struct Data,which declares a variable named units of type struct Units which is never declared before the struct Data... this reflects an error.. you should place the Units definition above Data definition.. and all will work fine..
and regarding forward declaration this does not work since whenever a struct variable is defined, the compiler first allocates the memory required to the struct (struct members donot have a memory allocated to them, unless they are linked to a struct type of variable.. thats why struct variables cant be initialized inside struct template).. :)
There is no prototype for struct. This is because compiler needs to know size of struct before using it. You could use pointer on struct, because pointers have known size no matter which type they point to.

error: redefinition of typedef in c

We have an assignment in school where we got a header file and we
need to implement it. The header defines:
typedef struct Board* BoardP;
which to my understanding means the BoardP is a pointer to struct Board.
Anyhow, my implementation is:
typedef struct Board
{
int width;
int height;
char *board;
} *BoardP;
But i keep getting:
Board.c:21: error: redefinition of typedef ‘BoardP’
Board.h:4: note: previous declaration of ‘BoardP’ was here
Any ideas as to why this happens? Thanks!
EDIT: another question. As you can see my struct hold an array of characters. When I write a constructor should I initialize (malloc(sizeof(height*width)) the array first and then the struct? And how about use of free()? Should I free the array first and then the struct?
Thanks
Drop the typedef from the definition.
struct Board
{
int width;
int height;
char *board;
};
A struct is a struct; it's not like you always have to typedef it. To be honest, I only typedef structs for opaque pointers.
From style(9):
Avoid using typedefs for structure types. Typedefs are problematic
because they do not properly hide their underlying type; for example
you need to know if the typedef is the structure itself or a pointer
to the structure. In addition they must be declared exactly once,
whereas an incomplete structure type can be mentioned as many times as
necessary.
It happens because in your pre-written header file you have to write an implementation for, you already typedef the data type struct Board * into a "new" data type BoardP. Your explanation that the BoardP is the pointer to the data type struct Board is correct.
But, to make the code in the header work, you only have to define what's missing, which is, in this instance, only an implementation of the struct Board data type.
Your proposed solution would work if you didn't already have the typedef in the header file.
As you already have it in the header file, only the code proposed by cnicutar (the code without the typedef) should be put in the .c file.
Regarding your second question...
You can malloc in either order you like, but I generally allocate the object itself before I try to allocate any sub objects, because that way you have a clear place to store the results of subobject mallocs (in the struct) rather than having to store them in otherwise useless temporary variables.
Be sure to handle your errors correctly - if the second malloc fails, you'll need to free the first one. This is actually a place that many C programmers like to use goto:
struct Board *makeBoard(...)
{
struct Board *b = malloc(sizeof *b);
if(b == NULL) goto end1;
b->board = malloc(...);
if(b->board == NULL) goto end2;
// ...
end2:
free(b);
end1:
return NULL;
}
When you free the data, you have to free the subobjects before you free the main objects, unless you store pointers to all the subobjects in temporary variables before you free the main object. That is, the following won't work:
free(b);
free(b->board);
Because by the second statement, b is freed and won't be able to be safely dereferenced. It's cleanest just to do it in the opposite order.

How to use pointers to structures

I have defined a structure in one of my source code files. Also I have defined pointer to that structure like (global declaration)
struct blockPropStruct
{ int random_id;
int id;
CvPoint left_up;
CvPoint right_down;
};
typedef struct blockPropStruct *newBlock;
In the same file I am assigning memory to those pointers using malloc to create array of structures.
newBlock = (blockPropStruct*)malloc(maxNum*sizeof(blockPropStruct));
Now I am trying yo use it in some other source file by declaring (global declaration)
extern struct blockPropStruct *newBlock;
Now when I use something like
newBlock[i].left_up.x=mark1[i];
It throws up an error.
It would appear that you have omitted the declaration of the struct type in the file which declares the extern variable.
The name of your structure is struct blockPropStruct. Note that in C, you can't just remove the struct part, it's part of the type's name. You can define a type for your structure so you have less typing, but I think it's better to remember to use your structures as struct blockPropStruct.
Based on the error messages you have added in your comments:
error C2036: 'blockPropStruct *' : unknown size
error C2027: use of undefined type 'blockPropStruct'
You are attempting to get the size sizeof(blockPropStruct) in your malloc() call since blockPropStruct is not a valid identifier so you are attempting to get the size of an undefined type.
To define your type:
typedef struct blockPropStruct blockPropStruct;
Now you can refer to your structure type as blockPropStruct or struct blockPropStruct.
You need to give a name with 'typedef' and point to it.
newBlock = (blockPropStruct*)malloc(maxNum*sizeof(blockPropStruct));
To actually for the above statement to work, the current source file should see the size of structure. So, check whether you have included the corresponding header file.
extern struct blockPropStruct *newBlock;
And when you are doing -
newBlock[i].left_up.x=mark1[i];
You should bring the definition of the blockPropStruct to the current compilation unit to be able to use it members. So, try -
#include "blockPropStruct.h"
extern struct blockPropStruct *newBlock; // This says to use else where
// initialized newBlock
// ....
newBlock[i].left_up.x=mark1[i]; // And to do this, bring the definition
// to this file scope
And there is no need to explicitly typecast malloc.

Resources