Problems with return values of function pointers - c

I have the following SSCCE:
#include <stdio.h>
#include <stdint.h>
#include <time.h>
#include <string.h>
#define streq(x, y) (strcmp((x), (y)) == 0)
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0]))
typedef struct
{
const char *cmd;
void* (*fn)(void);
} __attribute__((__packed__)) Command;
void* getTime(void)
{
return ((void*)((uintptr_t)time(NULL)));
}
void* getDay(void)
{
time_t t = time(NULL);
struct tm tm = *localtime(&t);
return ((void*)((uintptr_t)(tm.tm_wday)));
}
static Command commands[] =
{
{"time", getTime},
{"day", getDay},
};
int main(int argc, char *argv[])
{
for (int i = 0; i < ARRAY_SIZE(commands); ++i)
{
Command *p = commands+i;
if (streq(argv[1], p->cmd)) printf("%d\n", (int)p->fn);
}
}
My question is why when I run the code as such:
./test day
The return value is 3648 and not a value from 0-6 as specified here.

You need to call the function. Right now you're just printing the function pointer value. The following code should do it:
if (streq(argv[1], p->cmd)) printf("%d\n", (int)(p->fn()));

Related

How come my compiler isn't able to see these functions I've created?

So I'm currently trying to work through a book called "Crafting Interpreters" and it goes step by step through making a language. I'm writing this language in C and already running into issues. I have a couple header files with respective c files and then the main driver code. When I try to compile the code, I get this error:
compiler error msg
I'm not sure what's going wrong here as I have other projects using header files and they are able to compile correctly.
//main
#include "common.h"
#include "chunk.h"
int main(int argc, const char* argv[]) {
Chunk chunk;
initChunk(&chunk);
writeChunk(&chunk, OP_RETURN);
freeChunk(&chunk);
return 0;
}
//common.h
#ifndef clox_common_h
#define clox_common_h
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
#endif
//chunk.h
#ifndef clox_chunk_h
#define clox_chunk_h
#include "common.h"
typedef enum {
OP_RETURN,
} OpCode;
typedef struct {
int count;
int capacity;
uint8_t* code;
} Chunk;
void initChunk(Chunk* chunk);
void freeChunk(Chunk* chunk);
void writeChunk(Chunk* chunk, uint8_t byte);
#endif
//chunk.c
#include <stdlib.h>
#include "chunk.h"
#include "memory.h"
void initChunk(Chunk* chunk) {
chunk->count = 0;
chunk->capacity = 0;
chunk->code = NULL;
}
void freeChunk(Chunk* chunk) {
FREE_ARRAY(uint8_t, chunk->code, chunk->capacity);
initChunk(chunk);
}
void writeChunk(Chunk* chunk, uint8_t byte) {
if (chunk->capacity < chunk->count) {
int oldCapacity = chunk->capacity;
chunk->capacity = GROW_CAPACITY(oldCapacity);
chunk->code = GROW_ARRAY(uint8_t, chunk->code,
oldCapacity, chunk->capacity);
}
chunk->code[chunk->count] = byte;
chunk->count++;
}
//memory.h
#ifndef clox_memory_h
#define clox_memory_h
#include "common.h"
#define GROW_CAPACITY(capacity) \
((capacity) < 8 ? 8 : (capacity) * 2)
#define GROW_ARRAY(type, pointer, oldCount, newCount) \
(type*)reallocate(pointer, sizeof(type) * (oldCount), \
sizeof(type) * (newCount))
#define FREE_ARRAY(type, pointer, oldCount) \
reallocate(pointer, sizeof(type) * (oldCount), 0)
void* reallocate(void* pointer, size_t oldSize, size_t newSize);
#endif
//memory.c
#include <stdlib.h>
#include "memory.h"
void* reallocate(void* pointer, size_t oldSize, size_t newSize) {
if (newSize == 0) {
free(pointer);
return NULL;
}
void* result = realloc(pointer, newSize);
if (result == NULL) exit(1);
return result;
}
Any guidance would be appreciated

how to print the contents of char**?

I have a structure defined as a char** array containing strings. I dont know how to run printf on its contents.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef STRUCT_STRING_ARRAY
#define STRUCT_STRING_ARRAY
typedef struct s_string_array
{
int size;
char** array;
} string_array;
#endif
void my_print_words_array(string_array* param_1)
{
int len = param_1->size;
char **d = param_1->array;
for(int i = 0 ; i < len;i++){
printf("%s\n", d[i]);
}
}
int main(){
struct s_string_array *d;
d->size = 2;
char **my_arr = (char *[]){"hello", "world"};//this init is fine
d->array = my_arr;
my_print_words_array(d);
return 0 ;
}
the main function gives me segfault error. What's wrong?
There is no sense to declare a pointer to the structure
struct s_string_array *d;
moreover that is not initialized and has indeterminate value that further is a reason of undefined behavior.
What you are trying to achieve is the following
#include <stdio.h>
typedef struct s_string_array
{
int size;
char** array;
} string_array;
void my_print_words_array( const string_array *param_1 )
{
for ( int i = 0; i < param_1->size; i++ )
{
puts( param_1->array[i] );
}
}
int main( void )
{
string_array d =
{
.size = 2,
.array = (char *[]){"hello", "world"}
};
my_print_words_array( &d );
return 0 ;
}
The program output is
hello
world

How to initialize global constant variable in main() function using pure C?

How can I do global constant initialization like this? Is it possible at all? Or there is another way to do what I want? I mean I need global parameters gained from main() and they must be constants.
#include <stdio.h>
#include <stdlib.h>
const int var;
int main(int argc, char *argv[]) {
var = atoi(argv[1]);
/* ... */
return 0;
}
I need global parameters gained from main() and they must be constants.
No portable way to do directly as OP wants.
Code needs different access for reading and writing. Effectively hiding the access to the true data.
A close solution it to set and get data via functions defined in another file. Then no way to change data once set and only settable once.
main_var.h
int main_var_get(void);
void main_var_set(int v);
main_var.c
#include <stdlib.h>
#include "main_var.h"
static int var; // This could instead be a struct of many members.
// Or a pointer to a struct with many members.
static int var_init;
int main_var_get(void) {
if (!var_init) {
// Handle call of get before set, perhaps exit or return default value
exit(EXIT_FAILURE);
}
return var;
}
void main_var_set(int v) {
if (var_init) {
// Handle 2nd set, perhaps exit or ignore
exit(EXIT_FAILURE);
}
var = v;
var_init = 1;
}
main.c
#include <stdio.h>
#include "main_var.h"
int main(void) {
main_var_set(42);
...
printf("%d\n", main_var_get());
}
Another is to use a const int *. Access before setting is the same no-no as dereferencing NULL. Attempting to write *main_var_addr is UB like writing any const object.
main_var.h
extern const int *main_var_addr;
void main_var_set(int v);
main_var.c
#include <stdlib.h>
#include "main_var.h"
const int *main_var_addr = NULL;
static int var;
void main_var_set(int v) {
if (main_var_addr) {
// Handle 2nd set attempt, perhaps exit or ignore
exit(EXIT_FAILURE);
}
var = v;
main_var_addr = &var
}
main.c
#include <stdio.h>
#include "main_var.h"
int main(void) {
main_var_set(42);
...
printf("%d\n", *main_var_addr);
}
I don't think C allows you to initialize a constant variable elsewhere. However, you can just change var from const to static.
This is not possible, actually const doesn't mean the variable is constant in C, it's only mean that you are not allowed to change the value of the variable, but someone else could.
Global value are initialize before the main run, that mean you can't initialize at runtime, how this initialization is done is implementation behavior so there is no "pure C" way to do what you ask.
However, I don't see why you could not encapsulate your global:
my_var.h:
int init_my_var(int argc, char **argv);
int get_my_var(void);
my_var.c
#include <stdlib.h>
#include <limits.h>
#include <errno.h>
static int var;
int init_my_var(int argc, char **argv) {
#ifndef NDEBUG
#include <stdbool.h>
#include <assert.h>
{
static bool first = true;
assert(first);
first = false;
}
#endif
if (argc < 2) {
return 1;
}
errno = 0;
long ret = strtol(argv[1], NULL, 10);
if (errno || (ret < INT_MIN || ret > INT_MAX)) {
return 2;
}
var = (int)ret;
return 0;
}
int get_my_var(void) {
return var;
}
main.c:
#include <stdio.h>
int main(void) {
printf("%d\n", get_my_var());
if (init_my_var(2, (char *[]){"", "42"})) {
return EXIT_FAILURE;
}
printf("%d\n", get_my_var());
if (init_my_var(2, (char *[]){"", "0"})) {
return EXIT_FAILURE;
}
}

function pointer not working for int

Im trying to use the power of function pointers, it all went fine until i tried to make the function pointer use a 2nd argument as type int.
The code below generates an error, which is displayed below
In an header file:
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
Error:
error: expected ‘)’ before ‘int’
void (*move)(Unit, int);
^
void (*move)(Unit); works all fine, which surprises me how adding an argument can cause an error.
I call my struct in a C file, by including header and then doing:
Unit units[UNITCOUNT];
units[0].move(&units[0], 1);
Update:
adding:
typedef struct UnitTag Unit
Causes the error to dissapear, however I can no longer use the function as before.
error: incompatible type for argument 1 of ‘units[i].move’
units[0].move(&units[0], 0);
^
note: expected ‘Unit’ but argument is of type ‘struct UnitTag *’
If I'm getting you, you can simply use struct keyword:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag, int);
} Unit;
void Test (struct UnitTag test1, int test2)
{
printf("Test1.x: %d\n", test1.x);
printf("Test1.y: %d\n", test1.y);
printf("Test2 : %d\n", test2);
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(units[0], 3);
}
Output:
Test1.x: 1
Test1.y: 2
Test2 : 3
If you want to pass struct by referebce, simply:
#include <stdio.h>
typedef struct UnitTag {
int x;
int y;
void (*move)(struct UnitTag*, int);
} Unit;
void Test (struct UnitTag *test1, int test2)
{
test1->x = 4;
test1->y = 5;
}
int main(void)
{
Unit units[100];
units[0].move = Test;
units[0].x = 1;
units[0].y = 2;
units[0].move(&units[0], 3);
printf("units[0].x: %d\n", units[0].x);
printf("units[0].y: %d\n", units[0].y);
}
Output is:
units[0].x: 4
units[0].y: 5
You need the prototype for Unit before using it.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit, int);
} Unit;
int main(void)
{
return 0;
}
After the clarification what you wanted to do. It probably makes more sense to give a pointer to Unit, so that the move command which returns void can change something about your object.
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct UnitTag Unit;
typedef struct UnitTag {
int x;
int y;
void (*move)(Unit *, int);
} Unit;
Unit test;
/* some function that corresponds to the interface */
void myMove(Unit *u, int i)
{
u->x = u->x + i;
}
int main(void)
{
/* initialize test struct */
test.x = 0;
test.y = 0;
test.move = myMove;
test.move(&test, 5);
printf("Values after move are (x, y) = (%i, %i).\n", test.x, test.y);
return 0;
}

Dynamic Array of Structures in C

I'm trying to create an array of structures, but I'm not sure how to proceed with declaring an array and mallocing it. Here is the code I have so far:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define MAX_STRING 128
typedef char String[MAX_STRING]
typedef struct {
String Name; //Name of the person
String Best; //Name of the best friend
} Names;
int main(void) {
}
This is an exercise I'm trying to do and the end product should be like this: HERE
#include <stdlib.h>
#include <stdio.h>
#define N 3
typedef struct
{
char* Name; //Why complicate things using a string?
char* Best;
}Names;
int main(void)
{
int i;
//Create an array of pointers.
//Each element of the array is a pointer to a struct "Names"
Names** data = malloc(N*sizeof(Names*));
//data[i] is a array element which points to a single struct "Names".
//Dynamically allocate memory for each struct
for(i=0;i<N;i++)
{
data[i] = malloc(sizeof(Names));
}
//Rest is your assignment
data[0]->Name = "aaaa";
data[0]->Best = "bbbb";
data[1]->Name = "cccc";
data[1]->Best = "dddd";
data[2]->Name = "eeee";
data[2]->Best = "ffff";
for(i=0;i<N;i++)
{
printf("%s\t%s\n",data[i]->Name,data[i]->Best);
}
}
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define MAX_STRING 128
#define NUMBER_OF_STRUCTURES_IN_ARRAY 10
typedef char String[MAX_STRING]
typedef struct {
String Name; //Name of the person
String Best; //Name of the best friend
} Names;
int main(void)
{
int rCode=0;
Names *names_A = NULL;
int index;
names_A = malloc(sizeof(*names_A) * NUMBER_OF_STRUCTURES_IN_ARRAY);
if(NULL == names)
{
rCode=ENOMEM;
fprintf(stderr, "Error: malloc() failed\n");
goto CLEANUP;
}
for(index=0; index < NUMBER_OF_STRUCTURES_IN_ARRAY; ++index)
{
strcpy(names_A[index].Name, "Some Name");
strcpy(names_A[index].Best, "Another Name");
}
CLEANUP:
if(names_A)
free(names_A);
return(rCode);
}

Resources