C Declaration: Unique Construct - c++

Linux kernel has the following definition inside sched_class struct definition.
#ifdef CONFIG_SMP
int (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
.......
.......
Now what does this line mean, I have fairly good knowledge in C & C++. But I was having hard time understanding this declaration construct:
int (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
Can someone please explain what does this mean and what it does.
Thanks

It's a function pointer.
int (*select_task_rq)(struct task_struct *p, int task_cpu, int sd_flag, int flags);
means that select_task_rq is a pointer to a function returning an int and taking all those parameter types.
It can be set to any compatible function and called as if it were a fixed function name. It's sometimes used to provide a primitive form of polymorphism in C, or to allow easy switching between functions based on other information.

Related

: warning: ISO C++ forbids variable length array ‘s1’ [-Wvla]

I am building an R package that contains a c++ program. The checking runs fine, but I am getting this message
: warning: ISO C++ forbids variable length array ‘s1’ [-Wvla]
The CRAN's maintainer says that the error is in this part of the code is shown below. I am thinking that the argument "nrows" is redundant , but I wonder if there is another way to solve the problem
double entCI(double input[], int cMatrix[], double partition,
int nrows, int begin, int end)
{
double s1[nrows], s2[nrows], entropy;
int cs1[nrows], cs2[nrows];
int s1Count=0, s2Count=0, sCount=0;
while(input[begin]<partition)
{
cs1[s1Count]=cMatrix[begin];
s1[s1Count++]=input[begin++];
}
while(begin<end)
{
cs2[s2Count]=cMatrix[begin];
s2[s2Count++]=input[begin++];
}
sCount=s1Count+s2Count;
entropy=(s1Count/double(sCount))*ent(s1,cs1,s1Count)
+(s2Count/double(sCount))*ent(s2,cs2,s2Count);
return entropy;
}
Indeed, the error is on these lines:
double s1[nrows], s2[nrows], entropy;
int cs1[nrows], cs2[nrows];
They declare arrays, whose size depend on the nrows argument. The value of nrows is determined at runtime and therefore the arrays must be variable length. Such array variables are not allowed by the c++ standard as told to you by the warning.
I am thinking that the argument "nrows" is redundant
I don't see how that is. It's used in the function.
but I wonder if there is another way to solve the problem
There are ways to solve the problem. If the size of the array needs to be determined at runtime, it must be allocated dynamically. The simplest and safest way to do that is to use std::vector.
Generally you should use dynamic memory allocation to create array out of variable:
double* s1 = new double[nrows];
Then, remember to delete that array.
Other solution is to use std::vector instead of plain array.
Variable Length Arrays is for a long time a feature from gcc. It has been accepted in C99 but not in C++11 (nor in any following C++ version I know).
An easy and clean solution would be to compile that function as C because it does not use any specific C++ feature, simply array manipulation. In fact, this function is plain C that happens to be accepted by g++ but is not correct C++ hence the warning.
My advice is :
put the function in a .c file and compile it in C99 mode
declare it as extern "C" double entCI(double input[], int cMatrix[], double partition,
int nrows, int begin, int end) in other C++ module, or better write the include file declaring it as
#ifdef C++
extern "C" {
#endif
double entCI(double input[], int cMatrix[], double partition,
int nrows, int begin, int end)
#ifdef C++
}
#endif

arrays with missing sizes vs pointers

I have generally thought that the following two prototypes were interchangeable:
int main(int argc, char ** argv);
int main(int argc, char * argv[]);
In general I had imagined that char ** argv and char * argv[] were interchangeable. However, I have also come accross some stuff on the internet that claim that you can declare structs like
struct S {
int size;
int ar[];
};
And then simply malloc appropriately so that ar can be as large as you want at runtime.
But this seems rather strange to me. If I had instead declared
struct S {
int size;
int * ar;
};
Can I still do the same thing? I would have imagined this depends on what you make ar point to.
How exactly are int * ar and int ar[] different when used inside a struct? What about with char ** argv and char * argv[] in function prototypes? Do they have different semantics in C as opposed to in C++?
There's a special-case rule for function parameters that look like arrays. Any such parameter is "adjusted" to a pointer to the (possibly qualified) element type.
Because of this rule, these definitions:
int main(int argc, char **argv) { /* ... */ }
and
int main(int argc, char *argv[]) { /* ... */ }
are exactly equivalent. (There's a similar rule for parameters of function type, which are adjusted to function pointers.)
This rule applies only to parameter declarations.
One annoying consequence is that if you declare an array parameter with a size, it's silently ignored:
void func(int array[42]);
really means
void func(int *array);
(There is a usage of the static keyword, added in C99, which I won't go into here.)
struct S {
int size;
int ar[];
};
This is a flexible array member, a feature added in C99. It declares that ar is an array (not, I repeat not, a pointer) of unspecified size. To use it, you have to allocate enough space to hold however many elements you're going to need at run time. This was added to the language as a replacement for the "struct hack", described in question 2.6 of the comp.lang.c FAQ.
Section 6 of the same FAQ is an excellent resource for explaining the often confusing relationship between arrays and pointers.
There is a special rule for using arrays types in function arguments: They become pointer types. However, that rule only holds for function arguments.
This becomes very obvious when you replace the undefined size with, e.g. a size of two:
void f(int x[2]); // equivalent to void f(int* x);
struct A {
int q[2]; // obviously not equivalent to int* q;
};
The structure definition you used
struct S {
int size;
int ar[];
};
is intended to say that an arbitrary amount of ints is supposed to follow the size member - probably exactly size elements. You cannot just leave out the last member, because that could lead to errors w.r.t. alignment and padding (assume for a second that ar was an array of doubles, and you will see the problem).
This syntax is an evolution of an old trick and has been added in C99.
You can use both the first and the second layout for the same purpose, but the layout in memory will not be the same. For the first example, you'd have (assuming a 32 bit architecture):
[size (4 bytes)][ar (size bytes)]
And for the second one:
[size (4 bytes)][pointer to ar (4 bytes)][ar (size bytes)]
So the second solution wastes memory.
char ** and char *[] are indeed the same. In fact, the below will work:
void foo(int a1[]) {
int a2[3];
a2 = 0; // ERROR: Can't assign to an array.
a1 = 0; // OKAY: You can assign to it, because it's actually a pointer!
...
The struct S that you show is using a flexible array member, though. It takes up no space. You can't assign to it. Basically, int [] means different things depending on whether it is a member or a parameter. In the struct where you have the pointer, though, you can basically make that point anywhere.

Calling function via pointer

Here is a simple code
#include<iostream.h>
#include<stdlib.h>
#include<conio.h>
void (*func[2])(int);
void main(int n=1)
{
int i;
cout<<endl<<n;
func[0]=&exit;
func[1]=&main;
i=++n<=10;
(func[i])(n);
}
Here I am satisfied with the output (i.e. 1 to 10 in different lines). The only thing which confused me was that why the global pointer is of the type void (*ptr[2])(int). If possible, please explain in simple words that why this pointer was taken so specifically
It's not a pointer, it's an array of two pointers.
This is a function:
void func(int);
This is a pointer to a function:
void (*func)(int);
and this is an array of two pointers to functions:
void (*func[2])(int);
So func[i] points to exit if i is zero (i.e. if n is greater than 10), and points to main otherwise, where i is 1.
Note that you're not allowed to call main recursively like this, nor to give main any signature other than int main() or int main(int, char**). (At least, that's the case in modern C++; these rules presumably don't apply to the prehistoric dialect your compiler accepts).

Passing struct of array as reference c++

I am new to structure programming, and I find it quite confusing when trying to pass a structure of array in c++. I have a project to do for college, a Star Trek game. This is the sample code:
void main_menu(char,char [][sz2],int&,struct enterpriseSt*,struct klingonSt*[100]);
void combat_menu(char [][sz2],struct enterpriseSt*,int&,struct klingonSt*[100]);
struct enterpriseSt
{
int energy_level;
int damage;
int torpedo_count;
};
struct klingonSt
{
int energy_level;
int damage;
int position[2];
};
int main()
{
struct enterpriseSt enterprise;
enterprise.energy_level=energy_ent_max;
enterprise.damage=0;
enterprise.torpedo_count=10;
struct klingonSt klingon[100];
main_menu(command,galaxy,turn,&enterprise,&klingon);
return 0;
}
void main_menu(char command, char galaxy[][sz2],int& turn,struct enterpriseSt * enterprise,struct klingonSt * klingon[100])
{
combat_menu(galaxy,enterprise,turn,klingon);
}
I have two structures, enterpriseSt and klingonSt. I can pass enterprise no problem, but with klingon I am struggling. I get all kinds of errors, doesn't matter what combination I use. The current one is:
error: cannot convert ‘klingonSt (*)[100]’ to ‘klingonSt**’ for argument ‘5’ to ‘void main_menu(char, char (*)[64], int&, enterpriseSt*, klingonSt**)’
I've made such a mess with it now. Could someone please explain it to me why it works with enterprise but not with klingon?
I use g++ compiler on Ubuntu. Thanks.
Your problem is in misunderstanding the arguments parsing rules.
you think that struct klingonSt*[100] is a pointer to the array of size 100 of type struct klingonSt, but actually when argument parsing, array and function symbols that should be situated on the right of token has higher priority, than symbols on the left of expression.
So, lets first write the expression with argument name included:
struct klingonSt*var[100]
and parse it
var
is an array of size 100 (as array symbol on the right has higher priority, than pointer on the left)
of pointers
to the type struct klingonSt
so, struct klingonSt*var[100] is actually is array of size 100 of pointers to struct klingonSt.
to pass a pointer to the array of size 100 of type struct klingonSt you should change parsing precedence using parenthesis:
struct klingonSt(*var)[100]
or
struct klingonSt(*)[100]
If you change your definition, your code will compile fine.
I think you're a bit confused on passing arrays to functions. When this is done, the array decays into a pointer to the first element of the array. You can declare the parameter as an array, but the array range is ignored by the compiler, and not enforced at runtime. Thus, for this style of coding, you'd just want to pass the array as a pointer, and length as a separate parameter (I've omitted your other params for clarity):
void main_menu(enterpriseSt*, int enterpriseCount, klingonSt*, int klingonCount);
Some alternatives to consider:
Adopting a modern C++ style, and use std containers like vector/list, passing them by reference.
void main_menu(vector<enterpriseSt> & enterprises, vector<klingonSt> & klingons);
Or, using a template wrapper to pass sized local arrays implicitly:
template<size_t eCount, size_t kCount>
void main_menu(enterpriseSt (&enterprises)[eCount], klingonSt (&klingons)[kCount])
{
main_menu(enterprises, eCount, klingons, kCount);
}
The problem that
struct klingonSt * klingon[100]
is an array of 100 struct klingonSt * rather than a point to 100 struct klingonSt
use struct klingonSt klingon[][100] instead.

Bind C function in C++ (undefined reference)

I have a regular C++ class like PardisoSolver.h:
#ifndef PARDISOSOLVER_H_
#define PARDISOSOLVER_H_
class PardisoSolver {
public:
/* Initializes a new Solver with the given matrix in CSR */
PardisoSolver(
int* ia,
int* ja,
double* a,
int n,
int nja);
virtual ~PardisoSolver();
void setMatrixType(int mtype);
void pardisoSymFactorize();
private:
static int get_nproc(void);
void handle_error(int ierror, int line);
int* ia; // row indices
int* ja; // column pointer
double* a; // non zero values
int n_eq; // size of matrix
int nja; // number of non zero elements
bool factorized;
/* PARDISO SETTINGS */
void *pt[64];
int maxfct;
int mnum;
int mtype;
int perm;
int nrhs;
int iparm[64];
int msglvl;
int error;
double dparm[64];
double dzero;
int izero;
};
#endif /* PARDISOSOLVER_H_ */
And on the other hand I have the implementations in PardisoSolver.cpp. Here I have an additional declaration of a C function just along with the implementations of the class:
extern "C" void pardiso (void *, int *, int *, int *, int *, int *,
double *, int *, int *, int *, int *, int *,
int *, double *, double *, int *, double *);
Now when I try to call that function like
pardiso (pt, &maxfct, &mnum, &mtype, &phase,
&n_eq, a, ia, ja, &izero, &nrhs,
iparm, &msglvl, &dzero, &dzero, &error, dparm);
I get the compile error
PardisoSolver.cpp:94: undefined reference to `pardiso'
where the call is in line 94. Did I declare the C function in the wrong place? As I got it, it cannot be a member of a class so this should be the way to call it. Thanks for the help.
All of this suggest that your program design needs improvment. First of all, there should only be one interface to your "module" (class + other stuff). You should not have "a class, and then some", that doesn't make any sense. All functions related to the functionality of the class should be included in that class. All that aren't related, should be moved to another part of the program.
Once you have straightened that out, you need to clarify the programming language. Is this C or C++? Is it C++ with a caller in C? It seems to be the latter. If so, you need to separate the two languages somehow. As one example: in Windows you could place the C++ class in a DLL, with an interface that can be called from C.
And finally, you should consider whether it makes sense to have a function taking 17 pointers as parameters. Are these parameters not related at all? Could they be grouped in structs/classes? Or perhaps this is simply a needlessly complex monster function, that could be split in several different ones.