struct issue probably related to codeblocks but I am not sure - c

While writing a simple program where I had to create structs for saving information about a film and a film director, both of those had the same variables inside but with different names
struct Regista
{
char nome[30];
char cognome[30];
int nascita;
int doIexist;
};
typedef struct Regista regista;
struct Film
{
char titolo[30];
char reg[30];
int anno;
int doIexist;
};
I had created an array for both and I wanted to pass those as argument in different functions in order to add elements in those array, and now the question I have: I wrongly wrote this:
int insertfilm(film arrayfilm[]);
int insertreg(regista arrayreg[]);
int main(){
//other stuff
film arrayfilm[SIZE];
regista arrayreg[SIZE];
//other stuff
switch (mainMenuChoice)
{
case 1:
{
insertfilm(arrayfilm);
break;
}
case 2:
{
insertreg(arrayfilm);
break;
}
//other stuff
it should be noted that i passed an array of struct film while it should expect an array of struct regista in insertreg()
I was expecting that it would report an error of wrong type but instead it went all silent and run it without any problem.
My question is: is this caused by my IDE (codeeblocks) or by the C implementation?

The gcc/mingw compiler that Codeblocks uses by default is lax when it comes to give compiler errors for C language type compatibility violations. If you run it with default settings, you get:
warning: passing argument 1 of 'insertreg' from incompatible pointer type
Now as far as the C language is concerned, the above is sufficient for the compiler to be compliant. C doesn't speak of errors and warnings, only of diagnostic messages.
Your code is not valid C, since two structs are only compatible if they have the same struct tag, if all their members have the same type and if they have the same variable name. You use different struct tags and different variable names both, so they aren't compatible.
Formally, since the types aren't compatible, your code is a "constraint violation of the simple assignment rule" and a compiler must give you a diagnostic message, which it did.
I strongly recommend all beginners to compile with strict standard compliance and maximum warnings though. With gcc this means -std=c11 -pedantic-errors -Wall -Wextra. Pedantic errors in particular will block the code from compiling into an executable even though there are C language violations.
In Codeblocks specifically: go Settings -> Compiler, then check the corresponding options there, for example "Enable extra compiler warnings [-Wextra]" to enable -Wextra.

Related

IAR compilation failure, CCS compilation works. Types Incompatibility

After developing a new firmware (main and libraries) with CCS for my CC2538, all errors are debugged, and now, device is working fine.
As from CCS I can not flash the firmware permanently, I'm working with IAR to develop this action.
On IAR, I have created the workspace, the project and included all libraries and files needed to compile the firmware. But, compilation fails due to incompatible types errors.
Error[Pe144]: a value of type "int" cannot be used to initialize an
entity of type "signed short *"
int16_t *accData[3] = malloc(sizeof(int16_t));
Error[Pe513]: a value of type "int" cannot be assigned to an entity
of type "signed short *"
int16_t *accData[3] = malloc(sizeof(int16_t));
Error[Pe120]: return value type ("signed short **") does not match
the function type ("signed short*")
int16_t * lsm303d_readAccData(void)
{
int16_t *accData[3] = malloc(sizeof(int16_t));
...
return accData;
}
Which is the root cause of these errors?
Maybe, any option of the compiler? Do I need to add any file? Or prototype on the code?
KR!
Which is the root cause of these errors?
"a value of type "int"" is the root cause. There should be no int here! Just the signed short* (which is your int16_t*) and a void* from malloc.
This is because you are using a C90 compiler and forgot to #include <stdlib.h>. Upon finding a function with no prototype, C90 would implicitly assume you want a function returning int, which explains the compiler errors "a value of type "int"". But malloc actually returns a void*, so this is a severe bug. Solve this by including the header stdlib.h where malloc is found.
This undesired and irrational behavior of the language was fixed 17 years ago. Consider using a modern compiler instead, or configure your compiler to use the current C language standard (ISO 9899:2011).
That being said, this code doesn't make any sense either:
int16_t *accData[3] = malloc(sizeof(int16_t));
You probably meant
int16_t *accData = malloc( sizeof(int16_t[3]) );
The first error is somewhat misleading. It seems to indicate that you forgot to include <stdlib.h>, so malloc is undefined and the compiler assumes it returns int.
In any case, you are assigning a pointer to an array: this is incorrect.
Returning the address of a local automatic array is incorrect too.
You should define accData as a pointer instead of an array, and make it point to an allocated array of int16_t. You seem to want this array to hold 3 elements, otherwise modify the code accordingly:
#include <stdlib.h>
int16_t *lsm303d_readAccData(void) {
int16_t *accData = malloc(sizeof(int16_t) * 3);
...
return accData;
}
You should configure the compiler to issue more warnings and refuse obsolete constructions such as implicit int. For gcc, add -std=c99 or -std=c11 and -Wall -Wextra -Werror.

Why does Turbo C++ 3.0 give "size of the type is unknown or zero" error for C programs?

#include<stdio.h>
struct Node
{
};
int main()
{
return 0;
}
This simple code is saved with a file name NODE.C and this gives an error :
ERROR NODE.C 5: Size of the type is unknown or zero
The code works fine if I change the extension from NODE.C to NODE.CPP
Can someone explain why this happens?
Empty structures are not legal in C.
From the C99 standard, the relevant grammar productions are:
Note that struct-declaration-list is not optional, and must always have at least one struct-declaration.
In contrast, here is the C++ grammar:
Note that member-specification is optional.
Also note that an empty struct in C++ will not have size zero. The C language also requires that all objects have non-zero size; the error message you're seeing isn't exactly accurate (the error is correct, but the descriptive message is not).
Empty struct is a syntax error in C. The grammar of C language is written so that it prohibits empty structs.
But it is legal in C++ to use empty structs. Thats why .C extension is giving you an error

Compiling C structs

This is my code:
#include <stdio.h>
typedef struct {
const char *description;
float value;
int age;
} swag;
typedef struct {
swag *swag;
const char *sequence;
} combination;
typedef struct {
combination numbers;
const char *make;
} safe;
int main(void)
{
swag gold = { "GOLD!", 100000.0 };
combination numbers = { &gold, "6503" };
safe s = { numbers, "RAMCON" };
printf("Contents = %s\n", s.numbers.swag->description);
getchar();
return 0;
}
Whenever I compile it with the VS developer console, I get this error: error C2440: 'initializing' : cannot convert from 'combination' to 'swag *'.
However if I use gcc the console just prints: "GOLD!". Don't understand what's going on here.
What you stumbled upon is an implementation-specific variant of a popular non-standard compiler extension used in various C89/90 compilers.
The strict rules of classic C89/90 prohibited the use of non-constant objects in {} initializers. This immediately meant that it was impossible to specify an entire struct object between the {} in the initializer, since that would violate the above requirement. Under that rule you could only use scalar constants between the {}.
However, many C89/90 compilers ignored that standard requirement and allowed users to specify non-constant values when writing {} initializers for local objects. Unfortunately, this immediately created an ambiguity if user specified a complex struct object inside the {} initializer, as in your
safe s = { numbers, "RAMCON" };
The language standard did not allow this, for which reason it was not clear what this numbers initializer should apply to. There are two ways to interpret this:
The existing rules of the language said that the compiler must automatically enter each level of struct nesting and apply sequential initializers from the {} to all sequential scalar fields found in that way (actually, it is a bit more complicated, but that's the general idea).
This is exactly what your compiler did. It took the first initializer numbers, it found the first scalar field s.numbers.swag and attempted to apply the former to the latter. This expectedly produced the error you observed.
Other compiler took a more elaborate approach to that extension. When the compiler saw that the next initializer from the {} list had the same type as the target field on the left-hand side, it did not "open" the target field and did not enter the next level of nesting, but rather used the whole initializer value to initialize the whole target field.
This latter behavior is what you expected in your example (and, if I am not mistaken, this is the behavior required by C99), but your C89/90 compiler behaved in accordance with the first approach.
In other words, when you are writing C89/90 code, it is generally OK to use that non-standard extension when you specify non-constant objects in local {} initializers. But it is a good idea to avoid using struct objects in such initializers and stick to scalar initializers only.
Looks like an issue with the initializers. If you use the proper options with gcc, it will tell you this:
$ gcc -Wall -ansi -pedantic x.c
x.c: In function ‘main’:
x.c:21: warning: initializer element is not computable at load time
x.c:22: warning: initializer element is not computable at load time
which is propably the same issue VS is trying to tell you. You can make these go away if you declare gold and numbers static.

Errors compiling example from ANSI C book, Linked Lists chapter

I am doing some examples out of an older C book [A First Book of ANSI C] and am getting an error while trying to compile this example code:
#include <stdio.h>
struct tele_typ {
char name[30];
char phone_no[15];
struct tele_typ *nextaddr;
};
main() {
struct tele_typ t1 = {"Acme, Sam", "(201) 555-6678"};
struct tele_typ t2 = {"Dolan, Edith", "(213) 682-3104"};
struct tele_typ t3 = {"Lanfrank, John", "(415) 718-4581"};
tele_typ *first; /* create a pointer to a structure */
first = &t1; /* store t1's address in first */
t1.nextaddr = &t2; /* store t2's address in t1.nextaddr */
t2.nextaddr = &t3; /* store t3's address in t2.nextaddr */
t3.nextaddr = NULL; /* store the NULL address in t3.nextaddr */
printf("\n%s %s %s",first->name,t1.nextaddr->name,t2.nextaddr->name);
}
..and the output from gcc newstruct.c -o newstruct:
newstruct.c: In function 'main':
newstruct.c:13:3: error: unknown type name 'tele_typ'
newstruct.c:15:9: warning: assignment from incompatible pointer type [enabled by default]
newstruct.c:20:28: error: request for member 'name' in something not a structure or union
It's chapter 10.4 on Linked Lists. Is there an error in the book? or has something changed in the standards/gcc version 4.6.2 20120120 (prerelease)? Thank you!
I couldn't reproduce the first warning; are you sure the code you've pasted here is the code that gives you the warning?
The error unknown type name 'tele_typ' is easy to fix: you've declared a type struct tele_typ, but don't have the struct in front of the line:
tele_typ *first; /* create a pointer to a structure */
If you change this to:
struct tele_typ *first; /* create a pointer to a structure */
It'll compile without error. (And also without warnings in my gcc-4.5.real (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2.)
If you wanted to compile the function body exactly as-is, then you'd also want to add:
typedef struct tele_typ tele_typ;
immediately after the struct tele_typ definition:
struct tele_typ {
char name[30];
char phone_no[15];
struct tele_typ *nextaddr;
};
typedef struct tele_typ tele_typ;
But I'm a little worried about a C book that doesn't give the main() function a return type or typed parameters. int main(int argc, char* argv[]) or int main(int argc, char** argv) is usual, and any book that deviates from these two options strikes me as a little strange. The C Programming Language is a fine book; it is hard to improve upon it for its clarity and correctness. Consider switching to the original.
Your code has the following errors, some of them minor.
main() needs to be int main(void). The main() form is an old-style definition; it's deprecated as of the 1989 ANSI C standard, and flat-out invalid under the 1999 ISO C standard, which dropped the "implicit int" rule. Using (void) rather than () makes it explicit that main has no parameters; the () form is still valid, but has been deprecated since 1989. Many C compilers will accept old-style features like this for the sake of backward compatibility, but will at least warn about them in conforming mode. You should find out how to enable such warnings for your compiler.
tele_typ *first; needs to be struct tele_typ *first;. This is the main problem. (Adding a typedef is another way to work around this, but it's absolutely unnecessary. The code already refers to the type as struct tele_typ; you just need to do so consistently.) Note that in C++ you can refer to the type either as struct tele_typ or just as tele_typ -- of course, C++ is a different language with different rules.
You should have a \n at the end of the string you print; you don't need it at the beginning.
printf("%s %s %s\n",first->name,t1.nextaddr->name,t2.nextaddr->name);
You should have a return 0; before the closing } in your main function. As of the 1989 ANSI C standard (or the equivalent 1990 ISO C standard), falling off the end of main without returning a value returns an undefined result to the calling environment. As of the 1999 standard, falling off the end of main does an implicit return 0;, but there's no harm in being explicit about it.
With warnings enabled, some compilers may complain about missing initializers on the declarations of t1, t2, and t3, since you didn't provide values for the nextaddr member. This is ok, since (a) as long as you have an initializer, any unspecified members are initialized to zero (in the case of a pointer, to a null pointer), and (b) you explicitly assign values to these members later on.
I see that you're using gcc. To get a good set of warnings, you can use this:
gcc -ansi -pedantic -Wall -Wextra
Change the -ansi to -std=c99 or -std=c1x if you want to test against a newer version of the C standard. Note that using -ansi or one of the -std=... options may disable some non-standard extensions. Sometimes you need to write non-portable code; in that case, you can drop that option, and probably the -pedantic as well. But this program doesn't use any extensions, and doesn't need to.
You're missing the 'struct' at the beginning of the 4th line of function main. It should read
struct tele_typ *first;
That would have worked fine in C++, since the 'struct' keyword is optional, but in C it's required.
This line is wrong:
tele_typ *first; /* create a pointer to a structure */
You forgot the struct keyword.
Also, main should really be declared as returning an int, and end with a return.
Using the typedef is definitely the way to go.
Just a quibble: Leading double underscores are reserved; they should NOT be used by application programmers because they could cause namespace problems.
The Kernahan & Ritche book "The C Programming Language" is the best book bar none. It is a hard slog for the beginner, however. The book the person who Posted the question has is obviously wrong!
You have to change the pointer structure declaration for something like this:
struct tele_typ *first; /* create a pointer to a structure */
Why, because you haven't already defined the structure tele_type as a direct type, you still have to point at it using struct tele_typ.
If you on the other side had done something like this:
typedef struct TELE_TYP {
char name[30];
char phone_no[15];
struct TELE_TYP *nextaddr;
}tele_typ;
You would have been able to call for the previously defined type and it would have been ok if you had written:
tele_typ *first;
Long story short, the book is wrong :P

dereferencing pointer to incomplete type

I've seen a lot of questions on this but I'm going to ask the question differently without specific code. Is there a way of EASILY determining what is causing the type to be incomplete? In my case I'm using someone elses code and I'm completely sure I don't have the headers right, but (since computers do this stuff much faster and better than human eyeballs) is there a way to get the compiler to say, "hey you think you have type X at line 34 but that's actually missing." The error itself only shows up when you assign, which isn't very helpful.
I saw a question the other day where someone inadvertently used an incomplete type by specifying something like
struct a {
int q;
};
struct A *x;
x->q = 3;
The compiler knew that struct A was a struct, despite A being totally undefined, by virtue of the struct keyword.
That was in C++, where such usage of struct is atypical (and, it turns out, can lead to foot-shooting). In C if you do
typedef struct a {
...
} a;
then you can use a as the typename and omit the struct later. This will lead the compiler to give you an undefined identifier error later, rather than incomplete type, if you mistype the name or forget a header.
Another possible reason is indirect reference. If a code references to a struct that not included in current c file, the compiler will complain.
a->b->c //error if b not included in current c file
What do you mean, the error only shows up when you assign? For example on GCC, with no assignment in sight:
int main() {
struct blah *b = 0;
*b; // this is line 6
}
incompletetype.c:6: error: dereferencing pointer to incomplete type.
The error is at line 6, that's where I used an incomplete type as if it were a complete type. I was fine up until then.
The mistake is that you should have included whatever header defines the type. But the compiler can't possibly guess what line that should have been included at: any line outside of a function would be fine, pretty much. Neither is it going to go trawling through every text file on your system, looking for a header that defines it, and suggest you should include that.
Alternatively (good point, potatoswatter), the error is at the line where b was defined, when you meant to specify some type which actually exists, but actually specified blah. Finding the definition of the variable b shouldn't be too difficult in most cases. IDEs can usually do it for you, compiler warnings maybe can't be bothered. It's some pretty heinous code, though, if you can't find the definitions of the things you're using.
I don't exactly understand what's the problem. Incomplete type is not the type that's "missing". Incompete type is a type that is declared but not defined (in case of struct types). To find the non-defining declaration is easy. As for the finding the missing definition... the compiler won't help you here, since that is what caused the error in the first place.
A major reason for incomplete type errors in C are typos in type names, which prevent the compiler from matching one name to the other (like in matching the declaration to the definition). But again, the compiler cannot help you here. Compiler don't make guesses about typos.
this error usually shows if the name of your struct is different from the initialization of your struct in the code, so normally, c will find the name of the struct you put and if the original struct is not found, this would usually appear, or if you point a pointer pointed into that pointer, the error will show up.
A - Solution
Speaking for C language, I've just found ampirically that following declaration code will be the solution;
typedef struct ListNode
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
So as a general rule, I give the same name both for both type definition and name of the struct;
typedef struct X
{
// code for additional types here
X* prev; // reference to pointer
X* next; // reference to pointer
} X;
B - Problemetic Samples
Where following declarations are considered both incomplete by the gcc compiler when executing following statement. ;
removed->next->prev = removed->prev;
And I get same error for the dereferencing code reported in the error output;
>gcc Main.c LinkedList.c -o Main.exe -w
LinkedList.c: In function 'removeFromList':
LinkedList.c:166:18: error: dereferencing pointer to incomplete type 'struct ListNode'
removed->next->prev = removed->prev;
For both of the header file declarations listed below;
typedef struct
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
Plus this one;
typedef struct ListNodeType
{
int data;
ListNode * prev;
ListNode * next;
} ListNode;
Outside of possible scenarios involving whole-program optimization, the code code generated for something like:
struct foo *bar;
struct foo *test(struct foo *whatever, int blah)
{
return blah ? whatever: bar;
}
will be totally unaffected by what members struct foo might contain. Because make utilities will generally recompile any compilation unit in which the complete definition of a structure appears, even when such changes couldn't actually affect the code generated for them, it's common to omit complete structure definitions from compilation units that don't actually need them, and such omission is generally not worthy of a warning.
A compiler needs to have a complete structure or union definition to know how to handle declarations objects of the type with automatic or static duration, declarations of aggregates containing members of the type, or code which accesses members of the structure or union. If the compiler doesn't have the information needed to perform one of the above operations, it will have no choice but to squawk about it.
Incidentally, there's one more situation where the Standard would allow a compiler to require a complete union definition to be visible but would not require a diagnostic: if two structures start with a Common Initial Sequence, and a union type containing both is visible when the compiler is processing code that uses a pointer of one of the structure types to inspects a member of that Common Initial Sequence, the compiler is required to recognize that such code might be accessing the corresponding member of a structure of the other type. I don't know what compilers if any comply with the Standard when the complete union type is visible but not when it isn't [gcc is prone to generate non-conforming code in either case unless the -fno-strict-aliasing flag is used, in which case it will generate conforming code in both cases] but if one wants to write code that uses the CIS rule in such a fashion as to guarantee correct behavior on conforming compilers, one may need to ensure that complete union type definition is visible; failure to do so may result in a compiler silently generating bogus code.

Resources