The language is C.
Recently here I asked for and received help making the function qsort work for an array of structures.
I am now studying bit-fields and trying to make a program that uses a structure that uses another structure using bitfields and then sorting it out. But when I compile it, I get error at the compare function that "dereferencing pointer to incomplete type" and I had many trials again but still can't make it work. Can you folks help me?
Here's the code:
#include <stdio.h>
#include <stdlib.h>
int compare(const void * a, const void * b)
{
struct emp *orderA = (struct emp *)a;
struct emp *orderB = (struct emp *)b;
return (orderA->d.year - orderB->d.year);
}
int main()
{
int i;
struct date{
unsigned day : 5;
unsigned month : 4;
unsigned year : 12;
};
struct emp {
char name[10];
struct date d;
};
struct emp e[5];
for(i = 0; i < 5; i++)
{
scanf("%s %d %d %d", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year);
}
qsort(e, 5, sizeof(struct emp), compare);
for(i = 0; i < 5; i++)
{
printf("%s %d %d %d\n", e[i].name, e[i].d.day, e[i].d.month, e[i].d.year);
}
return 0;
}
Why this doesn't work
Since you've defined struct emp inside your main function, it only exists inside your main function.
As such, when you attempt to cast to struct emp* in your compare function, the type does not exist.
If you want this code to work, you should move
struct emp {
char name[10];
struct date d;
};
out of your main function and above your compare function.
Ideally you should move it into its own header file and include that.
The same applies to your struct date since it is used inside struct emp. So move
struct date{
unsigned day : 5;
unsigned month : 4;
unsigned year : 12;
};
out of your main function as well.
Scopes in C
Keep in mind as a general rule in C that any non-static identifier declared or defined inside a scope (meaning between a set of {}) is local to that scope and cannot be accessed outside of that scope.
Related
I have many programs where structs are defined. And each time, I have to create a function to print the members. For example,
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
void printMyStruct(myStruct myPeople) {
printf("%s\n",myPeople.name);
printf("%s\n",myPeople.address);
printf("%d\n",myPeople.zip);
}
int main()
{
myStruct myPeople={"myName" , "10 myStreet", 11111};
printMyStruct(myPeople);
}
I know that reflection is not supported in C. And so, I write these printing functions for each struct I defined.
But, I wonder if it exists any tricks to generate automatically these printing functions. I would understand that I have to modify a little bit these functions. But, if a part of the job is done automatically, it would be great.
(This example is simple, sometimes struct are nested or I have array of structs or some fields are pointers, ...)
You can of-course print structs, but expect a lot of non-readable output:
#include <stdio.h>
#include <ctype.h>
struct example {
int x;
int y;
char c;
};
#define NOT_PRINTABLE "Not Printable"
void print_structure(const char *structure, size_t size) {
for (size_t i = 0; i < size; i++) {
printf("%ld)\t%.2X: %.*s\n", i, structure[i],
(isprint(structure[i]) ? 1 : sizeof(NOT_PRINTABLE) - 1),
(isprint(structure[i]) ? &structure[i] : NOT_PRINTABLE));
}
}
int main(int argc, char **argv) {
struct example a;
a.x = 5;
a.y = 6;
a.c = 'A';
print_structure((char *)&a, sizeof(struct example));
return 0;
}
But the issue is that, it will print the structs as it is represented in memory. So 4 byte (32 bit) integer 1 will be represented with 4 bytes, not the char '1'.
And due to the way pointers work, you cannot make out if a member is a pointer or a non-pointer.
Another issue is that structures have padding to help with alignment, and better/efficent use of memory. So you would see a lot of 0x00 in the middle.
Remember that C is a compiled language.
let's consider to use https://copilot.github.com/. it's great.
this is what i have with copilot
typedef struct {
char name[128];
char address[1024];
int zip;
} myStruct;
//print struct myStruct >> auto generate by codepilot after you type a comment `print struct myStruct`
void printStruct(myStruct *s) {
printf("name: %s\n", s->name);
printf("address: %s\n", s->address);
printf("zip: %d\n", s->zip);
}
The below is my code. Compiler generates the errors as
#include<stdio.h>
struct Shelf{
int clothes;
int *books;
};
struct Shelf b;
b.clothes=5;
*(b.books)=6;
Compiler generates the errors as below for both statements b.clothes=5; and b->books=6; in above code.
error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘->’ token
I'm not a beginner at C and I believe that what I have written is correct. Kindly solve my problem
FIRST
You cannot do this
struct Shelf{
int clothes;
int books;
};
struct Shelf b;
b.clothes=5;
b.books=6;
In global scope
You can assign value inside a function
int main (void )
{
b.clothes=5;
b.books=6;
}
Or initializing values on declaration
struct Shelf b = { .clothes = 5, .books = 6 };
Moreover as you can see b is not a pointer so using -> is not correct: use . to access members of struct.
SECOND
Your struct has a pointer member book
struct Shelf{
int clothes;
int *books;
};
What you can do is to set it to the address of another variable, like
int book = 6;
struct Shelf b = { .clothes = 5, .books = &book };
Or allocate memory for that pointer like
int main (void )
{
b.clothes=5;
b.books=malloc(sizeof(int));
if (b.books != NULL)
{
*(b.books) = 6;
}
}
BTW I guess you want an array of books, so
int main (void )
{
b.clothes=5;
b.books=malloc(sizeof(int) * MAX_N_OF_BOOKS);
if (b.books != NULL)
{
for (int i=0; i<MAX_N_OF_BOOKS; i++)
b.books[i] = 6;
}
}
COMPETE TEST CODE
#include <stdio.h>
#include <stdlib.h>
struct Shelf
{
int clothes;
int *books;
};
int main(void)
{
struct Shelf b;
b.clothes = 5;
b.books = malloc(sizeof(int));
if (b.books != NULL)
{
*(b.books) = 6;
}
printf ("clothes: %d\n", b.clothes);
printf ("book: %d\n", *(b.books) );
}
OUTPUT
clothes: 5
book: 6
b is a struct, not a pointer, so -> is not correct.
It's like doing (*b).books, which is wrong.
struct Shelf{
int clothes;
int *books;
};
One data member of the struct is a pointer, however:
struct Shelf b;
is not a pointer, it is just a struct as I said before.
As for your question in comment:
b.clothes=5;
is correct. Also something like this would be ok:
int number = 6;
b.books = &number;
-> operator used to access of member of struct via pointer. b is not dynamically allocated so b->books=6; is wrong. You should first allocate memory for member books and then dereference it.
b.books = malloc(sizeof(int));
*(b.books)= 6;
To explain more, I have two structures-'first' and 'second' having common variables 'jack' and 'jill'. I want to print jack via a pointer based on if-else condition.
I understand at the time of printing I have to typecast the void pointer. But whether the pointer points to struct a or b is decided on run time.
It is a basic C code. How to overcome this?
Code
#include <stdio.h>
int main(void)
{
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
a first;
b second;
void *z;
if(1)
{
a* z;
z = &first;
printf("First one");
}
else
{
b* z;
z = &second;
printf("Second one");
}
printf("%d\n", z->jack);
return 0;
}
Error
prog.c:36:17: warning: dereferencing 'void *' pointer printf("%d\n", z->jack); prog.c:36:17: error: request for member 'jack' in something not a structure or union
You get a compiler warning since the compiler does not understand z->jack since z is a void * (note that the declarations a* z and b* z are not valid outside the scope of the if and else block).
To overcome this you can use a function printJack as shown in the following listing:
#include <stdio.h>
typedef struct one
{
int jack;
float jill;
}a;
typedef struct two
{
int jack;
float jill;
char something;
int something1;
}b;
void printJack(void *pStruct, int type)
{
switch (type)
{
case 1:
printf("jack: %d\n", ((a *)pStruct)->jack);
break;
default:
printf("jack: %d\n", ((b *)pStruct)->jack);
break;
}
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.jack = 5;
second.jack = 4892;
printJack(&first, 1);
printJack(&second, 0);
z = &first;
printJack(z, 1);
return (0);
}
I've written code like this often and experienced a lot of trouble with it. Not at the time of implementing, since you are knowing what you are typing at that moment but let's say a few years later if you need to extend your code. You will miss a few places where you cast from void * to a * or b * and you'll spend a lot of time debugging what's going on...
Now I'm writing things like this in the following way:
#include <stdio.h>
typedef struct header
{
int jack;
float jill;
} h;
typedef struct one
{
struct header header;
/* what ever you like */
}a;
typedef struct two
{
struct header header;
char something;
int something1;
/* and even more... */
}b;
void printJack(void *pStruct)
{
printf("jack: %d\n", ((struct header *)pStruct)->jack);
}
/*
** main
*/
int main(void)
{
a first;
b second;
void *z;
first.header.jack = 5;
second.header.jack = 4892;
printJack(&first);
printJack(&second);
v = &first;
printJack(v);
return (0);
}
As you've noticed I have declared a new struct header which covers the the common parts of struct one and struct two. Instead of casting the void * to either a * or b * a "common" cast to struct header * (or h *) is done.
By doing so you can easily extend the "common attribtues" of the structs or you can implement further structs using this header and function printJack still will work. Additionally there is no need for attribute type anymore making is easier to call printJack. You can even change the type of jack without needing to change it in various places within your code.
But remember that struct header needs to be the first element of the structs you use this mechanism. Otherwise you will end up with a few surprises since you are using memory which does not contain the data of the struct header...
I need to execute a function that returns array of a specified struct with variable length. Then I should loop through the returned array.
example struct :
typedef struct student {
int id;
char *name;
int grade;
} Student;
function prototypes 1 :
Student *students;
students = findStudentByGrade(int grade);
function prototypes 2 :
Student *students;
int retval = findStudentByGrade(&students, int grade);
I am bit confused on above methods. How can correctly define a array of struct? call function ? and loop through it untill end? Can some one help me please.
You can do this in this way. This code is working. I tested in CodeLite.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct student {
int id;
char *name;
} Student;
Student *findStudent(int *asize, const int grade);
int main(void)
{
Student *stds;
int asize = 0;
stds = findStudent(&asize, 5);
int i;
for (i = 0; i < asize; i++) {
printf("ID : %i\n", stds[i].id);
}
return 0;
}
Student *findStudent(int *asize, const int grade)
{
struct student *stds = malloc(sizeof(struct student) * 3);
stds[0].id = 10;
stds[1].id = 20;
stds[2].id = 40;
*asize = 3;
return stds;
}
Get the array of struc as returned statement and pass an int variable with argument list to get the size back and simply loop through using a for loop. Or else you will find problem in looping. It is more easy to get the array size from the function which create the array.
I mean this is quite a basic question, but:
Defining array of your structures would look like:
int size = ...;
Student *students = (Student*) malloc(sizeof(Student) * size);
Then just pass that to the function (both size and the array) and then just loop until i < size.
Ofcourse, don't forget to:
free(students);
at the end.
newbie need help. This code works on Windows(Visual Studio 2012), but on GCC i get error: "array type has incomplete element type" for all void type functions below. Can someone tell me why ? (this is only a piece of my all code).
Thank you :-)
void initialize_arrays(struct data data_list[][ARRAY_SIZE]);
void read_file(struct data data_list[][ARRAY_SIZE]);
void print_struct_array(struct data data_list[][ARRAY_SIZE]);
void parallel_print(int thread_number, struct data data_list[][ARRAY_SIZE]);
void print_struct(struct data data_struct, int thread, int array_num, int elem_num);
struct data {
char *name;
int age;
double lenght;
};
int main()
{
struct data data_array[STRUCT_SIZE][ARRAY_SIZE];
initialize_arrays(data_array);
read_file(data_array);
print_struct_array(data_array);
parallel_print(6, data_array);
getchar();
return 0;
}
void initialize_arrays(struct data data_list[][ARRAY_SIZE])
{
int i,j;
for(i = 0; i < ARRAY_SIZE; i++)
for(j = 0; j < STRUCT_SIZE; j++)
{
data_list[i][j].name = NULL;
data_list[i][j].age = 0;
data_list[i][j].lenght = 0.0;
}
}
At the point where the function prototypes are declared, there is no such thing as struct data known to the program, because the struct declaration appear further down.
Move the struct declaration above the function prototypes.
(Whether some C language code works or not in Visual Studio is one big lottery, since it barely follows any C standard.)