convert a one line function to a macro in c - c

I have a function which I want to convert to a macro without violating type safety
#define UINTPTR_MAX_XOR_WITH_1 (uintptr_t) (UINTPTR_MAX ^ 1)
struct node
{
unsigned long key;
tbb::atomic<struct node*> lChild; //format <address,flagBit>
tbb::atomic<struct node*> rChild; //format <address,flagBit>
};
struct node* getAddress(struct node* p)
{
return (struct node*)((uintptr_t) p & UINTPTR_MAX_XOR_WITH_1);
}
main()
{
nodeAddr = getAddress(node);
lNodeAddr = getAddress(node->lChild);
}
I try to replace getAddress() function with this macro. I know this macro definition is wrong.
#define getAddress(p) ((struct node*) (uintptr_t) p & UINTPTR_MAX_XOR_WITH_1)
I read this post
Macro vs Function in C
But still couldn't figure how to do it for this case

This is almost equivalent, except that the macro is more permissive than the function when type-checking its argument:
#define getAddress(p) ((struct node*) ((uintptr_t) (struct node*)(p) & UINTPTR_MAX_XOR_WITH_1))
Some C compilers accept static inline, that's not a macro, but it's equivalent to the original function, and will get inlined most of the time in practice:
static inline struct node* getAddress(struct node* p) {
return (struct node*)((uintptr_t) p & UINTPTR_MAX_XOR_WITH_1);
}

Related

Macro to allocate a static array in compile time

Is there a way to allocate a static array in compile time ?
Example:
typedef struct Node
{
struct Node* prev;
struct Node* next;
bool allocated;
void* object;
}node_t;
#define ALLOC( size ) { node_t vec[size]; return &vec[0] }
#define list_const_func_pointers(max_list_size) \
{ \
.maximum_list_size = max_list_size, \
.vectorLL = ALLOC( max_list_size ), \
.init = init_linked_list, \
.my_st_malloc = my_static_malloc \
}
struct static_doublyll_t
{
node_t* head;
node_t* last;
int32_t list_size; // "actual list size"
const uint32_t maximum_list_size; // Tamanho do array de node_t alocado estaticamente.
node_t* vectorLL; // Aponta para uma array de node_t alocado estaticamente.
void (*const init)(static_doublyll_t*);
node_t* (*const my_st_malloc)(static_doublyll_t* l);
static_doublyll_t* this_pointer; // unnecessary because "recursion problem".
};
// Driver code:
#define list_size 20
static static_doublyll_t list = list_const_func_pointers(list_size); // init the const "variables".
Notes:
I need that the compiler return unique memory blocks (statically allocated at compile time) on each macro call.
This macro in the above example is what I need to work:
#define ALLOC( size ) { node_t vec[size]; return &vec[0] }"
I would suggest something more simple.
typedef struct Node
{
struct Node* prev;
struct Node* next;
bool allocated;
void* object;
}node_t;
#define DECLARE(name, max_list_size) \
static node_t node_t##name[max_list_size]; \
struct static_doublyll_t name = \
{ \
.maximum_list_size = max_list_size, \
.vectorLL = node_t##name, \
}
struct static_doublyll_t
{
node_t* head;
node_t* last;
int32_t list_size; // "actual list size"
const uint32_t maximum_list_size; // Tamanho do array de node_t alocado estaticamente.
node_t* vectorLL; // Aponta para uma array de node_t alocado estaticamente.
};
// Driver code:
#define list_size 20
DECLARE(list, list_size);
I need that the compiler return unique memory blocks(statically allocated at compile time) on each macro call.
Macros are not "called" in the same sense as functions, and they do not "return" anything. The compiler expands macro invocations at compile time, and compiles the result as C code, in the context of the surrounding C code.
You are using the macro in a context where it needs to expand to an expression of array or pointer type. Your best bet for that would be to use a compound literal:
#define ALLOC(size) ( (node_t []) { [size - 1] = {0} } )
That will produce an array with static storage duration only at file scope (that is, outside any function). It's unclear from the example code whether that would serve your purpose. I observe, however, that the only other context where what you describe could make sense would be in the initializer of a local object with static storage duration, and if that's what you have then you could consider just moving that out of its function.
Note well that what you describe does not make any sense at all for something that needs to provide a separate array on each call to some function, nor where the size parameter is not a compile-time constant at each invocation. Those kinds of things generally demand dynamic allocation.

standard way to solve "passing argument of function from incompatible pointer type" with function pointers parameter

I have a list module implementing a foward list, like the following (minimal working example):
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
struct list_cell {
void* payload;
struct list_cell* next;
};
struct list {
struct list_cell* head;
int length;
};
typedef bool(*matcher_t)(const void* data);
void* findElementInList(struct list* l, matcher_t matcher) {
struct list_cell* tmp = l->head;
while (tmp != NULL) {
if (matcher(tmp->payload)) {
return tmp->payload;
}
tmp = tmp->next;
}
return NULL;
}
struct person {
char* name;
char* surname;
};
static char* constName = "Thomas";
bool matchByName(const struct person* p) {
printf("comparing %s with %s\n", p->name, constName);
return strcmp(p->name, constName) == 0;
}
int main() {
//initializations (made by hand to have a MWE)
struct person globalThomas = {"Thomas", "Lot"};
struct list* l = (struct list*) malloc(sizeof(struct list));
l->head = (struct list_cell*) malloc(sizeof(struct list_cell));
l->head->payload = &globalThomas;
l->head->next = NULL;
l->length = 1;
void* el = findElementInList(l, matchByName);
if (el != NULL) {
printf("found Thomas!\n");
} else {
printf("Thomas not found!\n");
}
//deallocation
free(l->head);
free(l);
}
Compiling this with gcc will generate the following warning:
list.c:57:34: warning: passing argument 2 of ‘findElementInList’ from incompatible pointer type [-Wincompatible-pointer-types]
void* el = findElementInList(l, matchByName);
^
list.c:18:7: note: expected ‘matcher_t {aka _Bool (*)(const void *)}’ but argument is of type ‘_Bool (*)(const struct person *)’
void* findElementInList(struct list* l, matcher_t matcher) {
This happens because matcher_t defined its parameter with void* but we inject struct person*. I want to solve this warning but I'm uncertain about the best way to solve it. Clearly (as proposed in in this SO answer) I can solve it by changing matchByName signature to matchByName(const void* p) and by casting void* pointer into struct person*. But I feel like this make the function the function purpose: by looking at the header only, I can't determine what is the input of the function. Leaving struct person* makes it instead clear.
So my question is: What the best method to solve this warning? What do you usually do to solve it? Is there another way to solve it aside changing matchByName signature?.
Thanks for any kind reply
PS: the objective here is to add -Werror flag in compilation in order to make the code more robust.
In C, this is the best you can do:
bool matchByName(const void *px)
{
const struct person *p = px;
printf("comparing %s with %s\n", p->name, constName);
return strcmp(p->name, constName) == 0;
}
You have to make the function signature match its caller's expectation, and its caller is a pseudo-generic so it has to pass const void * rather than a concrete type. There is no way around this. But by assigning the untyped parameter to a variable with the correct concrete type as the first statement in the function, you make things clear for a human reading the code, and that's the best you can do.
Incidentally, you really ought to get rid of that constName global variable, by having findElementInList accept an additional const void * parameter that it passes down to the matcher unmolested:
bool matchByName(const void *px, const void *cx)
{
const struct person *p = px;
const char *nameToMatch = cx;
printf("comparing %s with %s\n", p->name, constName);
return strcmp(p->name, constName) == 0;
}
void *findElementInList(struct list *l, matcher_t matcher,
const void *matcher_args)
{
struct list_cell *tmp = l->head;
while (tmp) {
if (matcher(tmp->payload, matcher_args)) {
return tmp->payload;
}
tmp = tmp->next;
}
return 0;
}
Please also note the stylistic corrections I have made to your code:
For historical reasons, in C preferred style is to put the opening curly brace of a function definition on its own line, even if all other opening curly braces are "cuddled" with their statement head. In some code you will also see the return type on its own line, which I think makes sense when there are often a lot of qualifiers on the return type, but don't do that unless you're going to do it consistently throughout the entire codebase.
The * in a pointer declaration binds to the thing on its right, not the thing on its left, so it should always be written with a space to its left and no space to its right. Everyone who says otherwise is wrong.
Explicit comparisons of pointers with NULL/0 are bad style; just write if (ptr) (or, in this case, while (ptr)). I personally think NULL itself is bad style and you should write 0 instead, but reasonable people can disagree about that.
Function pointers are only compatible if their types are identical. To wildly convert from one type to the other is strictly speaking undefined behavior (although some cases may work as a non-standard extension on many systems).
So you will either need to use the very same type in all cases, or write a wrapper function such as this:
inline bool matchByName (const void* p)
{
return matchByNamePerson (p);
}
That being said, generic programming with void pointers is old-fashioned C and quite dangerous. Nowadays you should preferably write fully type-safe code instead:
_Generic matchByName ((p), \
const struct person*: matchByNamePerson, \
const struct thing*: matchByNameThing)(p)
A solution that may preserve both warnign absence and code readability might be the introduction of the following macro:
#define PDOC(...) void*
//function declaration
bool matchByName(const PDOC(struct person*) p);
//function definition
bool matchByName(const PDOC(struct person*) _p) {
const struct person* p = (const struct person*) _p;
//insert awesome code here
}
In this way you don't generate the warning but you preserve signature readability (although it costs you some addtional types).

Simulate a Java generic interface and abstract data type in C

I am trying to port a library written in Java into C programming language. For Java interface, I intend to use a struct of function-pointers to replace, for instance:
// Java code
public interface ActionsFunction {
Set<Action> actions(Object s);
}
/* C code */
typedef struct ActionsFunction {
List* (*actions)(void* s);
void (*clear_actions)(struct List **list); /* Since C doesn't have garbage collector */
} ActionsFunction;
My question is: whether it is a suitable solution or not, and how can I simulate a generic interface such as:
public interface List <E> {
void add(E x);
Iterator<E> iterator();
}
UPDATE:
I also have to face with another problem: implementing generic abstract data structure like List, Queue, Stack, etc since the C standard library lacks of those implementation. My approach is client code should pass the pointer of its data accompanying with its size, thus allowing library to hold that one without specifying its type. One more time, it just my idea. I need your advices for the design as well as implementing technique.
My initial porting code can be found at:
https://github.com/PhamPhiLong/AIMA
generic abstract data structure can be found in utility sub folder.
Here's a very brief example using macros to accomplish something like this. This can get hairy pretty quick, but if done correctly, you can maintain complete static type safety.
#include <stdlib.h>
#include <stdio.h>
#define list_type(type) struct __list_##type
/* A generic list node that keeps 'type' by value. */
#define define_list_val(type) \
list_type(type) { \
list_type(type) *next; \
type value; \
}
#define list_add(plist, node) \
do \
{ \
typeof(plist) p; \
for (p = plist; *p != NULL; p = &(*p)->next) ; \
*p = node; \
node->next = NULL; \
} while(0)
#define list_foreach(plist, p) \
for (p = *plist; p != NULL; p = p->next)
define_list_val(int) *g_list_ints;
define_list_val(float) *g_list_floats;
int main(void)
{
list_type(int) *node;
node = malloc(sizeof(*node));
node->value = 42;
list_add(&g_list_ints, node);
node = malloc(sizeof(*node));
node->value = 66;
list_add(&g_list_ints, node);
list_foreach(&g_list_ints, node) {
printf("Node: %d\n", node->value);
}
return 0;
}
There are a few common ways to do generic-ish programming in C. I would expect to use one or more of the following methods in trying to accomplish the task you've described.
MACROS: One is to use macros. In this example, MAX looks like a function, but operate on anything that can be compared with the ">" operator:
#define MAX(a,b) ((a) > (b) ? (a) : (b))
int i;
float f;
unsigned char b;
f = MAX(7.4, 2.5)
i = MAX(3, 4)
b = MAX(10, 20)
VOID *: Another method is to use void * pointers for representing generic data, and then pass function pointers into your algorithms to operate on the data. Look up the <stdlib.h> function qsort for a classic example of this technique.
UNIONS: Yet another, though probably seen less often, technique is to use unions to hold data of multiple different types. This makes your algorithms that operate on the data kinda ugly though and might not save much coding:
enum { VAR_DOUBLE, VAR_INT, VAR_STRING }
/* Declare a generic container struct for any type of data you want to operate on */
struct VarType
{
int type;
union data
{
double d;
int i;
char * sptr;
};
}
int main(){
VarType x;
x.data.d = 1.75;
x.type = VAR_DOUBLE;
/* call some function that sorts out what to do based on value of x.type */
my_function( x );
}
CLEVER CASTING & POINTER MATH It's a pretty common idiom to see data structures with functions that operate on a specific kind of struct and then require that the struct by included in your struct to do anything useful.
The easy way to do this, is the force the struct that allows insertion into the data structure to be the first member of your derived type. Then you can seamless cast back & forth between the two. The more versatile way is to use 'offsetof'. Here's a simple example.
For example:
/* Simple types */
struct listNode { struct listNode * next; struct listNode * prev };
struct list { struct listNode dummy; }
/* Functions that operate on those types */
int append( struct list * theList, struct listNode * theNode );
listNode * first( struct list *theList );
/* To use, you must do something like this: */
/* Define your own type that includes a list node */
typedef struct {
int x;
double y;
char name[16];
struct listNode node;
} MyCoolType;
int main() {
struct list myList;
MyCoolType coolObject;
MyCoolType * ptr;
/* Add the 'coolObject's 'listNode' member to the list */
appendList( &myList, &coolObject.node );
/* Use ugly casting & pointer math to get back you your original type
You may want to google 'offsetof' here. */
ptr = (MyCoolType *) ( (char*) first( &myList )
- offsetof(MyCoolType,node);
}
The libev documentation has some more good examples of this last technique:
http://search.cpan.org/dist/EV/libev/ev.pod#COMMON_OR_USEFUL_IDIOMS_(OR_BOTH)

getting C error: conversion to non-scalar type requested

Hey I am getting this error:
error: conversion to non-scalar type requested
Here are my structs:
typedef struct value_t value;
struct value{
void* x;
int y;
value* next;
value* prev;
};
typedef struct key_t key;
struct key{
int x;
value * values;
key* next;
key* prev;
};
Here is the code that is giving me problems:
struct key new_node = (struct key) calloc(1, sizeof(struct key));
struct key* curr_node = head;
new_node.key = new_key;
struct value head_value = (struct value) calloc(1, sizeof(struct value))
Am I not suppose to use calloc on structs? Also, I have a struct that I have created and then I want to set that to a pointer of that same struct type but getting an error. This is an example of what I am doing:
struct value x;
struct value* y = *x;
this gives me this error
error: invalid type argument of ‘unary *’
When I do y = x, I get this warning:
warning: assignment from incompatible pointer type
You are trying to assign a pointer expression (the return type of malloc() and friends is void*) to a struct type (struct new_node). That is nonsense. Also: the cast is not needed (and possibly dangerous, since it can hide errors)
struct key *new_node = calloc(1, sizeof *new_node);
the same problem with the other malloc() line:
struct value *head_value = calloc(1, sizeof *head_value);
More errors: You are omitting the 'struct' keyword (which is allowed in C++, but nonsense in C):
struct key{
int x;
struct value *values;
struct key *next;
struct key *prev;
};
UPDATE: using structs and pointers to struct.
struct key the_struct;
struct key other_struct;
struct key *the_pointer;
the_pointer = &other_struct; // a pointer should point to something
the_struct.x = 42;
the_pointer->x = the_struct.x;
/* a->b can be seen as shorthand for (*a).b :: */
(*thepointer).x = the_struct.x;
/* and for the pointer members :: */
the_struct.next = the_pointer;
the_pointer->next = malloc (sizeof *the_pointer->next);
I don't think you've correctly understood typedefs.
The common idiom with using typedefs for convenience naming is this:
struct foo {
int something;
};
typedef struct foo foo_t;
Then you use the type foo_t instead of the less convenient struct foo.
For convenience, you can combine the struct declaration and the typedef into one block:
typedef struct {
int something;
} foo_t;
This defines a foo_t just like the above.
The last token on the typedef line is the name you're assigning. I have no idea what the code you wrote is actually doing to your namespace, but I doubt it's what you want.
Now, as for the code itself: calloc returns a pointer, which means both your cast and your storage type should be struct key* (or, if you fix your naming, key_t). The correct line is struct key* new_node = (struct key*)calloc(1, sizeof(struct key));
For your second, independent, issue, the last line should be struct value* y = &x;. You want y to store the address of x, not the thing at address x. The error message indicates this - you are misusing the unary star operator to attempt to dereference a non-pointer variable.
struct key new_node = (struct key) calloc(1, sizeof(struct key));
calloc returns a pointer value (void *), which you are trying to convert and assign to an aggregate (IOW, non-scalar) type (struct key). To fix this, change the type of new_node to struct key * and rewrite your allocation as follows:
struct key *new_node = calloc(1, sizeof *new_node);
Two things to note. First of all, ditch the cast expression. malloc, calloc, and realloc all return void *, which can be assigned to any object pointer type without need for a cast1. In fact, the presence of a cast can potentially mask an error if you forget to include stdlib.h or otherwise don't have a declaration for malloc in scope2.
Secondly, note that I use the expression *new_node as the argument to sizeof, rather than (struct key). sizeof doesn't evaluate it's operator (unless it's a variable array type, which this isn't); it just computes the type of the expression. Since the type of the expression *new_node is struct key, sizeof will return the correct number of bytes to store that object. It can save some maintenance headaches if your code is structured like
T *foo;
... // more than a few lines of code
foo = malloc(sizeof (T))
and you change the type of foo in the declaration, but forget to update the malloc call.
Also, it's not clear what you're trying to accomplish with your typedefs and struct definitions. The code
typedef struct value_t value;
struct value{
void* x;
int y;
value* next;
value* prev;
};
isn't doing what you think it is. You're creating a typedef name value which is a synonym for an as-yet-undefined type struct value_t. This value type is different from the struct value type you create later (typedef names and struct tags live in different namespaces). Rewrite your structs to follow this model:
struct value_t {
void *x;
int y;
struct value_t *next;
struct value_t *prev;
};
typedef struct value_t value;
Also, life will be easier if you write your declarations so that the * is associated with the declarator, not the type specifier3. A declaration like T* p is parsed as though it were written T (*p). This will save you the embarrassment of writing int* a, b; and expecting both a and b to be pointers (b is just a regular int).
1 - This is one area where C and C++ differ; C++ does not allow implicit conversions between void * and other object pointer types, so if you compile this as C++ code, you'll get an error at compile time. Also, before the 1989 standard was adopted, the *alloc functions returned char *, so in those days a cast was required if you were assigning to a different pointer type. This should only be an issue if you're working on a very old system.
2 - Up until the 1999 standard, if the compiler saw a function call without a preceding declaration, it assumed the function returned an int (which is why you still occasionally see examples like
main()
{
...
}
in some tutorials; main is implicitly typed to return int. As of C99, this is no longer allowed). So if you forget to include stdlib.h and call calloc (and you're not compiling as C99), the compiler will assume the function returns an int and generate the machine code accordingly. If you leave the cast off, the compiler will issue a diagnostic to the effect that you're trying to assign an int value to a pointer, which is not allowed. If you leave the cast in, the code will compile but the pointer value may be munged at runtime (conversions of pointers to int and back to pointers again is not guaranteed to be meaningful).
3 - There are some rare instances, limited to C++, where the T* p style can make code a little more clear, but in general you're better off following the T *p style. Yes, that's a personal opinion, but one that's backed up by a non-trivial amount of experience.
calloc(3) returns a pointer to the memory it allocates.
struct key new_node = (struct key) calloc(1, sizeof(struct key));
should be
struct key* new_node = calloc(1, sizeof(struct key));
You should not assign a pointer to a non-pointer variable. Change new_node to be a pointer.
Also, to use the address of variable, you need &, not *, so change it to struct value* y = &x;
Edit: your typedefs are wrong too. reverse them.
For the second problem, you want to use an ampersand & instead of an astrisk "*`. An astrisk dereferences a pointer, an ampersand gives you the pointer from the value.

C dynamic array initialization problem

I'm having a problem initializing an array of structs in my C program. Here's the function where it gets initialized:
void InitializeBPStructures() {
SatCounterTable = (struct SatCounterTableEntry *)malloc(sizeof(struct SatCounterTableEntry) * Counter_Count);
}
Counter_Count is an integer global variable and SatCounterTable is declared earlier in the C source file as
static struct SatCounterTableEntry* SatCounterTable;
and if it's relevant this is my SatCounterTable struct
struct SatCounterTableEntry {
enum SatCounter_State Predict_State;
md_addr_t tag;
};
md_addr_t is just a label for an unsigned int corresponding to a memory address
The problem is that when I try and compile, I get the following error
sim-safe.c:129: error: expected expression before ‘=’ token
And the array initialization in my IntitializeBPStructures() is on line 129. I'm not sure why this line is a problem. Any ideas?
EDIT:
Here's some additional lines of code around the function
struct SatCounterTableEntry
{
enum SatCounter_State Predict_State;
md_addr_t tag;
};
/* simulated registers */
static struct regs_t regs;
/* simulated memory */
static struct mem_t *mem = NULL;
/* track number of refs */
static counter_t sim_num_refs = 0;
/* maximum number of inst's to execute */
static unsigned int max_insts;
static struct SatCounterTableEntry* SatCounterTable;
void InitializeBPStructures()
{
SatCounterTable = (struct SatCounterTableEntry *)malloc(sizeof(struct SatCounterTableEntry) * Counter_Count);
}
void BranchPredict(md_addr_t PC, md_addr_t nextPC, enum Branch_Result result)
{
if (result == N)
sim_num_mispred_static++;
if (result != (myrand() % 2))
sim_num_mispred_random++;
sim_num_br++;
}
You're missing a semicolon at line 126.
Edit: new idea
Do you perhaps have a #define with an extra =?
#define Counter_Count = 42; /* WRONG */
#define Counter_Count = 42 /* WRONG */
#define Counter_Count 42; /* WRONG, but it works some time */
#define Counter_Count 42 /* CORRECT */
SatCounterTable is declared earlier in the C source file as
static struct SatCounterTableEntry* SatCounterTable;
Is that declaration made at file scope or is it within another function? If the latter, then the SatCounterTable name won't be visible inside InitializeBPStructures().
SatCounterTable = (struct SatCounterTableEntry *)malloc(sizeof(struct SatCounterTableEntry) * Counter_Count);
Ugh. Do me a favor and rewrite that as
SatCounterTable = malloc(sizeof *SatCounterTable * Counter_Count);
You really don't need to cast the result of malloc(); that hasn't been necessary since C89 was adopted. And using sizeof on the object being allocated rather than the type can save you some heartburn (if nothing else, it saves some keystrokes).
The error text suggests that something hasn't been defined properly prior to this call; for some reason it isn't recognizing SatCounterTable. I think pmg's on the right track. You must be missing a semicolon or a curly bracket or something prior to this call.
The C compiler you are using has some reason to believe that SatCounterTable is not an lvalue or primary expression. Given how your variables are named (confusingly I might add), is it possible that you defined a variable at a closer scope also with the name SatCounterTable, such that SatCounterTable is not an assignable expression?
Edit: I would also seriously consider pmg's answer.
I compiled this code:
#include <stdlib.h>
typedef unsigned int md_addr_t;
typedef unsigned int counter_t;
int myrand() { return 0; }
struct SatCounterTableEntry
{
enum SatCounter_State Predict_State;
md_addr_t tag;
};
static unsigned int Counter_Count;
static unsigned int sim_num_mispred_static;
static unsigned int sim_num_mispred_random;
static unsigned int sim_num_br;
static const unsigned int N = 0;
/* simulated registers */
static struct regs_t {} regs;
/* simulated memory */
static struct mem_t *mem = NULL;
/* track number of refs */
static counter_t sim_num_refs = 0;
/* maximum number of inst's to execute */
static unsigned int max_insts;
static struct SatCounterTableEntry* SatCounterTable;
void InitializeBPStructures()
{
SatCounterTable = (struct SatCounterTableEntry *)malloc(sizeof(struct SatCounterTableEntry) * Counter_Count);
}
void BranchPredict(md_addr_t PC, md_addr_t nextPC, enum Branch_Result result)
{
if (result == N)
sim_num_mispred_static++;
if (result != (myrand() % 2))
sim_num_mispred_random++;
sim_num_br++;
}
int main() {
}
You must have errors elsewhere in your code. Have I mentioned how incredibly hideous this design is? You should really be using objects for this.

Resources