How do I create arrays / average [duplicate] - c

Okay, so this is a stripped down variant of a bug I had. The bug was that I initialized an array using a variable that wasn't initialized. Earlier I used a function to declare the number of elements using a function, but after a cleanup I forgot about it and moved all declarations to the top of the function.
I used the flags -std=c99 -Wall -Wextra -pedantic -O, and usually gcc warns about values being used before they are uninitialized, but in this specific case it didn't. So, my question is:
Is this a bug in gcc or is it possible for f(&n) to post-initialize the array size in some weird way?
#include <stdio.h>
void f(int * x) {
*x = 8;
}
int main(void) {
int n;
float a[n]; // Compiler should warn that n may contain garbage
a[7] = 3.1415;
printf("%f\n", a[7]);
f(&n); // Removing this causes the compiler warn as expected
return 0;
}
EDIT: It may be this gcc bug?

GCC is accepting float a[n] as a variable-length array. It should, however, warn you that n contains garbage when it’s used. Perhaps VLA initialization is getting rearranged in a way that makes that fact non-obvious to the code generator? If n were initialized before use, moving the call to f() above the declaration of a would clearly be wrong, but this program produces undefined behavior.

Related

Warning: may be used uninitialized in this function

Hitting below warning with new gcc version 6.X
Warning: 'temp' may be used uninitialized in this function [-Wmaybe-uninitialized]
Code:-
int temp;
if (logcat (MSPRO_P->regs[test],
byte, &temp, test) == FALSE){
memErrorMsgHistoryVa (MSPRO_MEMP, "Invalid Data Count 0 value");
MSPRO_P->flashCmdError = TRUE;
}
gcc isn't supposed to warn about passing a pointer to an uninitialized variable to a function it doesn't know anything about (the assumption is that the function will initialize it). So I'm pretty sure that gcc knows things about logcat and the uninitialized use is detected in there. Maybe it got inlined or such.
Example:
$ cat > foo.c
static int
bar(int *a)
{
return *a + *a;
}
int
foo(void)
{
int x;
int y = bar(&x);
return x + y;
}
$ cc -Wall -c foo.c
$
Here, despite it being blindingly obvious to humans, gcc doesn't actually know what happens inside the function bar. So no warning.
Let's help gcc to understand what's going on:
$ cc -O1 -Wall -c foo.c
foo.c: In function ‘foo’:
foo.c:4:12: warning: ‘x’ is used uninitialized in this function [-Wuninitialized]
return *a + *a;
~~~^~~~
foo.c:10:6: note: ‘x’ was declared here
int x;
^
$
Just turning on optimization helped gcc to see what's going on (probably some inlining happened).
From the minimal piece of code you've shown and the warning message, where it looks like you cut out the bit that actually tells you exactly where in your code the problem happens, I conclude that the problem is in your logcat function.
temp is uninitialized after int temp;.
logcat (MSPRO_P->regs[test], byte, &temp, test)
Since a pointer to temp is passed to the function, we, as programmers can guess that this function is supposed to initialize temp. But that is very difficult, if not impossible, for the compiler to assert with absolute certainity, specially when that function is in separate translation unit. From compilers perspective, there is no easy way to tell whether logcat will write to *temp or read it first in uninitialized state. And that's why the warning.
The easiest way to get rid of this warning is assign some initial value to temp, like:
int temp = 0

Why does this code print addresses?

Why didn't I get a compile time error while accidentally printing only one dimension of a 2D array?
#include <stdio.h>
void main() {
int i;
int arr[2][3] = { 1, 2, 3, 4, 5, 6 }; //<- Declared a 2D array
for (i = 0; i < 6; i++) {
printf("%d\n", arr[i]); // <- Accidently forgot a dimension
}
}
I should have received a compile time error but instead I got a group of addresses! Why? What did arr[0] mean in this context to the compiler?
An expression with array type evaluates to a pointer to the first array element in most contexts (a notable exception, among others, is the sizeof operator).
In your example, arr[i] has array type. So it evaluates to a pointer of type int (*)[] (a pointer to an array). That's what's getting printed. Printing a pointer with %d is undefined behavior, because printf() will read the pointer as if it was an int.
Felix Palmen's answer explains the observed behavior.
Regarding your second question: the reason why you don't get a warning is you did not ask for them.
Compilers are notoriously lenient by default and will accept broken code including obvious undefined behavior. This particular one is not obvious because printf() accepts any number of extra arguments after the initial format string.
You can instruct your compiler to emit many useful warnings to avoid silly mistakes and detect non obvious programming errors.
gcc -Wall -Wextra -Werror
clang -Weverything -Werror
option /W3 or /W4 with Microsoft Visual Studio.
gcc and clang will complain about the sloppy initializer for array arr. It should read:
int arr[2][3] = { { 1, 2, 3 }, { 4, 5, 6 } };
The print loop is indeed surprising, did you really mean to print the array with a single loop?
Note also that the standard prototype for main without arguments is int main(void).

Purpose of casting a struct pointer to void without using the result [duplicate]

This question already has answers here:
Why cast an unused function parameter value to void?
(2 answers)
Closed 6 years ago.
I am trying to make sense of the following bit of C code.
static unsigned
parent(const struct binheap *bh, unsigned u)
{
(void)bh;
return (u / 2);
}
What could the purpose of (void)bh; be? It is not assigned to anything and should not have an effect on the output. The only purpose I can think of might be as a kind of an assert against a null pointer perhaps.
For context, that snippet is from the original implementation of a B-heap. That code tends to be rather too clever in other places as well, e.g. doing for (unsigned n = 2; n; n += n) { to break at n = 65536.
(void)bh; has no effect in the generated code. However, with many compilers it will prevent the compiler from issuing a warning about the parameter bh not being otherwise used in the function, and that was almost certainly the intent of the programmer. bh being a struct pointer is irrelevant; if this technique works at all, it will work regardless of the type of the unused parameter.
C++ has a more elegant way to accomplish this, allowing you to omit the variable name for any argument you don't need --
static unsigned
parent(const struct binheap *, unsigned u)
{
return (u / 2);
}
-- but C doesn't support this. Some compilers have extensions for the same purpose that are, if not so elegant, at least more self-describing, e.g. GCC's
static unsigned
parent(const struct binheap *bh __attribute__((unused)), unsigned u)
{
return (u / 2);
}
The (void)bh; trick is the only technique for suppressing unused-parameter warnings that uses only the facilities of ISO C; on the other hand, it's not guaranteed to work, the warnings a compiler emits are entirely up to that compiler, so you're already in implementation-defined territory no matter what you do.
This is simply to avoid the compiler warning against an unused variable. Without the cast there in place, you compiler will (try to) warn you that you have an unused variable in your code.
This is typically done to avoid compiler warnings. For example, if compiling with -Wall -Wextra in gcc, it will warn you that you're not using bh IF you do not make the cast to void.
Because compiler warning
Some compilers throw warning when a variable is unused within the function. See below
#include <stdio.h>
void hello(int a, int b)
{
int i = b + 1;
printf("hello %d\n", i);
return;
}
int main(void)
{
hello(10, 20);
return 0;
}
Compiling it as below to see the warning
$ gcc -Wunused-parameter a.c
a.c:3:16: warning: unused parameter 'a' [-Wunused-parameter]
void hello(int a, int b)
^
1 warning generated.

Why doesn't gcc o warn when size of array is uninitialized in this code?

Okay, so this is a stripped down variant of a bug I had. The bug was that I initialized an array using a variable that wasn't initialized. Earlier I used a function to declare the number of elements using a function, but after a cleanup I forgot about it and moved all declarations to the top of the function.
I used the flags -std=c99 -Wall -Wextra -pedantic -O, and usually gcc warns about values being used before they are uninitialized, but in this specific case it didn't. So, my question is:
Is this a bug in gcc or is it possible for f(&n) to post-initialize the array size in some weird way?
#include <stdio.h>
void f(int * x) {
*x = 8;
}
int main(void) {
int n;
float a[n]; // Compiler should warn that n may contain garbage
a[7] = 3.1415;
printf("%f\n", a[7]);
f(&n); // Removing this causes the compiler warn as expected
return 0;
}
EDIT: It may be this gcc bug?
GCC is accepting float a[n] as a variable-length array. It should, however, warn you that n contains garbage when it’s used. Perhaps VLA initialization is getting rearranged in a way that makes that fact non-obvious to the code generator? If n were initialized before use, moving the call to f() above the declaration of a would clearly be wrong, but this program produces undefined behavior.

Array of pointers problem

I have tried this example of array of pointers. I am getting the error "Illegal initialisation in function main"
int main()
{
int a[]={1,2,3,4,5};
int b[]={1,2,3,4,5};
int c[]={1,2,3,4,5};
int *p[3]={a,b,c};
int i;
clrscr();
for(i=0;i<3;i++)
printf("%d - %u\n",*p[i],p[i]);
getch();
}
If I use static int instead of int in array declarations, it works fine. Can any one tell me the effect of static here. Thanks a lot.
In gcc you see warnings about this if you use the -pedantic flag.
But this is apparently something that has changed in the standard, in C90 it say:
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
and it was not allowed as the p array is an aggregate type, but in C99 we have:
All the expressions in an initializer for an object that has static
storage duration shall be constant expressions or string literals.
This compiles fine with gcc and gcc -ansi. gcc -ansi -pedantic however gives the following warning:
blackjack.c: In function ‘main’:
blackjack.c:8: warning: initializer element is not computable at load time
blackjack.c:8: warning: initializer element is not computable at load time
blackjack.c:8: warning: initializer element is not computable at load time
Whereas line 8 is:
int *p[3]={a,b,c};
As I see it the problem is that at the time a, b, and c would be stored in p, they don't exist yet. That's because they will be put on the stack and the position on the stack depends on things outside the scope of a function. To clarify this, 'load time' means the time the program is loaded into memory, not the time it is already in execution. (Don't ask me why/how it works anyway)
try:
printf("%d - %u\n",*(p[i]),p[i]);
although I have a feeling you're trying to do something more like:
int a[]={1,2,3,4,5};
int b[]={1,2,3,4,5};
int c[]={1,2,3,4,5};
int *p[3]={a,b,c};
int i;
clrscr();
for(i=0;i<sizeof(p)/sizeof(int*);i++) {
for (int j =0; j < sizeof(a)/sizeof(int); j++) {
printf("%d - %u\n",(p[i])[j],p[i]);
}
}
getch();
The rules are pretty simple.For static objects the initialization list should be constant.No such restriction exists for the elements that will be allocated space on stack.
It appears logical too,as the static objects need to be written in the data section and the compiler must be able to resolve their values beforehand.
On stack memory is allocated once the function in question(main) is called.So no problem there.I don't know why the opposite behavior on turbo-c.
on gcc this happens:(on compiling with gcc -Wall prog.c
int *p[]={a,b,c} //works fine
static int *p[]={a,b,c} //oops blunder

Resources