different initializ and sign pointer value in global and function - c

I know I will get many down grade regarding this question, but I still write following test code:
int *gPtr;
//I know I can NOT write below code line, but I need know WHY
gPtr = NULL;//or some other value which I want to init it
//int *gPtr = NULL; //this line should be OK
int main (void)
{
int *ptr;
ptr = NULL;
return 0;
}
The global *gPtr during compile will output error:
ptr.c:4:1: warning: data definition has no type or storage class [enabled by default]
ptr.c:4:1: error: conflicting types for ‘gPtr’
ptr.c:3:6: note: previous declaration of ‘gPtr’ was here
ptr.c:4:8: warning: initialization makes integer from pointer without a cast [enabled by default]
However, in the function, I did same code, but no compile error/warning, I would like to know:
what is the different between sign a value in global and function.
why compiler do NOT allow me sign value in global area.
what is different between int a = 0; and int a; a=0;//no other code between these two sentences
please give me advise for above three questions according to the compiler view(or you think it should have other explanation in some others view like coding standard?)

You can define a global variable with an initial value:
int *gPtr = NULL;
But you cannot do an assignment outside of a function scope.
The compiler (well, at least my clang compiler) actually interprets
gPtr = NULL;
in the global scope as
int gPtr = NULL;
which causes similar warnings and a conflicting types error:
warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
gPtr = NULL;
^~~~
error: redefinition of 'gPtr' with a different type: 'int' vs 'int *'
note: previous definition is here
int *gPtr;
Global variable without an explicit initial value are automatically initialized
to zero, therefore in your case
int *gPtr;
would be sufficient (as #WhozCraig already commented above).

This compiles fine:
#include <stdio.h>
/* int *gPtr; */
/* gPtr = NULL; */
int *gPtr = NULL;
int main (void)
{
int *ptr;
ptr = NULL;
return 0;
}
I suspect you had one of two problems. Firstly, you can't declare gptr, then assign NULL to it, and then do a int *gptr = NULL (which does the first two combined); hence I commented out the first two. You need one or the other. Secondly your line int *gPtr = NULL; was missing a semicolon.

Related

Array type safety function arguments accessed with compound literal

There is a method which is defined in this manner:
void corruption(int (*idata[1]), bool (*flags[3]), bool* (*finfo[2]), int* (*error[1]));
I am trying to pass information to it using compound literals while also respecting type-safety definition, but I have a problem with this.
Argument (*idata[1]) is information which is being checked.
Argument (*flags[3]) are information which suggest the method what to do
Argument *(*finfo[2]) are information which are updated by the algorithm changing the original value
Argument *(*error[1]) are information which are updated by the algorithm changing the original value
I do not know how to pass anything to this function via compound literals without producing errors or unwanted behaviour. The reason why I want to try and do this with a compound literal is because I am trying to avoid assigning the information to separate variables since there are variables which already exist in code. I've tried writing this, but of course it does not work.
int data = 5151;
bool f1_flag = false;
bool f2_flag = false;
bool f3_flag = true;
bool* f1_info = points to some variable;
bool* f2_info = points to some variable;
int error_code = 0;
corruption
(
&(int(*)){ &(int[]){data} },
&(bool(*)){ &(bool[]){f1_flag, f2_flag, f3_flag} },
&(bool []){ &(bool(*)){ &(bool[]){f1_info, f2_info } } },
&(int []) { &(int[]){error} }
);
Compiler warnings which I receive for argument 1 and 2 are:
/* warning: initialization of 'int *' from incompatible pointer type 'int (*)[1] */
/* warning: initialization of '_Bool *' from incompatible pointer type '_Bool (*)[3] */
Of course argument 3 and 4 produce warning as well and cause segmentation fault.
I think you do not understand the types well.
void corruption(int *idata[1], bool *flags[3], bool **finfo[2], int **error[1]);
void foo(void)
{
int data = 5151;
bool f1_flag = false;
bool f2_flag = false;
bool f3_flag = true;
bool *f1_info = &f1_flag;
bool *f2_info = &f2_flag;
int error_code = 0;
corruption
(
(int *[]){&data},
(bool *[]){&f1_flag, &f2_flag, &f3_flag},
(bool **[]){&f1_info, &f2_info},
(int **[]){&(int *){&error_code}}
);
}

conflicting type for funct in C

I am trying to run the code below and i am getting the error messages below.
Program:
int main()
{
int (*res)[3],i;
res=func();
}
int (*func())[3]
{
static int arr[3][3]={1,2,3,4,5,6,7,8,9};
return arr;
}
Error:
PointerTo1D.c: In function ‘main’:
PointerTo1D.c:6:5: warning: assignment makes pointer from integer without a cast [enabled by default]
res=func();
^
PointerTo1D.c: At top level:
PointerTo1D.c:11:7: error: conflicting types for ‘func’
int (*func())[3]
^
PointerTo1D.c:6:6: note: previous implicit declaration of ‘func’ was here
res=func();
Could someone please help me out here???
res is a pointer to an array with 3 elements of int
int (*func())[3]: func is a function which returns a pointer to array with 3 elements of int
Because there is no prototype for function func() you got:
warning: implicit declaration of function 'func'
res=func();
which means that compiler use default prototype int func().
There is next warning:
warning: assignment makes pointer from integer without a cast [enabled by default]
res=func();
because default prototype is used, compiler assumes that function func() returns int which is than assigned as a pointer to res which is the pointer
When code for function func() is reached you get error:
error: conflicting types for 'func'
int (*func())[3]
Solution is to provide proper prototype before main.
int (*func())[3];
int main()
{
...
}
Update: There is also warning:
warning: missing braces around initializer [-Wmissing-braces]
static int arr[3][3]={1,2,3,4,5,6,7,8,9};
It is better to use:
static int arr[3][3]={{1,2,3}, {4,5,6}, {7,8,9}};
You have to change your code to
int** func() //change here
{
static int arr[3][3]={1,2,3,4,5,6,7,8,9};
return arr;
}
and
int** func(); //forward declaration
int main()
{
int ** res = NULL,i = 0; //change here
res=func();
return 0;
}
Any function you call from your main() should either be defined before main() or atleast have a forward declaration before main() so that the comipler has a way to know the function signature before the function is used (called).
Note: Usually, it's not a good practice to use static for this purpose. Dynamic memory allocation (malloc()/calloc()) is designed exactly for this purpose.
First if you want to return a pointer do like this :
(int **)func() {
...
return arr;
}
Then define res like this :
int ** res;
res = func();
If a function is called without a declaration being visible, it is assumed to be old-style declared, with external linkage, and returning an int in C89:
extern int func();
The empty parentheses (an old-style declaration) mean: No argument checking required, function takes fixed number of default-promoted arguments.
In C99, implicit declarations have been removed, Gcc warns about them by default, but sticks to the old behaviour, probably for backward compatibility. They can be turned into errors for example with gcc -std=c99 -pedantic-errors, or gcc -std=gnu89 -Werror=implicit-function-declaration if you want to stick to GNU89 (what I suspect was specified from the warnings given).
To fix the problem, the function needs at least to be declared before use:
int (*func())[3];
int main() {
func();
}
This still uses old-style declarations, marked obsolescent in all C standards, I'd suggest using prototypes to ensure argument checking:
int (*func(void))[3];
int main(void) { /* ... */ }

Global variable does not take new value

I was making a simple C program
#include<stdio.h>
static int a;
a = 5;
int main()
{
printf("%d",a);
return 0;
}
Compiler error: "non static declaration of 'a' follows static declaration"
What does this error mean?
what this error log means?
It is a little tricky: what looks like an assignment
a = 5;
is treated as
int a = 5;
due to an old C rule that allowed you to declare int variables and int-returning functions without specifying their type explicitly (this is definitely not a good idea in the modern version of C).
Note that this is treated as a declaration with an implicit int only in the scope outside a function body.
You can fix it by combining the declaration with initialization, like this:
static int a = 5;
Outside a function you can only declare variables, you cannot have actual code statements.
a = 5;
is being interpreted as another declaration, when your intent I think is to write some code.
instead declare and initialise a at the same time
static int a = 5;
Your first declaration of a is static (ahas internal linkage).
The second declaration is not static (a has external linkage). Yes, a = 5; is a declaration with implicit type int in this case.
Both do not agree.
Btw. for functions this would be o.k. because the second declaration would "inherit" the internal linkage.
We cannot write any assignment statement globally. For example:
#include <stdio.h>
static int i=10; //Initialization statement
i=25; //Assignment statement
int main(){
printf("%d",i);
return 0;
}
Output: Compilation error
Note: Assigning any value to the variable at the time of declaration is known as initialization while assigning any value to variable not at the time of declaration is known assignment.
You can't set value as you did it: a = 5; before main(...). See code below:
static int a = 1; //default = 0;
int main()
{
printf("a = %d\n", a);
a = 2;
printf("a = %d\n", a);
return 0;
}
Output:
a = 1
a = 2
A = 5 is considered as an attempt to create another variable called a. You should put the = 5 after static int a.
Static int a = 5;
Just a little modification to your code will help you to understand it.
#include<stdio.h>
//static int a; //comment this statement
a = 5;
int main()
{
printf("%d",a);
return 0;
}
now compile this code [please enable your compiler's warnings]
Then you will get a warning something like this
data definition has no type or storage class [enabled by default]
So now try to understand this warning it means that compiler treat statement a=5 as a definition but without data type. But compiler unable default data type that is int.
so this statement is equivalent to
int a=5;

Error compiling pthreads, pthread create says struct for multi argument pass is wrong type

I'm trying to compile but getting the errors
error: expected expression before 'void'
warning: passing argument 3 of 'pthread_create' from incompatible pointer type [enabled by default] used [-Wunused-but-set-variable]
I type casted the struct to void* so it should work.
In the global variable section I have
struct threadArgs
{
char** str;
int length;
};
struct threadArgs arguments;
The lines around the error are here
arguments.str = str;
arguments.length = linesRead;
for(int i = 0; i < lettersInAlpha; i++)
errCode[i] = pthread_create(&letter[i], NULL, &findMatch, (*void)&arguments);
the prototype for findMatch is void findMatch(char **str, const int length);
Also I think I'm doing the right thing by passing the arrays address, right?
Basically any code can be changed, so findMatch() can be modified as needed.
Your function must be conforming to the requirements of pthreads as a valid thread-proc. Part of the compliance is the signature. it must be of the form void *func(void*). in other words your function must:
return void*
take a single void* parameter.
The argument address you provide at the end is passed to your thread proc, and you're responsible for unpacking your own parameters from there.
Trying to minimize the changes you need for findMatch, declare your thread function like this:
void * findMatch(void* pv)
{
struct threadArgs * argsp = pv;
char **str = argsp->str;
const int length = argsp->length;
// the rest of your code.
return NULL;
}
Note: your code hints at something else that may be an issue. arguments is a global. This means that once you start a thread, if you modify arguments for preparation for the next thread, you have created a race condition where your modifications will potentially race with the initial thread's access of that memory. This isn't an issue in your code as-is, because you make no modifications to arguments from thread-to-thread creation. But if you ever do, consider allocating a separate arguments variable to be sent to each thread, so that thread "owns" it, and only it.

Problem with the following code

I want to the know the problems with the code presented below. I seem to be getting a segmentation fault.
void mallocfn(void *mem, int size)
{
mem = malloc(size);
}
int main()
{
int *ptr = NULL;
mallocfn(ptr, sizeof(ptr));
*ptr = 3;
return;
}
Assuming that your wrapper around malloc is misnamed in your example (you use AllocateMemory in the main(...) function) - so I'm taking it that the function you've called malloc is actually AllocateMemory, you're passing in a pointer by value, setting this parameter value to be the result of malloc, but when the function returns the pointer that was passed in will not have changed.
int *ptr = NULL;
AllocateMemory(ptr, sizeof(ptr));
*ptr = 3; // ptr is still NULL here. AllocateMemory can't have changed it.
should be something like:
void mallocfn(void **mem, int size)
void mallocfn(int **mem, int size)
{
*mem = malloc(size);
}
int main()
{
int *ptr = NULL;
mallocfn(&ptr, sizeof(ptr));
*ptr = 3;
return;
}
Because you need to edit the contents of p and not something pointed b p, so you need to send the pointer variable p's address to the allocating function.
Also check #Will A 's answer
Keeping your example, a proper use of malloc would look more like this:
#include <stdlib.h>
int main()
{
int *ptr = NULL;
ptr = malloc(sizeof(int));
if (ptr != NULL)
{
*ptr = 3;
free(ptr);
}
return 0;
}
If you're learning C I suggest you get more self-motivated to read error messages and come to this conclusion yourself. Let's parse them:
prog.c:1: warning: conflicting types for built-in function ‘malloc’
malloc is a standard function, and I guess gcc already knows how it's declared, treating it as a "built-in". Typically when using standard library functions you want to #include the right header. You can figure out which header based on documentation (man malloc).
In C++ you can declare functions that have the same name as already existing functions, with different parameters. C will not let you do this, and so the compiler complains.
prog.c:3: warning: passing argument 1 of ‘malloc’ makes pointer from integer without a cast
prog.c:3: error: too few arguments to function ‘malloc’
Your malloc is calling itself. You said that the first parameter was void* and that it had two parameters. Now you are calling it with an integer.
prog.c:8: error: ‘NULL’ undeclared (first use in this function)
NULL is declared in standard headers, and you did not #include them.
prog.c:9: warning: implicit declaration of function ‘AllocateMemory’
You just called a function AllocateMemory, without telling the compiler what it's supposed to look like. (Or providing an implementation, which will create a linker error.)
prog.c:12: warning: ‘return’ with no value, in function returning non-void
You said that main would return int (as it should), however you just said return; without a value.
Abandon this whole idiom. There is no way to do it in C without making a separate allocation function for each type of object you might want to allocate. Instead use malloc the way it was intended to be used - with the pointer being returned to you in the return value. This way it automatically gets converted from void * to the right pointer type on assignment.

Resources