Something strange that I saw in C? - c

typedef struct stage_tag {
pthread_mutex_t mutex; /* Protect data */
pthread_cond_t avail; /* Data available */
pthread_cond_t ready; /* Ready for data */
int data_ready; /* Data present */
long data; /* Data to process */
pthread_t thread; /* Thread for stage */
struct stage_tag *next; /* Next stage */
} stage_t;
typedef struct pipe_tag {
pthread_mutex_t mutex; /* Mutex to protect pipe */
stage_t *head; /* First stage */
stage_t *tail; /* Final stage */
int stages; /* Number of stages */
int active; /* Active data elements */
} pipe_t;
int pipe_create (pipe_t *pipe, int stages)
{
int pipe_index;
stage_t **link = &pipe->head, *new_stage, *stage;
int status;
.....
// The question lies in the method pipe_create. There is a double pointer of type stage_t which has three values... What kind of declaration is this? I am really confused.

A single declaration statement can declare multiple variables whose type are related (in the sense that they differ only by qualification):
T **x, *y, z;
is the same as:
T **x;
T *y;
T z;
A slightly absurd example:
int main(void)
{
int a = 1, * const b = &a, * const * c = &b;
return a + *b + **c;
}

Here you are creating three different variables. one is stage_t ** type link variable and initializing it to &pipe->head. Second is stage_t * type new_stage variable and third is stage_t * type stage variable. Last two variables are uninitialized.

Related

Dereferencing pointer to imcomplete type in linux terminal

So I'm trying to make a new system call in Red Hat 2.4.20 for a project that I've been working on. And for the I've created a C file to try the system call works or not and I've been getting the same error, Dereferencing pointer to imcomplete type, for days. My header file is here:
struct prcdata {
long counter; /* process counter value */
long nice; /* process nice value */
long prio; /* calculated with 20- processes’ nice value */
long weight; /* calculated with 20-nice+counter */
pid_t pid; /* process id */
long uid; /* user id of process owner */
int nofprocess; /* number of process of owner of current process
*/}
;
My C file for the system call is like this
#include <linux/mysyscall.h>
asmlinkage int cprocinf(struct prcdata *data)
{
cli();
struct prcdata temp;
copy_from_user(&temp,data,sizeof(struct prcdata));
temp.prio=20-current->nice;
temp.weight=current->counter + temp.prio;
temp.rank=2*current->nice;
temp.pid=current->pid;
temp.uid=current->uid;
temp.processcount=current->user->proccesses.counter;
copy_to_user(data,&temp,sizeof(struct prcdata));
return 0;
sti();
}
And the file to try this code is like this
#include <linux/mysyscall.h>
#include <stdio.h>
main(){
int ret;
struct prcdata *data;
ret=mysyscall(data);
printf("First values of process\n");
printf("Nice Value. %d\nPriority: %d\n", -data->prio+20,data->prio);
printf("Weight: %d\n", data->weight);
printf("Rank: %d\nPid: %d\nPid: %d\nParent: %d\nProcess Count: %d\n",data->rank,data->pid,data->pidparent,data->processcount);
}
What am I doing wrong
This
copy_from_user(&temp,arg1,sizeof(struct prcdata));
....
copy_to_user(arg1,&temp,sizeof(struct prcdata));
should be
copy_from_user(&temp,data,sizeof(struct prcdata));
....
copy_to_user(data,&temp,sizeof(struct prcdata));
And here you need to initialize the pointer or pass a local object:
main()
{
int ret;
struct prcdata data;
ret=mysyscall(&data);
...
}
or
main()
{
int ret;
struct prcdata *data = malloc(sizeof (struct prcdata));
ret=mysyscall(&data);
...
free(data);
}

What is this problem "dereferencing pointer to incomplete type 'struct cashier' "?

I am learning data structure of queue, and making a cashier structure like this:1 There are 2 integers,1 float and 1 queue data type in it.2 So I wanted to make a cashier pointer to point to the cashier structure.`
struct cashier {
int numberOfCustomersServed; /* This should be initialized to 0 */
int totalCustomerWaitingTime; /* This should be initialized to 0 */
float totalAmountReceived; /* This should be initialized to 0 */
queueADT customerQ; /* This should be initialized to an empty queue */
}cashier;
struct cashier* initCashier(void){
struct cashier *y;
y->numberOfCusCustomersServed=0;
y->totalCustomerWaitingTime=0;
y->totalAmountReceived=0.0;
y->customerQ=getEmptyQueue();
return y;
};
But then I get the error:
/cygdrive/c/Users/Heta/Desktop/CLionHWQ2/supermarket.c:8:6: error: dereferencing pointer to incomplete type 'struct cashier'
y->numberOfCusCustomersServed=0;
And below is basically the queue function.3
The main() is not yet finished, mostly just empty.4
Any help from this will be appreciated. :)
1.
struct cashier *y;
y is a pointer to struct cashier, but it was not set to point to a variable of type struct cashier.
Thus,
y->numberOfCusCustomersServed=0;
y->totalCustomerWaitingTime=0;
y->totalAmountReceived=0.0;
y->customerQ=getEmptyQueue();
return y; // discussed further at point 2.
doesn´t work, since y has not been initialized to point to a valid variable of type struct cashier.
Rather use:
struct cashier x; // x is a variable of type `struct cashier`.
struct cashier *y = &x; // y is a pointer to x.
y->numberOfCusCustomersServed = 0;
y->totalCustomerWaitingTime = 0;
y->totalAmountReceived = 0.0;
y->customerQ = getEmptyQueue();
with x as a variable of type struct cashier and y as pointer to it, or alternatively:
struct cashier x;
x.numberOfCusCustomersServed = 0;
x.totalCustomerWaitingTime = 0;
x.totalAmountReceived = 0.0;
x.customerQ = getEmptyQueue();
since the pointer of y is redundant.
2.
return y;
You cannot return a pointer to an inner-scope variable from a function, because the variable the pointer points to does no longer exist when the function is finished.
If you really want to return a structure, you should do it like that:
struct cashier initCashier(void){
struct cashier x; // x is a variable of type `struct cashier`.
struct cashier *y = &x; // y is a pointer to x.
y->numberOfCusCustomersServed = 0;
y->totalCustomerWaitingTime = 0;
y->totalAmountReceived = 0.0;
y->customerQ = getEmptyQueue();
return x; // returning the complete structure.
};
or alternatively, since you do not need to use y, a pointer to the structure, otherwise:
struct cashier initCashier(void){
struct cashier x; // only the structure variable x.
x.numberOfCusCustomersServed = 0;
x.totalCustomerWaitingTime = 0;
x.totalAmountReceived = 0.0;
x.customerQ = getEmptyQueue();
return x; // returning the complete structure.
};
Be sure to also change the respective type of the return value of the function initCashier() from struct cashier* to struct cashier.
3.
struct cashier {
int numberOfCustomersServed; /* This should be initialized to 0 */
int totalCustomerWaitingTime; /* This should be initialized to 0 */
float totalAmountReceived; /* This should be initialized to 0 */
queueADT customerQ; /* This should be initialized to an empty queue */
}cashier;
_______
The second cashier defines a global variable of type struct cashier with the identifier of cashier, which is permissible because structure tag and global variables are in different name spaces, but you do not use this variable in the provided code, so either you can omit it (if you do not need it):
struct cashier {
int numberOfCustomersServed; /* This should be initialized to 0 */
int totalCustomerWaitingTime; /* This should be initialized to 0 */
float totalAmountReceived; /* This should be initialized to 0 */
queueADT customerQ; /* This should be initialized to an empty queue */
};
or you can use this one, which would solve half of the problems mentioned above, if you only want to use the global variable cashier of type struct cashier for the function initCashier():
struct cashier {
int numberOfCustomersServed; /* This should be initialized to 0 */
int totalCustomerWaitingTime; /* This should be initialized to 0 */
float totalAmountReceived; /* This should be initialized to 0 */
queueADT customerQ; /* This should be initialized to an empty queue */
}cashier; // global variable `cashier` of type `struct cashier`.
void initCashier(void){ // return type of `void`.
cashier.numberOfCusCustomersServed = 0; // the variable `cashier` is used directly.
cashier.totalCustomerWaitingTime = 0;
cashier.totalAmountReceived = 0.0;
cashier.customerQ = getEmptyQueue();
};

Error using LIBSVM in C in Eclipse IDE for binary-class machine learning

I am trying to use LIBSVM to perform binary-class machine learning (two classes only) using C on Eclipse. Before I started using my training data, I tried running a simple XOR problem to see if my LIBSVM application could predict the correct output value (which is a supposed to be +1).
However, after I built my project, I got errors such as undefined reference to '_Heap_Begin' , undefined reference to '_Heap_Limit' and undefined reference to '__reset_hardware'.
I added the svm.h file to the 'include' folder and svm_train.c and svm.cpp files to the 'src' folder and I already #include 'svm.h' in my source files, which is the instruction I followed from the README file in LIBSVM. I followed all the instructions from the README file, which states "You need to #include "svm.h" in your C/C++ source files and link your program with `svm.cpp'."
What am I doing wrong here?
File svm.h
#ifndef _LIBSVM_H
#define _LIBSVM_H
#define LIBSVM_VERSION 322
#ifdef __cplusplus
extern "C" {
#endif
extern int libsvm_version;
struct svm_node
{
int index;
double value;
};
struct svm_problem
{
int l;
double *y;
struct svm_node **x;
};
enum { C_SVC, NU_SVC, ONE_CLASS, EPSILON_SVR, NU_SVR }; /* svm_type */
enum { LINEAR, POLY, RBF, SIGMOID, PRECOMPUTED }; /* kernel_type */
struct svm_parameter
{
int svm_type;
int kernel_type;
int degree; /* For poly */
double gamma; /* For poly/rbf/sigmoid */
double coef0; /* For poly/sigmoid */
/* These are for training only */
double cache_size; /* In MB */
double eps; /* Stopping criteria */
double C; /* For C_SVC, EPSILON_SVR and NU_SVR */
int nr_weight; /* For C_SVC */
int *weight_label; /* For C_SVC */
double* weight; /* For C_SVC */
double nu; /* For NU_SVC, ONE_CLASS, and NU_SVR */
double p; /* For EPSILON_SVR */
int shrinking; /* Use the shrinking heuristics */
int probability; /* Do probability estimates */
};
//
// svm_model
//
struct svm_model
{
struct svm_parameter param; /* Parameter */
int nr_class; /* Number of classes, = 2 in regression/one class svm */
int l; /* Total #SV */
struct svm_node **SV; /* SVs (SV[l]) */
double **sv_coef; /* Coefficients for SVs in decision functions (sv_coef[k-1][l]) */
double *rho; /* Constants in decision functions (rho[k*(k-1)/2]) */
double *probA; /* Pariwise probability information */
double *probB;
int *sv_indices; /* sv_indices[0, ..., nSV-1] are values in [1, ..., num_traning_data] to indicate SVs in the training set */
/* For classification only */
int *label; /* Label of each class (label[k]) */
int *nSV; /* Number of SVs for each class (nSV[k]) */
/* nSV[0] + nSV[1] + ... + nSV[k-1] = l */
/* XXX */
int free_sv; /* 1 if svm_model is created by svm_load_model*/
/* 0 if svm_model is created by svm_train */
};
struct svm_model *svm_train(const struct svm_problem *prob, const struct svm_parameter *param);
void svm_cross_validation(const struct svm_problem *prob, const struct svm_parameter *param, int nr_fold, double *target);
int svm_save_model(const char *model_file_name, const struct svm_model *model);
struct svm_model *svm_load_model(const char *model_file_name);
int svm_get_svm_type(const struct svm_model *model);
int svm_get_nr_class(const struct svm_model *model);
void svm_get_labels(const struct svm_model *model, int *label);
void svm_get_sv_indices(const struct svm_model *model, int *sv_indices);
int svm_get_nr_sv(const struct svm_model *model);
double svm_get_svr_probability(const struct svm_model *model);
double svm_predict_values(const struct svm_model *model, const struct svm_node *x, double* dec_values);
double svm_predict(const struct svm_model *model, const struct svm_node *x);
double svm_predict_probability(const struct svm_model *model, const struct svm_node *x, double* prob_estimates);
void svm_free_model_content(struct svm_model *model_ptr);
void svm_free_and_destroy_model(struct svm_model **model_ptr_ptr);
void svm_destroy_param(struct svm_parameter *param);
const char *svm_check_parameter(const struct svm_problem *prob, const struct svm_parameter *param);
int svm_check_probability_model(const struct svm_model *model);
void svm_set_print_string_function(void (*print_func)(const char *));
#ifdef __cplusplus
}
#endif
#endif /* _LIBSVM_H */
File svm_train.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include "svm.h"
#define Malloc(type,n) (type *)malloc((n)*sizeof(type))
struct svm_parameter param; // Set by parse_command_line
struct svm_problem prob; // Set by read_problem
struct svm_model *model;
struct svm_node *x_space;
struct svm_node ** x;
struct svm_node *testnode;
void main(void)
{
param.svm_type = C_SVC;
param.kernel_type = RBF;
param.degree = 3;
param.gamma = 0.5;
param.coef0 = 0;
param.nu = 0.5;
param.cache_size = 100;
param.C = 1;
param.eps = 1e-3;
param.p = 0.1;
param.shrinking = 1;
param.probability = 0;
param.nr_weight = 0;
param.weight_label = NULL;
param.weight = NULL;
// Problem definition-------------------------------------------------------------
prob.l = 4;
// x values matrix of xor values (training data)
double matrix[prob.l][2];
matrix[0][0] = 1;
matrix[0][1] = 1;
matrix[1][0] = 1;
matrix[1][1] = 0;
matrix[2][0] = 0;
matrix[2][1] = 1;
matrix[3][0] = 0;
matrix[3][1] = 0;
// This part i do not understand
struct svm_node** x = (struct svm_node * *)malloc((prob.l)*sizeof(struct svm_node *));
// Trying to assign from matrix to svm_node training examples
for (int row = 0; row <prob.l; row++)
{
struct svm_node* x_space = Malloc(struct svm_node, 3);
for (int col = 0; col < 2; col++)
{
x_space[col].index = col;
x_space[col].value = matrix[row][col];
}
x_space[2].index = -1; // Each row of properties should be terminated with a -1 according to the readme
x[row] = x_space;
}
prob.x = x;
// Y values
prob.y = (double *)malloc((prob.l)*sizeof(double));
prob.y[0] = -1;
prob.y[1] = 1;
prob.y[2] = 1;
prob.y[3] = -1;
// Train model---------------------------------------------------------------------
struct svm_model *model = svm_train(&prob, &param);
// Test model----------------------------------------------------------------------
struct svm_node* testnode = (struct svm_node *) malloc((3)*sizeof(struct svm_node));
testnode[0].index = 0;
testnode[0].value = 1;
testnode[1].index = 1;
testnode[1].value = 0;
testnode[2].index = -1;
double retval = svm_predict(model, testnode);
svm_destroy_param(&param);
free(prob.y);
free(prob.x);
free(x_space);
}
Those undefined symbols don't seem related to SVMs, but to your toolchain. There must be a standard library of your development environment that you don't link (that we can't guess since we don't know the platform you are developing for).

c program how to print a char array held by a structure variable?

How do I print the char array held in the struct variable char binary_filename?
I tried:
printf("Binary file name is : %s \n", prv_instance_t.binary_filename);
However, I get the error error: expected expression before ‘prv_instance_t’
Here is the struct definition.
#define BINARY_FILE_NAME_MAXLEN 10
typedef struct _prv_instance_
{
/*
* The first two are mandatories and represent the pointer to the next instance and the ID of this one. The rest
* is the instance scope user data (uint8_t power in this case)
*/
struct _prv_instance_ * next; // matches lwm2m_list_t::next
uint16_t shortID; // matches lwm2m_list_t::id
uint8_t power;
uint8_t reset;
double dec;
char binary_filename[BINARY_FILE_NAME_MAXLEN];
} prv_instance_t;
You are using the type itself. To access a member of the struct you have to declare an instance of that struct first. For example, this will print Hello World :
#include <stdio.h>
#include <string.h>
#define BINARY_FILE_NAME_MAXLEN 10
typedef struct _prv_instance_
{
char binary_filename [BINARY_FILE_NAME_MAXLEN];
} prv_instance_t;
int main()
{
prv_instance_t foo, bar;
strcpy(foo.binary_filename, "Hello");
strcpy(bar.binary_filename, "World");
printf("%s %s\n", foo.binary_filename, bar.binary_filename);
return 0;
}
What you are trying to do is similar to
printf("%d", int);
Just remove typedef keyword.
Current definition does not define a variable, but makes two equivalent types prv_instance_t and struct _prv_instance_. From your question I understand that prv_instance_t should be an instance (variable) of type _prv_instance_, keyword typedef is unnecessary.
Your printf will work with:
#define BINARY_FILE_NAME_MAXLEN 10
struct _prv_instance_
{
/*
* The first two are mandatories and represent the pointer to the next instance and the ID of this one. The rest
* is the instance scope user data (uint8_t power in this case)
*/
struct _prv_instance_ * next; // matches lwm2m_list_t::next
uint16_t shortID; // matches lwm2m_list_t::id
uint8_t power;
uint8_t reset;
double dec;
char binary_filename[BINARY_FILE_NAME_MAXLEN];
} prv_instance_t;
as well as with the following one:
#define BINARY_FILE_NAME_MAXLEN 10
struct _prv_instance_
{
/*
* The first two are mandatories and represent the pointer to the next instance and the ID of this one. The rest
* is the instance scope user data (uint8_t power in this case)
*/
struct _prv_instance_ * next; // matches lwm2m_list_t::next
uint16_t shortID; // matches lwm2m_list_t::id
uint8_t power;
uint8_t reset;
double dec;
char binary_filename[BINARY_FILE_NAME_MAXLEN];
};
struct _prv_instance_ prv_instance_t;

invalid type argument of ‘->’ (have ‘struct coada’)

I am trying to create a list of threads that would be locked and executed in the order of the list. here is the code( it's a busy wait simulation I have for a course)
# include <stdio.h>
# include<pthread.h>
# include<stdlib.h>
# define NKIDS 10
pthread_mutex_t mutx;
struct kidrec {
int data;
pthread_t id;
};
struct coada {
struct kidrec th;
struct coada *next;
};
void *copilfunc(void*p)
{
int *ip=(int*)p;
int tmp;
int v;
pthread_mutex_lock(&mutx);
tmp=v; v=*ip;
printf(" We are at thread %d \n",v);
pthread_mutex_unlock(&mutx);
}
int main(){
struct kidrec kids[NKIDS];
struct coada c[NKIDS];
int m;
for(m=0;m<NKIDS;m++){
kids[m].data=m;
pthread_create(&kids[m].id,NULL,copilfunc,&kids[m].data);
c[m].th=kids[m];
if(m>0) c[m-1]->next=c[m];
if(m==NKIDS) c[NKIDS]->next=c[0];
}
for(m=0;m<NKIDS;m++)
pthread_join(c[m].th.id,NULL);
}
You are trying to access an attribute on an array of a struct using -> which is an access operator used for pointers (non-arrays)...
Try using
c[i].next = &c[j]
instead of
c[i]->next = c[j]
;)
The variable c[] is an array of struct coada, not struct coada *.
So the expression c[m-1] is a struct coada, and you access its fields with ..
Thus, it should be:
c[m - 1].next = &c[m];
It doesn't matter that next is a pointer, the period is for accessing the struct-typed value on its left. Also note that you need to take the address of the array element, thus the & on the right.

Resources