I'm having trouble assigning a passing a pointer of struct to a function my code (put simply) is
struct userCom{
int x;
int y;
}
main(void){
struct userCom com;
userComFunction(com);
printf("%d", com.x);
}
userComFunction(struct userCom *return_type){
struct userCom temp;
temp.x = 10;
printf("%d", temp.x);
*return_type = temp;
}
It would print
10
11537460
Am I passing through the pointer wrong?
I cannot seem to figure out why com.x is not equal to 10
As others have pointed out, the problem is that you're passing the wrong type of argument to userComFunction. But the real problem is that your compiler isn't telling you that.
As of C90 (that's two standards ago), calling a function with no visible declaration was legal, and the compiler would make assumptions (often incorrect) about what the function actually looks like. When the compiler sees the call to userComFunction, it hasn't seen a declaration or definition for userComFunction, so it can't diagnose your error.
As of C99, calling a function with no visible declaration is a constraint violation, meaning that a compiler must at least warn you about it. C99 also dropped the "implicit int" rule, so you can no longer omit the return type in a function declaration; main should be declared with an int return type (not void!), and userComFunction, since it doesn't return anything, should be void.
You can either move the full definition of userComFunction above the definition of main, or you can leave the definition where it is and add a "forward" declaration:
void userComFunction(struct userCom *return_type);
int main(void) {
/* ... */
}
void userComFunction(struct userCom *return_type) {
/* ... */
}
When you do that, the compiler should let you know that your call:
userComFunction(com);
is incorrect. (The fix is to change com to &com.)
You should also use gcc's command-line options to enable more warnings. For example:
gcc -std=c99 -pedantic -Wall -Wextra
-std=c99 says to enforce ISO C99 rules. -pedantic says to really enforce those rules. -Wall and -Wextra enable additional warnings.
If you want to assign 10 to x,then you should do it this way.
Here is the correct code-
struct userCom{
int x;
int y;
}
void struct userComFunction(struct userCom*);
main(void)
{
struct userCom com;
userComFunction(&com);
printf("%d\n", com.x);
}
userComFunction(struct userCom *return_type){
struct userCom temp;
temp.x = 10;
printf("%d\n", temp.x);
return_type->x= temp.x;
}
Related
main.h
struct tagname {
int m1;
int m2;
};
main.c
#include "main.h"
int main(void) {
struct tagname d1;
d1.m1 = 7;
struct tagname {
float s1;
float s2;
float s3;
};
struct tagname e1;
e1.s1 = 0;
}
I am using XC16 v1.60 (which I believe uses GCC v4.5.1 as the base) with -Wall, -Wextra, -Wshadow, and a host of other flags which I don't think are relevant, and I would have thought (hoped?) that the compiler would issue a warning here. What am I missing?
Edit: Apologies, I have updated the question with the extra detail desired.
C allows new declarations of identifiers in new scopes. When you declare a function or start a compound statement with {, that starts a new scope. Iteration and selection statements also start new scopes. Inside a new scope, a new declaration of an identifier generally hides the previous declaration. Since this is legal C, the compiler allows this.
In GCC 4.5.1, the documentation for -Wshadow says it warns “whenever a local variable shadows another local variable, parameter or global variable or whenever a built-in function is shadowed.” A structure tag is not a local variable or a built-in function.
Incidentally, the return type of main should be int except in special situations; using int main(void) or int main(int argc, char *argv), not void main(void).
EDIT: To try and make things easier for the kind souls trying to help me, here are a couple links that should make things more clear:
Pre-makefile repl
Post-makefile repl
A little background on the assignment: We are supposed to take a program we wrote last week and break up the separate functions into their own files and use a makefile to compile and link and all that stuff. This is my original program (basically, it reads a file of name number and stores them in a struct, then uses the command line arguments to search for a name).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct _data {
char* name;
long number;
};
int SCAN(FILE *(*input)) {
int lines = 0;
char word[50];
long num = 0;
while (1) {
fscanf(*input,"%s %ld",word, &num);
lines++;
if (feof(*input)) break;
}
return lines;
}
struct _data *LOAD(FILE *input, int size) {
char* line = NULL;
size_t len = 0;
int i=0;
rewind(input);
struct _data *book = calloc(size,sizeof(struct _data));
for (i = 0;i<size;i++) {
getline(&line, &len, input);
book[i].name = calloc(len+1,sizeof(char));
strcpy(book[i].name,strtok(line," "));
book[i].number = atoi(strtok(NULL, " "));
}
return book;
}
void SEARCH(struct _data *BlackBook, char *name, int size) {
int i;
for (i=0;i<size;i++) {
if (strcmp(name,BlackBook[i].name) == 0) {
printf("*******************************************\n");
printf("The name was found at the %d entry.\n",i+1);
printf("*******************************************\n");
break;
}
//If we reach the end of the array and name was not found
if (i == size-1) {
printf("*******************************************\n");
printf("The name was NOT found.\n");
printf("*******************************************\n");
}
}
}
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
//MAIN DRIVER ===================
int main(int argv, char** argc) {
int size;
char* filename = "hw5.data";
FILE *input = fopen(filename,"r");
size = SCAN(&input);
struct _data *phone_book = LOAD(input,size);
fclose(input);
//Check a name is given. If so, search
if (argv < 2) {
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
} else {
SEARCH(phone_book, argc[1], size);
}
FREE(phone_book,size);
return 0;
}
When I make my makefile, I can get the SCAN and LOAD functions to work appropriately. But, when I try to put either SEARCH or FREE into their own files, my compiler freaks out and I get warnings like:
In file included from hw6-free.c:1:0:
hw6-free.h:9:18: warning: ‘struct _data’ declared inside parameter list
void FREE(struct _data *BlackBook, int size);
^
hw6-free.h:9:18: warning: its scope is only this definition or declaration, which is probably not what you want
hw6-free.c:3:18: warning: ‘struct _data’ declared inside parameter list
void FREE(struct _data *BlackBook, int size) {
^
hw6-free.c:3:6: error: conflicting types for ‘FREE’
void FREE(struct _data *BlackBook, int size) {
^
In file included from hw6-free.c:1:0:
hw6-free.h:9:6: note: previous declaration of ‘FREE’ was here
void FREE(struct _data *BlackBook, int size);
^
hw6-free.c: In function ‘FREE’:
hw6-free.c:6:5: error: invalid use of undefined type ‘struct _data’
free(BlackBook[i].name);
^
hw6-free.c:6:19: error: dereferencing pointer to incomplete type ‘struct _data’
free(BlackBook[i].name);
^
Makefile:20: recipe for target 'hw6-free.o' failed
make: *** [hw6-free.o] Error 1
And reading through it, it looks like the fact my program takes a struct as an argument is my main problem? My 'post-makefile' program looks like:
#include "hw6-main.h"
int main(int argv, char** argc) {
int size;
char* filename = "hw5.data";
FILE *input = fopen(filename,"r");
size = SCAN(&input);
struct _data *phone_book = LOAD(input,size);
fclose(input);
//Check a name is given. If so, search
if (argv < 2) {
printf("*******************************************\n");
printf("* You must include a name to search for. *\n");
printf("*******************************************\n");
} else {
SEARCH(phone_book, argc[1], size);
}
FREE(phone_book,size);
return 0;
}
And my makefile looks like:
DEP = hw6-scan.o hw6-load.o hw6-search.o hw6-free.o hw6-main.o
HDR = hw6-scan.h hw6-load.h hw6-search.h hw6-free.h hw6-main.h
NAME = output
all: $(NAME)
output: $(DEP) $(HDR)
gcc $(DEP) $(HDR) -o $(NAME)
hw6-scan.o: hw6-scan.c
gcc -c hw6-scan.c
hw6-load.o: hw6-load.c
gcc -c hw6-load.c
hw6-search.o: hw6-search.c
gcc -c hw6-search.c
hw6-free.o: hw6-free.c
gcc -c hw6-free.c
hw6-main.o: hw6-main.c
gcc -c hw6-main.c
clean:
rm *.o *.gch *.out output testfile
As an example, my hw6-free.c and hw6-free.h look like:
#include "hw6-free.h"
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
and
#include <stdio.h>
#include <stdlib.h>
void FREE(struct _data *BlackBook, int size);
respectively.
And, finally, I defined the struct in the hw6-load.h file, along with a function prototype. Is that also a problem? Should I be defining it elsewhere?
I am SO SORRY for the long post, but I have been working on the for 10 hours and I'm about to throw my computer of a cliff.
THANK YOU FOR YOUR HELP STACK OVERFLOW!
This is an in-depth explanation of the details. It might be a bit too much, but if you keep reading, you may get a much deeper understanding of the language than if you just learn to write code that your compiler is ok with.
You are using your struct before you have declared it. Keep in mind that an #include is just a fancy way of telling your compiler: "Please, paste the contents of this .h file at this spot." The result of this pasting must read like valid code to the compiler.
It is true that the compiler's error message looks a bit weird. It certainly does not say "You used struct _data before you declared it". The reason for this is, that structs are implicitly declared at their first use. So, if you declare a variable with struct foo* bar; and the compiler has never seen a struct foo before, it will immediately consider struct foo as being declared, and a pointer variable to this struct foo of unknown size and shape will be defined. Likewise, when your compiler sees the function declaration
void foo(struct bar *baz);
it sees that it doesn't know a struct bar and implicitly declares one. Because this struct declaration happens inside a function declaration, the resulting type is declared local to the declaration at hand. As such, it is impossible for calling code to pass an argument of the correct type into this function, or even to implement the function in a separate statement. Such a function declaration is always useless. This is what the warning text "its scope is only this definition or declaration, which is probably not what you want" means: The compiler writers knew that such a declaration is bullshit, but it's legal C as far as the standard is concerned, so they compile it, but warn about it.
Ok, let's get to the actual error message. As the compiler tells you, the struct _data was only declared for the function declaration at hand. When your compiler later sees the function implementation, it stumbles across the undeclared struct _data a second time. Again, it implicitly declares a local struct type which is distinct from the previously implicitly declared type. Because those two implicitly declared types are distinct, so are the signatures of the declared functions. However, C mandates that a function can only have one signature, so the compiler produces the error "conflicting types for ‘FREE’".
You can try this out with this simple code:
void foo(struct bar* baz); //warning: local declaration of `struct bar`
void foo(struct bar* baz); //repeated warning + conflicting types error
So, how to fix this?
Simple. Declare your struct before you use it. That way you avoid its implicit declaration. The following code compiles fine:
struct bar; //global declaration of `struct bar`
void foo(struct bar* baz); //`struct bar` is known and the global declaration is used
void foo(struct bar* baz); //same as above, because this uses the same global declaration of `struct bar`, this redeclaration of `foo()` is ok
The declaration of the struct _data belongs into the header file that declares the functions which use struct _data as arguments.
Idiomatic declarations
Usually, types are declared with a typedef. This allows the code to omit the struct keyword when declaring variables. This takes one of two idiomatic forms:
To have a type with public members (pure data, no object in the OO sense), put the struct definition into the header:
typedef struct foo //`struct foo` is declared implicitly here
{ //it is also defined (= inner details are given) right here
int bar; //its member variables are defined
} baz; //this concludes the typedef, giving `struct foo` a second name
//`struct foo` and `baz` are now equivalent.
Usually, the two names will be the same or very similar, so the cleaned definition looks like this:
typedef struct foo {
int bar;
} foo;
//declarations of the functions that use `struct foo`
...
If the type is an object that should keep its data members to itself, the declaration and definitions are split like this:
Inside foo.h:
typedef struct foo foo; //declare that `struct foo` == `foo` exists, but don't give details
//declare the functions working on a `foo`
void foo_bim(foo* me);
void foo_bam(foo* me, ...);
...
Inside foo.c:
#include "foo.h" //so that the compiler may check that the function declarations in the header agree with the implementations in this file
struct foo { //define the size and shape of `struct foo` == `foo`
int bar;
};
//now only this file knows how a `struct foo` actually looks like
//implement the member functions of `foo`
void foo_bim(foo* me) {
...
}
void foo_bam(foo* me, ...) {
...
}
Note that the typedef ... non-struct-name; is purely optional in both cases, and there are quite a few programmers who want to see the struct keyword wherever a struct is used (like a certain Mr. Torvalds). These programmers simply leave off the typedef ... non-struct-name; part, otherwise they use the idioms above in the same way. I have described the full-featured version here, to ensure that you'll not be surprised when you first see the typedef construct.
I'm not sure what you did. But to step back: keep clear in your mind the difference between declarations and definitions. A declaration shows a variable or function signature, but does not create any variables of that type or implement that function. A definition declares a new variable (of some type) or implements a function. A declaration of a type just states that it exists (basically). A definition of a type shows its structure and members.
So, a definition of your type would be:
struct _data {
char* name;
long number;
};
And a declaration of a function would be:
void FREE(struct _data *BlackBook, int size);
and a definition of a function would be:
void FREE(struct _data *BlackBook, int size) {
int i;
for (i=0;i<size;i++){
free(BlackBook[i].name);
}
free(BlackBook);
}
So here're the rules:
Only #include header files in other files, never #include source files.
If a type is needed in more than one file, put its definition into a header file and #include that header file in all source files that use the type.
If a function is used in more than one file, put the declaration of that function into a header file and #include that header file in all the source files that use the function, including the source file containing the definition of the function.
If you follow these rules you'll never run into duplicate definitions at link time: you can't have duplicate definitions if you link each source file only one time and no included file contains a definition.
Type declarations can be useful, and breaking some of these rules can be useful, but for the work you're doing that's probably not worth worrying about.
Try to put header of struct declaration at top of files which uses it and be sure you’ve imported the file which contains struct declaration.
I'm doing this code and can't find a way to compile. Tried Online compilers which each one of them gives a different reason for the error, my Dev++ says that
[Warning] non-static data member initializers only available with -std=c++11 or -std=gnu++11
Every online compiler and cant find an error on code either
#include <stdio.h>
#include <stdlib.h>
struct uninter
{
char nome[5] = {'L','U','C','A','S'};
int RU = 2613496;
}; struct uninter aluno;
int main() {
int i;
printf("\n Nome do Aluno: ");
for (i = 0; i < 5; i++ ){
printf( "%c\n", aluno.nome[i]);
}
printf("\n RU do aluno: %d \n ", aluno.RU);
system("pause");
return 0;
}
[Warning] non-static data member initializers only available with -std=c++11 or -std=gnu++11
The warning message you are receiving is because you are compiling your code with a C++ compiler. Probably with with -std=c++98 or -ansi or otherwise implicitly using the 1998 standard.
You are trying to create a default initializer for a member of a struct, which is a feature not added to C++ until the 2011 standard. To compile a C++ program with this feature without the compiler warning you about this, you need to pass in the -std=c++11 or -std=gnu++11 flags to the compiler command as the warning states.
If this is expected to be C code rather than C++ code, default initializers for structs are simply not a part of the language. You can initialize its member variables upon declaration of an object of that struct's type.
An example of how you might do this with a C compiler:
// definition of the struct
struct uninter
{
char nome[5];
int RU;
};
// declaration of an instance of an object of type struct uninter
struct uninter x = {{'L','U','C','A','S'}, 2613496};
// alternative declaration if using C99 standard with designated initializers
struct uninter y = {
.nome={'L','U','C','A','S'},
.RU= 2613496
};
in general, cannot initialize a struct contents in C in the definition of the struct. Suggest something similar to:
struct uninter
{
char nome[5];
int RU;
};
struct uninter aluno = {.nome = "LUCAS", .RU = 2613496};
The problem with the code is that it is using non-static data member intializers:
struct uninter
{
char nome[5] = {'L','U','C','A','S'};
int RU = 2613496;
}; struct uninter aluno;
... which is a C++11 feature, and therefore isn't portable unless you are using a C++11 (or later) compiler. (It might still compile under older compilers, if they have that feature enabled as a compiler-specific extension, but they are politely warning you that you can't expect it to compile everywhere)
If you don't want your program to require C++11 or later to compile, the easiest thing to do would be to rewrite it so that the struct's member variables are initialized via a different mechanism. For example (assuming your c tag is intentional) you could have an init-method do it for you:
struct uninter
{
char nome[5+1]; // +1 for the NUL/terminator byte!
int RU;
}; struct uninter aluno;
void Init_uninter(uninter * u)
{
strcpy(u->nome, "LUCAS");
u->RU = 2613496;
}
[...]
int main() {
int i;
Init_uninter(&aluno);
[...]
... or if you actually intended to specify/use a pre-C++11 version of C++, a default-constructor would do the trick a bit more gracefully:
struct uninter
{
uninter()
{
strcpy(nome, "LUCAS");
RU = 2613496;
}
char nome[5+1]; // +1 for the NUL terminator byte!
int RU;
}; struct uninter aluno;
In a series of articles, Dan Saks introduces a possible implementation of virtual functions in C. Relying more on static type-checking, this is a different approach as opposed to the solution of A.-T. Schreiner with void * pointers and dynamic type-checking.
Here is a stripped-down example without the vptrs and vtables of Saks' version (for the sake of simplicity, function pointers are just members of struct Base and struct Derived).
#include <stdlib.h>
#include <stdio.h>
typedef struct Base Base;
// Base "class"
struct Base {
int (*get_param)(Base const *self);
};
inline int Base_get_param(Base const *self)
{
return self->get_param(self);
}
typedef struct Derived Derived;
// Derived "class"
struct Derived {
int (*get_param)(Derived const *self);
int param;
};
Derived * Derived_new(int param)
{
Derived *self = malloc(sizeof(Derived));
if (!self) abort();
self->get_param = Derived_get_param;
self->param = param;
return self;
}
void Derived_delete(Derived *self)
{
free(self);
}
inline int Derived_get_param(Derived const *self)
{
return self->param;
}
int main()
{
Derived *d = Derived_new(5);
printf("%d\n", Derived_get_param(d));
printf("%d\n", Base_get_param((Base *) d)); // <== undefined behavior?
Derived_delete(d);
return 0;
}
The gist is the function call (and cast) Base_get_param((Base *) d). Does this mean that the function pointer int (*get_param)(Derived const *self) gets "implicitly cast" to int (*get_param)(Base const *self)? Am I exploiting undefined behavior here (according to the C99 and C11 standards) because of incompatible types?
I get the proper output both with GCC 4.8 and clang 3.4. Is there a situation where the above implementation might be broken?
There is a detailed answer here about function pointer casts and compatible types but I am not sure about this case.
This program does indeed invoke undefined behavior, you have a violation of strict aliasing rules here:
printf("%d\n", Base_get_param((Base *) d));
^^^^^^^^^
Strict aliasing rules make it undefined behavior to access an object through a pointer of a different type, although there is an exception for char* which we are allowed to use to alias without invoking undefined behavior.
Basically the compiler can optimize around the assumption that pointers of different types do not point to the same memory. Once you you invoke undefined behavior the result of your program becomes unpredictable.
Practically in other cases such as in this question I could not get the compiler to do the wrong thing but in other more complicated cases things may go wrong. See gcc, strict-aliasing, and horror stories for cases where it did cause issues. The article Type Punning, Strict Aliasing, and Optimization provides the following code:
#include <stdio.h>
void check (int *h, long *k)
{
*h = 5;
*k = 6;
printf("%d\n", *h);
}
int main (void)
{
long k;
check((int *)&k, &k);
return 0;
}
which violates strict aliasing and produces different outputs using -O1 Vs -O2.
Strict aliasing for gcc can be turned off using -fno-strict-aliasing and perhaps the author is making such an assumption although I could not find that in the article. This does disable some optimizations so it is not a costless flag.
Instead of declaring a function pointer typedef for a function, is it possible to get it from the function declaration?
Typically,
int foo(int x);
typedef int (*fooFunc)(int);
fooFunc aFunc;
What I want:
int foo(int x);
foo* aFunc;
I want to use it for dlsym:
foo* aFunc;
aFunc = dlsym(lib, "foo");
aFunc(x);
If I update foo and forgot to update fooFunc, or vice versa, that would be bad. Also, I may have many functions and it would be more work to maintain both the function declarations and the function pointer typedefs that are associated with those functions.
Conclusion:
AndreyT's answer is the most portable but if you code for gcc then typeof is a great solution.
If you are talking about a declaration specifically, i.e. a non-defining declaration of a function, you can remove the redundancy by defining a typedef-name for function type and using it in both cases - to declare the function itself and to declare a pointer to it, like this
typedef int FuncType(int); /* <- function type */
FuncType foo; /* <- declaration of `int foo(int)` */
FuncType *aFunc; /* <- definition of `int (*aFunc)(int)` */
I.e. typedef-names can be used in non-defining function declarations. However, you can't use a typedef name in function definition, meaning that later you'll still have to do
int foo(int x) /* <- no way to use the above `FuncType` here */
{
/* whatever */
}
which basically renders the above trick virtually useless.
Of course, this doesn't help you to generate a pointer from an existing non-modifiable function declaration, if that's your situation.
If you have gcc, typeof works.
Update
$ cat fxf.c
#include <stdio.h>
int main(int argc, char **argv) {
typedef __typeof__ (main) function_of_same_type_as_main_t;
function_of_same_type_as_main_t *f;
printf("main() called.\n");
f = main;
if (argc) f(0, NULL);
return 0;
}
$ /usr/bin/gcc -std=c89 -pedantic -Wall -Wextra -o fxf fxf.c
fxf.c:3: warning: unused parameter ‘argv’
$ ./fxf
main() called.
main() called.
Simple answer: no, that doesn’t work. foo is a specific function which has a prototype (int (int)). Using foo in the way you did would be a bit like using an int to declare another int:
4 x; // expect this to be the same as int x
That said, there might be compiler extensions which make that work. I know that the upcoming C++ standard will have the decltype keyword to allow that. Using that, the following might work (untested, since I don’t have a supporting compiler handy):
int foo(int x);
decltype(&foo) aFunc = dlsym(lib, "foo");
It is not possible. However, you can write some code that would generate a warning, so that you would catch type mismatch. The following code generates an assignment from incompatible pointer type warning.
#include <stdio.h>
int foo(int, int);
typedef int(*fooFunc)(int);
fooFunc myfunc;
int foo(int x, int y)
{
return 2*x + y;
}
int main(int argc, char **argv)
{
myfunc = foo;
printf("myfunc : 0x%x\n", (unsigned int)myfunc);
return 0;
}
Of course, this means you would have to write this test code where the foo function is visible, so this is still more code to add for each function type. The solution here is probably a code generator, that would generate a proper header file containing both functions and their associated typedefs
Not quite the same, but you can typedef the function and use it for both the prototype and the pointer.
typedef int fooFunc(int);
fooFunc foo;
fooFunc *aFunc;