What is wrong with this header file? - c

I'm fairly new to C and am starting to learn header files. Whilst using my header I'm getting an error saying invalid type argument of '->' (have struct dirent). I don't understand what this means, I read here that the second argument to -> must be a pointer, so I tried to add a * to it (ent->*d_name) however then I get the error unexpected token *, how can I fix this?
#ifndef UTILIS_H_INCLUDED
#define UTILIS_H_INCLUDED "utilis.h"
#include <stdio.h>
#include <dirent.h>
char *connect(const char *pattern)
{
struct dirent ent;
char *d_name;
DIR *mgt = opendir("\\\\example\\windows7apps");
while ((ent = readdir(mgt)) != pattern)
{
puts(ent->d_name);
}
}
#endif

I read here that the second argument to -> must be a pointer,
That's wrong, the "first" argument, or, actually, the operand of the -> operator should be of pointer type.
In your case, ent is not a pointer type, so you cannot use the pointer member dereference operator ->. (you could have used the member dereference operator . instead).
Actually, in your code, ent should be a pointer, as per the return type of readdir(). So you better correct the type of ent to be of struct dirent *, then you can make use of -> on ent.

usually header files only contain data definitions and function prototypes. Your function definition should almost certainly be in a C file.
If you look at the function readdir it returns a pointer to a struct dirent so your variable ent should be a pointer
struct dirent *readdir(DIR *dirp);
struct dirent *ent;
That will fix your error invalid type argument of '->' (have struct dirent)

Related

variable has incomplete type 'struct stat'

Hi trying to port some code and I'm not understanding the problem here,
getting the error - file.c:370:17: error: variable has incomplete type 'struct stat'
here is the code that is throwing up the error
int srcfd, destfd;
int nread;
char ifc[PROPERTY_VALUE_MAX];
char *pbuf;
char *sptr;
struct stat sb;
if (stat(config_file, &sb) != 0)
return -1;
pbuf = malloc(sb.st_size + PROPERTY_VALUE_MAX);
if (!pbuf)
return 0;
i've read various stackoverflow questions regarding incomplete types and defining in header files, but i don't understand how to implement any of that. i've tried moving the function about, declaring it in a header file and outside the function . but get the same error.
The structure struct stat is only declared but not defined.
struct stat sb;
So the compiler does not know how much memory an object of the structure type will require and whether indeed the structure has for example the data member st_size used in this statement
pbuf = malloc(sb.st_size + PROPERTY_VALUE_MAX);
^^^^^^^^^^
If the structure is defined in some header then you need to include the header in this translation unit.

fprintf() to a csv file in C by using pointer

I have a structure defined like this
typedef struct{
int id;
char* name;
float percentage;
}student_t;
And there is a function that is to print struct's member in this format
"id, name, percentage\n"
But the function takes in void* val_ref //struct ptr, void* fp
How do I make it work? The function looks like this (paramters are given cannot be modified)
void printStudentInfo(void* val_ref, void* fp)
{
if (val_ref != NULL)
{
fprintf(fp, "%d,%s,%.2f", val_ref->id, val_ref->name, val_ref->percentage);
}
}
But I can't compile, it says warning: deferencing void* pointer
error: request for memeber "id" in something not a struct or union
error: request for memeber "name" in something not a struct or union
error: request for memeber "percentage" in something not a struct or union
Do I have to do type cast for parameter val_ref?
fprintf(fp, "%d,%s,%.2f", val_ref->id, val_ref->name, val_ref->percentage); Over here, you need to cast val_ref to the type of pointer it actually is: (student_t *)val_ref and then fetch a member of the struct for e.g. ((student_t*)val_ref)->id.
When you have a void*, your program does not know the actual data type you are pointing to. Hence, it is illegal to try to fetch a member. Upon using a cast, you are explicitly saying that val_ref points to a student_t and you know what you are doing when you ask for a specific member.
However, there is no need to cast fp because the function fprintf has the first argument as FILE * in it's signature:
int fprintf(FILE *stream, const char *format, ...);
So, even if you pass a void * as the first parameter, the local variable stream is defined as a FILE * and that's what the function works with.

Why is this struct type "incomplete," and is it really solved with a pointer?

I have defined these structures.
struct http_req {
struct http_req_line rl;
}
struct http_req_line {
enum method {
OPTIONS,
GET,
HEAD,
POST,
PUT,
DELETE,
TRACE,
CONNECT
} method;
enum uri_type {
ASTERISK,
ABSOLUTEURI,
ABS_PATH,
AUTHORITY
} uri_type;
union req_uri {
char asterisk[1];
char absoluteURI[256];
char abs_path[256];
char authority[256];
} req_uri;
char http_ver[16];
};
When I compile the file this header file is included in (which compiles fine on its own), gcc gives me this
request_types.h:2:23: error: field ‘rl’ has incomplete type
struct http_req_line rl;
But changing the 2nd line of the header to
struct http_req_line *rl;
gets rid of this error. What causes this error, and does changing that member to a pointer really fix the problem, or just hide it from the compiler?
At the point where the compiler sees:
struct http_req {
struct http_req_line rl;
}
there is no information about what a struct http_req_line is. You need the structure definition for struct http_req to appear after the definition of struct http_req_line. You can use a pointer (to an incomplete type); you can't use a copy of the structure.
See the C11 standard §6.7.2.1 Structure and union specifiers:
A structure or union shall not contain a member with incomplete or function type (hence, a structure shall not contain an instance of itself, but may contain a pointer to an instance of itself), …
At the point where you are defining struct http_req, struct http_req_line is not known. The compiler does not know how big it is or what its alignment requirement is, so it does not know how much space to use for the rl member and cannot complete its definition of struct http_req.
If you want to embed a struct http_req_line inside a struct http_req, move the definition of struct http_req_line before the definition of struct http_req.
If you change rl to be a pointer, the type is not incomplete in the C sense because the compiler will know how big the pointer is and what its alignment requirement is. It does not need to know how big the structure it points to is in order to be able to plan space for the pointer rl.
You're seeing this error because you're attempting to define an instance of a struct before the struct itself has been defined. You need to define it first, then use it:
struct http_req_line {
enum method {
OPTIONS,
GET,
HEAD,
POST,
PUT,
DELETE,
TRACE,
CONNECT
} method;
enum uri_type {
ASTERISK,
ABSOLUTEURI,
ABS_PATH,
AUTHORITY
} uri_type;
union req_uri {
char asterisk[1];
char absoluteURI[256];
char abs_path[256];
char authority[256];
} req_uri;
char http_ver[16];
};
struct http_req {
struct http_req_line rl;
};
The reason that changing the member type to a pointer works is because you don't need to have the full struct definition to use a pointer to it. When the type definition is needed is when that pointer would be dereferenced.

Expected identifier error in C

For some reason I am getting the error:
expected identifier or '(' before 'wordlist'
in my header file (as well as the corresponding function definitions) for the two functions returning wordlist pointers.
With the following code:
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
typedef struct word{
char *string;
struct word* next;
}word;
typedef struct wordlist{
word *head;
word *tail;
}wordlist;
*wordlist populateList(FILE *file);
*wordlist encrypt(wordlist *wl, int rotation);
void toFile(wordlist *wl, char *outputFileName);
#endif
Can anyone tell me why this might be?
This is because when you declare a pointer, the asterisk must follow the type name, not precede it:
wordlist * populateList(FILE *file);
// ^
// |
// Here
If in populateList and encrypt you want to return a pointer to wordlist, the correct syntax is wordlist *, not *wordlist (it's exactly as it is everywhere else).
If you want to define or declare a variable you specify the type of the variable followed by the variable name. So if you want a variable of type wordlist you would use:
wordlist myVariable;
If you want to specify a variable to be a pointer to a variable type, you prefix the variable name with an asterisk so if you want a variable that is a pointer to a variable of type wordlist you would use:
wordlist *myVariable;
The reason why most experienced C programmers put the asterisk with the variable name is because of something like the following:
wordlist myVariable, *pVariable1, myVariable2, *pVariable2;
The above will create four variables. myVariable is of type wordlist. myVariable2 is of type wordlist. pVariable1 and pVariable2 are of type pointer to wordlist.
So the asterisk acts as a kind of adjective or qualifier or modifier for the variable name declaration indicating that the variable is not of the type specified but is instead a pointer to the type specified.
The combined variable definition is the same as the following four lines of definitions.
wordlist myVariable; // declares a variable of type wordlist
wordlist *pVariable1; // declares a pointer to a variable of type wordlist
wordlist myVariable2; // declares a variable of type wordlist
wordlist *pVariable2; // declares a pointer to a variable of type wordlist
Function definitions/declarations work similarly.
wordlist *myFunc (void) {
wordlist *myNew = malloc (sizeof(wordlist));
if (myNew) {
// set up myNew stuff
}
return myNew;
}
Edit: function pointers
You can also specify a variable that contains a function pointer. For instance for myFunc() above you might specify something like the following. Notice that I am using parenthesis to enforce a specific order of evaluation. What this says is that pFunc is a pointer to a function that does not accept arguments (void argument list) and which returns a pointer to a wordlist variable. There are rules about operator and modifier precedence in C however as expressions become more complicated, it is usually better to enforce an evaluation order using parenthesis. See Programs as Data: Function Pointers
wordlist *((*pFunc) (void)) = myFunc; // pointer to a function that returns a pointer to a wordlist

Pointers ABC. error: invalid type argument of unary ‘*’ (have ‘struct config’)

I have a basic problem. I should know enough about pointers by now. The way I see it configData is the first link in a linked list (of the type struct config) while procNames is a pointer to the first link in a linked list of the type struct config. So if I want to say that procNames is equal to configData then I need to access the pointer that points to configData which is *configData. Anyhow I think I am missing something. Anyone sees the problem? Also, I get the next error: error: invalid type argument of unary ‘*’ (have ‘struct config’)
struct config_line {
char name[MAX_WORD];
int time;
};
struct config {
struct config_line *lines;
int count;
};
//global variable
struct config configData;
//local variable
struct config *procNames;
//the problem (done locally)
procNames = *configData;
I think you want
procNames = &configData;
This sets the pointer procNames to the address of the structure configData.
You can access the elements using either
procNames->count
procNames->lines[i].name // Pointer to the 1st char of the name in the i'th config_line structure
or
configData.count
configData.lines[i].name
Remember that, since lines is itself a pointer, you'll need to allocate memory for each config_line structure:
struct config_line thisLine; // Declare a structure
procNames->lines = &thisLine; // Point to it
or
// Declare a pointer to an array of structures, allocate memory for the structures
struct config_line *linePtr = malloc(NUM_STRUCTS * sizeof(struct config_line));
procName->lines[i] = *linePtr; // Points to 1st structure in the array
Based on your description of what you are trying to do, you need to take the address of configData (write &configData on the last line). What you are trying to do on the last line is dereference configData, which the compiler will not let you do since configData is not a pointer (it does not store an address inside).
The error message is fairly clear on this. Unary * takes a single pointer as an argument, but the argument used of type struct config, and not a pointer.

Resources