MISRA C 2012 rule 18.8 violation - c

i got a MISRA C violation for the code bellow `
typedef enum NUMBER{
LOW = 0,
HIGH = 2 }NUMBER;
int main(void){
unsigned int A[HIGH]={2U,3U};}
what are the recommendations?
Best reds

Rule 18.8 is about using VLA.
An array using an enumeration constant is not a VLA. There is no VLA in your code.
Conclusion: your static analyser is broken.

Related

What can be the alternate way to solve MISRA 2012 Rule 17.3 violation?

MISRA 2012 Rule 17.3 states that a function should never be implicitly declared. However, in this case at line no 6, pf_func is violating the MISRA 2012 17.3 Rule.
typedef unsigned long long uint64;
typedef void (*FOREACH_FUNC)(uint64 ull_key);
void main(FOREACH_FUNC pf_func)
{
uint64 var;
pf_func(var); /*Violation reported on this line*/
}
Here, pf_func is causing violation on MISRA 17.3 Rule. Is this violation valid or is this a bug in the static analysis tool that I am using. Moreover, is there any alternate solution to avoid this violation without changing the workflow of the code?
However, when I modify the code to this-
typedef unsigned long long uint64;
typedef void (*FOREACH_FUNC)(uint64 ull_key);
FOREACH_FUNC pf_func(uint64 ull_key);
void main()
{
uint64 var;
pf_func(var);
}
there is no violation reported for rule no 17.3. I am not able to understand the working of function pointer here. Is this the correct or ethical way to solve this issue? Or is there any fault in the static analysis tool itself?
Rule 17.3 is "a function shall not be declared implicitly" and refers to the old C90 way of allowing function calls even when no prototype format declaration is present.
Your code does not do this. All it does is to call a function through a function pointer. So there is no MISRA violation, this is a false positive and a tool bug in your static analyser.
However, assuming you use C99 or later, it is preferred to use stdint.h over home-brewed integer types.

Does union support flexible array members?

I have declared a flexible array member in union, like this:
#include <stdio.h>
union ut
{
int i;
int a[]; // flexible array member
};
int main(void)
{
union ut s;
return 0;
}
and compiler gives an error :
source_file.c:8:9: error: flexible array member in union
int a[];
But, Declared array zero size like this :
union ut
{
int i;
int a[0]; // Zero length array
};
And it's working fine.
Why does zero length array work fine union?
No, unions do not support flexible array members, only structs. C11 6.7.2.1 ยง18
As a special case, the last element of a structure with more than one
named member may have an incomplete array type; this is called a
flexible array member.
In addition, zero-length arrays is not valid C, that's a gcc non-standard extension. The reason why you get this to work is because your compiler, gcc, is configured to compile code for the "non-standard GNU language". If you would rather have it compile code for the C programming language, you need to add compiler options -std=c11 -pedantic-errors.
int a[] is the C standard notation (since C99).
int a[0] is GNU C syntax, which predates C99. Other compilers might also support it, I don't know.
Your compiler seems to default to C90 standard with GNU extensions, which is why latter compiles, but first one does.
Furthermore, as stated in Lundin's answer, standard C does not support flexible array members in union at all.
Try adding -std=c99 or -std=c11 to your compiler options (gcc docs here).
Also -pedantic or -pedantic-errors is probably a good idea too, it'll enforce more strict standard compliance.
And, obligatory aside, -Wall -Wextra won't hurt either...
I'm not sure what the standard would say about this, but G++' unions seems to accept flexible arrays just fine. If you wrap them in an anonymous struct first, like so:
union {
unsigned long int ul;
char fixed[4][2];
struct {
char flexible[][2];
};
};

compilation error in c struct variable assignment

Got a doubt in struct variable assignment.
struct udata
{
char name[50];
int num;
char ch;
};
void main()
{
struct udata a = {"ram", 20, 'a'};
struct udata b;
//b = {"ashok", 10, 'c'}; - illegal
b = a;
}
In above code b = {"ashok", 10, 'c'}; is giving compilation error but its accepting b = a;. I hope both are similar kind of assignment, but I dont know why its not accepting first one. Can someone explain me why it is so ?
Note : I am compiling in a fedora gcc compiler.
Initializers can only be used at declaration time. If you want to initialize b after declaration, then you can do it by using a compound literal-- a C99 feature:
b = (struct udata){"ashok", 10, 'c'};
GCC also support copound literals as an extension.
What you're trying to do cannot be done directly in standard C. The best standard and portable solution is to use a temporary:
const struct udata tmp = {"ashok", 10, 'c'};
b = tmp;
However, in practice, the following is often (but not always!) allowed by compilers (*note below):
b = (struct udata){...};
(* note: I believe at least MSVC does not support this syntax, and probably many others; but just throwing it out there. GCC, however, does support it)
That's how C is designed and specified to work. There's nothing you can do. If you have a structure variable, you can only initialize it by an initializer in the declaration or by later initializing the individual members.
In the future, when posting a question regarding compiler errors, please include the complete and unedited error log in the question.

C structure initialization with variable

I've run into a problem that seems to not be addressed by any of the C Standards after C89 save for the mention that structures initialization limits had been lifted. However, I've run into an error using the Open Watcom IDE (for debugging) where the compiler states that the initializer must be a constant expression.
Here's the gist of what's going on.
typedef struct{
short x;
short y;
} POINT;
void foo( short x, short y )
{
POINT here = { x, y }; /* <-- This is generating the error for the compiler */
/* ... */
}
Any ideas why, or what standard disallows that?
The following quote is from the C99 rationale:
The C89 Committee considered proposals for permitting automatic
aggregate initializers to consist of a brace-enclosed series of
arbitrary execution-time expressions, instead of just those usable for
a translation-time static initializer. Rather than determine a set of
rules which would avoid pathological cases and yet not seem too
arbitrary, the C89 Committee elected to permit only static
initializers. This was reconsidered and execution-time expressions are
valid in C99.
The problem is that C isn't an Object language and only does strict typing. Further, C maintains a difference between structs and arrays.
The way your code will have to work is
void foo( short x, short y )
{
POINT here;
here.x = x;
here.y = y;
}
This is normal for C89... initializers do need to be constant, ie. able to be determined at compile time. This means no variables in initializers, and it's true for other types as well, not just structs. In C99, your code would work.

struct initializer, typedef with visual studio

I wonder why the following does not work with Visual studio
typedef struct {
float x, y;
} complexf;
typedef union {
complexf f;
long long d;
} rope;
int main(void)
{
complexf a;
rope z = {a};
}
The error is at line rope z = {a}, cannot convert from complexf to float. If the first member of the union is not a typedef, then it works. Is this a compiler bug, or a dark edge of C ?
ANSI C standard (aka C89), 3.5.7:
All the expressions in an initializer
for an object that has static storage
duration or in an initializer list for
an object that has aggregate or union
type shall be constant expressions.
The latter part of this restriction has been dropped in C99, which isn't properly supported by VS.
in VS 6.0 when I compile with /W4 I get
warning C4204: nonstandard extension used : non-constant aggregate initializer
so that makes me think it's not standard C and you are in compiler dependent land.
Works fine on my G++ 3.4.4 on Cygwin.
Except for the ':' at the end needing a change to ';'.
And, I changed '__int64' to 'long long'.
With my stronger bias towards C for such code, I would have written,
rope z = *(rope *)&a;
to force it on to the C++ compiler :-).
But, don't do that...
The right way to go is of course, as David notes in his comment,
rope z; z.f = a;

Resources