Error while implementing a complex construct in C.
Here is the piece of snippet I had tried.
'Where f is a function returning a pointer to an array of
pointers pointing to a function returning character.'
#include <stdio.h>
int main()
{
char (*(*f())[]) ();
char s ()
{
return 'y';
}
char (*g[1])();
g[0] = s;
printf("%c\n",g[0]());
// here it's throwing error how to fix it?**strong text**
(char (*(*)[])()) func()
{
return g;
}
f = func;
printf("%c\n",(f())[0]());
return 0;
}
Error:
enter code heremain.c: In function ‘main’:
main.c:27:19: warning: implicit declaration of function ‘func’ [-Wimplicit-function-declaration]
(char (*(*)[])()) func()
^~~~
main.c:27:1: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
(char (*(*)[])()) func()
^
main.c:28:1: error: expected ‘;’ before ‘{’ token
{
^
main.c:33:1: error: invalid use of array with unspecified bounds
printf("%c\n",(f())[0]());
^~~~~~
main.c:33:16: error: called object is not a function or function pointer
printf("%c\n",(f())[0]());
Use typedefs to help:
#include <stdio.h>
typedef char (*functionPtr)(void);
typedef char (**arrayOfFunctionPtr)(void);
// OR THIS
// typedef functionPtr* arrayOfFunctionPtr;
typedef arrayOfFunctionPtr (*functionReturningArrayOfFunctionPointers)(void);
int main()
{
functionReturningArrayOfFunctionPointers f;
char s()
{
return 'y';
}
char (*g[1])();
g[0] = s;
printf("%c\n",g[0]());
arrayOfFunctionPtr func()
{
return g;
}
f = func;
printf("%c\n",(f())[0]());
return 0;
}
Related
I'm newly learned about function pointers here but I couldn't define a function pointer to be32toh() or other functions of endian.h header.
First of all, I can do what is told in the given thread:
#include <endian.h>
int addInt(int n, int m) {
return n+m;
}
int main(){
int (*functionPtr)(int,int);
functionPtr = addInt;
return 0;
}
But when I try to do the same for a function like be32toh(), I'll get a compilation error:
#include <stdint.h>
#include <endian.h>
int addInt(int n, int m) {
return n+m;
}
int main(){
int (*functionPtr)(int,int);
functionPtr = addInt;
uint32_t (*newptr)(uint32_t);
newptr = &be32toh;
return 0;
}
Compile as:
$ gcc test.c
Result is as below:
test.c: In function ‘main’:
test.c:15:15: error: ‘be32toh’ undeclared (first use in this function)
15 | newptr = &be32toh;
| ^~~~~~~
test.c:15:15: note: each undeclared identifier is reported only once for each function it appears in
What's the problem and how to fix it?
What's the problem
be32toh is a macro.
how to fix it?
Just write the function yourself.
uint32_t be32toh_func(uint32_t a) {
return be32toh(a);
}
....
newptr = &be32toh_func;
Im trying to have an unlimited array in C to store some data. My header file stock.h looks like this
#ifndef STOCK_H
#define STOCK_H
typedef struct {
char* id;
char* descripcion;
int precio;
} tAppliance;
typedef struct {
int cantidad;
tAppliance electrodomestico;
} tElectroStock;
typedef struct {
int size;
int capacity;
tElectroStock *electrodomesticos;
} tStock;
void tstock_init(tStock *stock);
void tstock_add(tStock *stock, tAppliance item, int cantidad);
#endif
My stock.c file
#include <stdio.h>
#include "stock.h"
void tstock_init(tStock *stock) {
stock->size = 0;
stock->capacity = 10;
stock->electrodomesticos = malloc(sizeof(tElectroStock) * stock->capacity);
}
void tstock_add(tStock *stock, tAppliance item, int cantidad) {
if(stock->size >= stock->capacity) {
stock->capacity = stock->capacity * 2;
stock->electrodomesticos = realloc(stock->electrodomesticos, sizeof(tElectroStock) * stock->capacity);
}
tElectroStock t;
t.cantidad = cantidad;
t.electrodomestico = item;
stock->size++;
stock->electrodomesticos[stock->size] = t;
}
And finally my main function
#include <stdio.h>
#include "stock.h"
int main(int argc, char **argv)
{
tStock t; // Creamos nuestra variable de stock
tstock_init(&t); // Iniciamos el stock
tAppliance item;
item.descripcion = "Television SONY";
item.id = "apeid9";
item.precio = 20;
tstock_add(&t, item, 1);
tstock_add(&t, item, 1);
}
As you can see on my main function I try to add 2 items to tStock. however adding the second item seems to crash the whole applicattion and no idea why.
Enable all warnings, and treat every single one of them as error. That way you could've found the issue with the member not being a pointer that's already been mentioned yourself.
Check the return value of library functions like malloc and realloc for errors and handle them appropriately.
Finally, you'll want to swap these two lines:
stock->size++;
stock->electrodomesticos[stock->size] = t;
Compile with -Wall you'll be warn:
test.c: In function ‘tstock_init’:
test.c:634:5: warning: implicit declaration of function ‘malloc’ [-Wimplicit-function-declaration]
stock->electrodomesticos = malloc(sizeof(tElectroStock) * stock->capacity);
^
test.c:634:32: warning: incompatible implicit declaration of built-in function ‘malloc’
stock->electrodomesticos = malloc(sizeof(tElectroStock) * stock->capacity);
^
test.c: In function ‘tstock_add’:
test.c:640:9: warning: implicit declaration of function ‘realloc’ [-Wimplicit-function-declaration]
stock->electrodomesticos = realloc(stock->electrodomesticos, sizeof(tElectroStock) * stock->capacity);
^
test.c:640:36: warning: incompatible implicit declaration of built-in function ‘realloc’
stock->electrodomesticos = realloc(stock->electrodomesticos, sizeof(tElectroStock) * stock->capacity);
Add to stock.c:
#include <stdlib.h>
You must also switch instruction as below:
stock->electrodomesticos[stock->size] = t;
stock->size++;
Otherwise your code is UB when stock->size++ == stock->capacity
I'm completely stuck at this point. I have the following code in 3 files:
file
mixer_oss.c
#include "mixer.h"
static char *devices[] = SOUND_DEVICE_NAMES;
static char **oss_get_device(void)
{
int i, o, devs, res;
char **result;
if ((ioctl(fd, SOUND_MIXER_READ_RECMASK, &devs)) == -1) {
return NULL;
} else {
result = malloc(sizeof(char*)*SOUND_MIXER_NRDEVICES);
o = 0;
for (i=0; i < SOUND_MIXER_NRDEVICES; i++) {
res = (devs >> i)%2;
if (res) {
result[o] = malloc(strlen(devices[i])+1);
sprintf(result[o], "%s", devices[i]);
o++;
}
result[o] = NULL;
}
}
return result;
}
struct mixer oss_mixer = {
.get_device = oss_get_device,
};
file
mixer.h
#ifdef __cplusplus
extern "C" {
#endif
struct mixer
{
char (* get_device) (void);
};
#pragma weak oss_mixer
extern struct mixer oss_mixer;
#ifdef __cplusplus
};
#endif
file
mixer.c
#include "mixer.h"
static char null_get_device(void)
{
}
static struct mixer *mixers[] = {
&oss_mixer,
&null_mixer
};
Now, when I compile the code, this is what I get
mixer-oss.c: warning: initialization from incompatible pointer type [enabled by default]
.get_device = oss_get_device,
^
warning: (near initialization for ‘oss_mixer.get_device’) [enabled by default]
Could you please help me?
Thanks in advance.
char (* get_device) (void); declares a pointer to a function that takes no argument and returns a char.
static char **oss_get_device(void) is a function that takes no arguments and returns a pointer to pointer to char.
Your pointer to a function should be declared like this:
char ** (*get_device)(void);
Now it is compatible with oss_get_device.
#include <stdio.h>
int _area(), _vol(), (*fnptr)();// declare the functions and the function pointer here
_area(a,b)
int a, b;
{
return (a*b); //The return value of _area after parameters are passed to it
}
_vol(fnptr,c) //engaging the function pointer as a parameter
int c;
{
fnptr = _area(); //initializing the function pointer to function _area
int k = (*fnptr)(8,9); // error occurs here
return (k*c);
}
Compiling produces an error ,
:error: invalid type argument of 'unary *' (have 'int')
**int k = (*fnptr)(8,9);** should be int **k = (*fnptr)(8,9);
Using function prototypes I believe the code should look something like this:
#include <stdio.h>
int _area(int a, int b);
int _vol(int (*fnptr)(int, int), int);;// declare the functions and the function pointer here
int _area(int a, int b)
{
return (a*b); //The return value of _area after parameters are passed to it
}
int _vol(int (*fnptr)(int, int),int c) //engaging the function pointer as a parameter
{
fnptr = _area; //initializing the function pointer to function _area
int k = fnptr(8,9); // error occurs here
return (k*c);
}
Try to change fnptr = _area() to fnprt = _area. You want to point fnptr to the adress of _area function, not to call the function itself.
I'm writing a unit test framework (see SO for more details). Or view the code at GitHub.
Safer Code describes a way to pass functions of arbitrary types.
But how do I call such a function without knowing its types beforehand? Assume f needs no input, so f() should work on its own.
Let's say I want to populate an array using an arbitrary generator function.
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = GC_MALLOC(len * size);
for (i = 0; i < len; i++) {
arr[i] = gen(NULL);
}
return arr;
}
It should look something like this, but I get compiler errors:
gcc -o example example.c qc.c qc.h -lgc
In file included from example.c:1:
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
In file included from qc.c:1:
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
qc.c:23: error: conflicting types for ‘gen_array’
qc.h:21: error: previous declaration of ‘gen_array’ was here
qc.c: In function ‘gen_array’:
qc.c:29: warning: dereferencing ‘void *’ pointer
qc.c:29: error: too many arguments to function ‘gen’
qc.c:29: error: invalid use of void expression
qc.h:21: error: expected declaration specifiers or ‘...’ before ‘size_t’
make: *** [example] Error 1
After thinking about some more I realize your problem your above code would never work.
You are first calling trying to call a void function with no parameters with the parameter NULL. Next you would need your code to be more generic. I placed an example below of what I mean. Now using a global variable
#include <stdio.h>
#include <stdlib.h>
typedef void (*fp)(void);
void * GEN_ARRAY_TEMP;
int gen_int() {
return 67;
}
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = malloc(len * size);
void* arr_end = arr + len * size;
GEN_ARRAY_TEMP = arr;
while (GEN_ARRAY_TEMP <= arr_end) {
gen();
GEN_ARRAY_TEMP+=size;
}
return arr;
}
void make_int() {
(*(int*)GEN_ARRAY_TEMP) = 9;
}
int main() {
int i;
int * gen_int_array = (int*) gen_array(make_int, sizeof(int));
for(i=0;i<67;i++) {
printf("%d\n",gen_int_array[i]);
}
}
That page suggests you make the function pointer take a void*. So in order for your code to compile, you must pass it a void pointer:
typedef void* (*fp)(void*);
doit(fp f) {
f(NULL);
}
And just make sure that the function that you're calling simply ignores the parameter.
Generally speaking, these generic function pointers are used for starting threads. The void pointer is simply a pointer to a struct that holds the actual parameters.
What would you need to do is wrap your function in a void function like so
#include <stdio.h>
typedef void (*fp)(void);
int sum(int x,int y) {return x+y;}
void doit(fp f) {
f();
}
void func() {
printf("Hello %d\n",sum(1,2));
}
int main() {
doit(func);
}
You have two problems:
First, qc.h is missing a <stdlib.h> include. This is needed for use of size_t.
Second, in gen_array, you create a void *arr, then try to dereference it as an array (arr[i]). Since the compiler doesn't know the size of your array elements, it cannot fill the array. You must treat it as a char *, offset by arr + size * i, and pass it into gen rather than taking a return (returns also need to know the structure size):
// ...
char *arr = GC_MALLOC(len * size);
for (int i = 0; i < len; i++) {
gen(arr + i * size, NULL);
}
return arr;
This will of course require changing the fp type definition.
For the case where your pointer to a function 'fp' is of type which takes no argument and returns void, in which case you should declare it as :
typedef void (*fp)();
In the above case the call should be :
(*gen)();
If your pointer to the function 'fp' is of type which takes 'void *' as argument and returns void, in which case you should declare it as :
typedef void (*fp)(void *);
In the above case the call should be :
(*gen)(NULL);
or any other pointer variable you might want to pass.
As far as your example goes try this :
typedef void * (*fp)(void *);
void* gen_array(fp gen, size_t size) {
int i, len = gen_int() % 100;
void* arr = GC_MALLOC(len * size);
for (i = 0; i < len; i++) {
arr[i] = (*gen)(NULL);
}
return arr;
}