It is possible to bound the c integer range using enums? - c

I'm not quite into enums, but I need to create a datatype in C that represents numbers with just one digit.
I have tried with enums like:
enum digit {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
Obiously the compiler interpret this as assigning the enumeration to a non-specified value.
Is there any way to "cheat" the compiler to let me do this?
Is there any other possible way to bound the range of an integer?

HAL2000's answer is good, still I will elaborate on it. As discussed in the comments, assert() is only the correct way if the setter is expected to be always called with a number between 0 and 9 and failure to do so is considered a programming error.
If you want validation instead (only set the value when it's in the correct range, otherwise report an error to the calling code), you'd change the setter like this:
static inline int
digit_set(struct digit *d, unsigned int val)
{
if (val > 9) return -1;
d->value = val;
return 0;
}
You can pick the returned values freely, -1 for error and 0 for success is very widespread in C, so I picked this. You could also prefer 1 for success and 0 for error, which would make your return value directly usable in a boolean expression.
This whole idea has a little weakness: Nothing will ever prevent you from directly setting the value member, bypassing your setter. Now, there's a solution to this as well, but it comes with costs. You can hide the definition of the struct in a separate translation unit, therefore calling code doesn't ever see its internals. It could look like this:
digit.h:
#ifndef DIGIT_H
#define DIGIT_H
typedef struct Digit Digit;
Digit *Digit_create(int val);
int Digit_setVal(Digit *self, int val);
int Digit_val(const Digit *self);
void Digit_destroy(Digit *self);
#endif
dgit.c:
#include <stdlib.h>
#include "digit.h"
struct Digit {
int val;
};
Digit *Digit_create(int val)
{
if (val < 0 || val > 9) return 0;
Digit *self = malloc(sizeof *self);
if (!self) return 0;
self->val = val;
return self;
}
int Digit_setVal(Digit *self, int val)
{
if (val < 0 || val > 9) return -1;
self->val = val;
return 0;
}
int Digit_val(const Digit *self)
{
return self->val;
}
void Digit_destroy(Digit *self)
{
free(self);
}
The cost:
This way of information hiding unfortunately requires a separate translation unit and dynamic allocation of the objects, which is expensive. I personally wouldn't recommend it for such a simple thing. But if you're e.g. writing a library and want to enforce it can't be used in a wrong way, it's worth a thought.
This basically is OOP realized in C, and for more complex structures, it really gives some benefit (also in structuring your program).
In the example above, the "constructor" Digit_create() makes sure to only ever construct valid objects. This is generally a good idea for robust code in more complex scenarios.
If you decide to implement something like this, make sure the deallocation function (here Digit_destroy()) works the same way as free(): It should silently ignore a null pointer. This is trivial here, because there's nothing else to do than calling free().

I recomend to use an abstract datatype with setters and getters if you really have to use range checking (otherwise use char/int and make sure not to write buggy code):
/* digit.h */
#include <assert.h>
struct digit
{
unsigned int value;
};
static inline unsigned int
digit_set(struct digit *d, unsigned int val)
{
assert(val <= 9);
d->val = val;
return val;
}
static inline unsigned int
digit_get(const struct digit *d)
{
return d->val;
}

You can't limit the range of values for either a type or variable in C unfortunately.
I would do a typedef char digit or typedef int digit and use that as the type for your variables, being sure not to assign anything besides 0 to 9 to your value. Note that this will not do any typechecking, and merely serves as documentation for you.

Related

In C program, how to dynamically select data type

I have encountered a problem, and I haven't found an answer in the internet and forums. I hope you can help.
There is an interface requirement to update the LOG parameter. The interface passes in the parameter index and the value to be added, and the interface adds the value to the corresponding parameter. The interface requires simple implementation and no complicated judgments.
My idea is to create a mapping table that records the starting address and data type of each parameter. When the interface is called, the parameter address is obtained according to the parameter index and forced to be converted to the corresponding type, and then the addition operation is performed.
The problem with this solution is that the increase_log_info function is too complicated. How to simplify the increase_log_info function in C language? How parameter types can be mapped directly, rather than through an if...else condition.
Thanks in advance.
Note:
T_LOG_INFO is data structure definition and cannot be changed.
LOG_INFO_INCREASE is an update parameter interface provided
externally and cannot be changed.
Other codes can be changed.
#pragma once
/********************************can not be change, begin**********************************/
/* T_LOG_INFO is data structure definition and cannot be changed. */
typedef struct
{
unsigned short tx_num;
unsigned int tx_bytes;
unsigned short rx_num;
unsigned int rx_bytes;
unsigned char discard_num;
unsigned int discard_bytes;
// There are many parameters behind, not listed
}T_LOG_INFO;
T_LOG_INFO g_log_info;
/* This macro is called very frequently, and efficiency needs to be considered.
** LOG_INFO_INCREASE is an update parameter interface provided externally and cannot be changed. */
//#define LOG_INFO_INCREASE(para_idx, inc_val)
/********************************can not be change, end**********************************/
/********************************an alternative, begin**********************************/
enum
{
LOG_PARA_IDX_TX_NUM,
LOG_PARA_IDX_TX_BYTES,
LOG_PARA_IDX_RX_NUM,
LOG_PARA_IDX_RX_BYTES,
LOG_PARA_IDX_DISCARD_NUM,
LOG_PARA_IDX_DISCARD_BYTES,
LOG_PARA_IDX_MAX
};
enum
{
DATA_TYPE_U8,
DATA_TYPE_U16,
DATA_TYPE_U32
};
typedef struct
{
/* Indicates the offset of this parameter in the structure. */
unsigned char offset;
/* Indicates the data type of the parameter. */
unsigned char data_type;
}T_PARA_MAPPING;
/* This table can also be calculated during system initialization. */
T_PARA_MAPPING g_para_mapping_table[LOG_PARA_IDX_MAX] =
{
{0, DATA_TYPE_U16}, // LOG_PARA_IDX_TX_NUM
{4, DATA_TYPE_U32}, // LOG_PARA_IDX_TX_BYTES
{8, DATA_TYPE_U16}, // LOG_PARA_IDX_RX_NUM
{12, DATA_TYPE_U32}, // LOG_PARA_IDX_RX_BYTES
{16, DATA_TYPE_U8}, // LOG_PARA_IDX_DISCARD_NUM
{20, DATA_TYPE_U32} // LOG_PARA_IDX_DISCARD_BYTES
};
/* How to simplify the function??? especially to remove the judgment. */
static inline void increase_log_info(unsigned int para_idx, unsigned inc_val)
{
unsigned int data_type = g_para_mapping_table[para_idx].data_type;
/* Get the parameter address and cast it to the corresponding type pointer before adding. */
if (data_type == DATA_TYPE_U8)
{
*((unsigned char*)(((unsigned char*)&g_log_info) + g_para_mapping_table[para_idx].offset)) += inc_val;
}
else if (data_type == DATA_TYPE_U16)
{
*((unsigned short*)(((unsigned char*)&g_log_info) + g_para_mapping_table[para_idx].offset)) += inc_val;
}
else
{
*((unsigned int*)(((unsigned char*)&g_log_info) + g_para_mapping_table[para_idx].offset)) += inc_val;
}
}
/* This macro is called very frequently, and efficiency needs to be considered. */
#define LOG_INFO_INCREASE(para_idx, inc_val) increase_log_info(para_idx, inc_val)
/********************************an alternative, end**********************************/
/********************************test case, begin**********************************/
void increase_log_info_test()
{
LOG_INFO_INCREASE(LOG_PARA_IDX_TX_NUM, 1);
LOG_INFO_INCREASE(LOG_PARA_IDX_TX_NUM, 2);
LOG_INFO_INCREASE(LOG_PARA_IDX_TX_NUM, 3);
LOG_INFO_INCREASE(LOG_PARA_IDX_RX_BYTES, 10);
LOG_INFO_INCREASE(LOG_PARA_IDX_RX_BYTES, 20);
LOG_INFO_INCREASE(LOG_PARA_IDX_RX_BYTES, 30);
}
/********************************test case, end**********************************/
Quick answer with, maybe, syntax errors. But I hope the idea can be grasped.
I would prepare an array with a "datatype" for every member of the T_LOG_INFO struct:
{
unsigned short tx_num;
unsigned int tx_bytes;
unsigned short rx_num;
...
}
Copy/paste the above struct and, with a lot of editing, the array would be declared like this:
const char datatypes[LOG_PARA_IDX_MAX] = {
/* unsigned short tx_num; */ 2,
/* unsigned int tx_bytes; */ 4,
/* unsigned short rx_num; */ 2,
...
}
For lazyness, I used numbers like 2, 4 and so on. They indicate mainly the length, but they can carry other info (20=array of 20 char...).
Then I would declare another data structure (the final one):
struct datadesc {
int addr;
char kind;
} datadesc_array[LOG_PARA_IDX_MAX];
Prepare the table in code (the program itself) with:
address=&g_log_info;
for (int i=0; i<LOG_PARA_IDX_MAX; i++) {
datadesc_array[i].addr = address;
datadesc_array[i].kind = datatypes[i];
address += datatypes[i]; // simple like this if datatypes[] only accounts for length...
}
At this point, when you receive a command, you do:
param_addr = datadesc[para_idx].addr;
param_kind = datadesc[para_idx].kind;
switch (param_kind) {
case 2: // unsigned short
*(short*) param_addr = ...
break;
case 4: // unsigned int
*(unsigned int*) param_addr = ...
}
This way you have a reduced set of cases, just one for every data type you cope with. The only long work is done while preparing the datatypes[] array,
Basically, you can't. Data types in C are a purely static, compile-time construct. There's no such thing as a variable that holds a type or anything like that.
So you fundamentally can't avoid a chain of ifs, or else a switch, with the code for each different type written out separately. In principle you can avoid some of the repetition using macros, but that may actually end up being harder to read and understand.
The efficiency isn't so bad, though. A modern compiler is likely to handle an if chain in an efficient way, and switch might be even better.
Given this, your array of offsets and types may be unnecessary complexity. I would start with something much simpler, albeit longer:
void increase_log_info(unsigned int para_idx, unsigned inc_val) {
switch (para_idx) {
case LOG_PARA_IDX_TX_NUM:
g_log_info.tx_num += inc_val;
break;
case LOG_PARA_IDX_TX_BYTES:
g_log_info.tx_bytes += inc_val;
break;
// ...
}
}
It'll probably compile into a jump table. That's probably more efficient than what you have, as we don't have to keep accessing the mapping table somewhere else in memory and doing the corresponding address calculations. If it really can be proved to be too slow, you could consider some alternatives, but don't optimize prematurely!
This also has the advantage of being robust if the offset or types of any of the g_log_info members changes. In your code, you have to remember to manually update your mapping table, or else face very confusing bugs which the compiler will give you no help in detecting.
If you have an extremely large number of members, consider generating this function's C code with a script instead of by hand.
If this is inlined and called with a constant para_idx value, you can expect the compiler to propagate the constant and emit only the code to update the specific member in question.

c function to return one of two possible types

I currently use three different functions to return a numeric value (one returns a double, the other two return a long):
int main(void)
{
// lots of code
dRate = funcGetInterestRate();
lMonths = funcGetTerm();
lPrincipal = funcGetPrincipal();
// lots of code
return 0;
}
The three functions code is about 90% the same so I would like to consolidate into 1 function. I want to pass a value flag to a single function something like this:
if "1" passed, determine interest rate, return a double
if "2" passed, determine term of loan, return a long
if "3" passed, determine principal of loan, return a long
I only want to return 1 value ever from the function when it is called, but the value I want to return can be either a double or a long. I want to do something like this:
void funcFunction(value passed to determine either long or double)
{
// lots of code
if (foo)
return double value;
else
return long value;
}
Is there an easy way to do this?
A function's return type is fixed at compile time. You can't change the return type based on the parameters you pass in.
However, since your main goal is to remove repeated code in the functions and consolidate them, this can be addressed in a different way. In other words, this is an XY problem.
What you can do in your case is extract the common code in each of your three functions into a separate function, then the three original functions can call the common function to do most of the work, then extract the part they need and return that.
For example:
struct loan {
double rate;
long term;
long principal;
};
void calcLoan(struct loan *loan)
{
// do stuff
loan->rate = // some value
loan->term = // some value
loan->principal = // some value
}
double funcGetInterestRate()
{
struct loan loan;
calcLoan(&loan);
return loan.rate;
}
long funcGetTerm()
{
struct loan loan;
calcLoan(&loan);
return loan.term;
}
long funcGetPrincipal()
{
struct loan loan;
calcLoan(&loan);
return loan.principal;
}
No, C does not allow this. The return type is in the function declaration (which you have as void).
Slightly easier is to provide two pointers to variables and indicate which one to use in the return value:
int funcFunction(yourArgument, long *longResult, double *dblResult)
{
// lots of code
if (foo)
{
*dblResult = value;
return 1;
} else
{
*longResult = otherValue;
return 0;
}
}
(And possibly you can even use a union.)
However ... I had to use value and otherValue as inside the function you cannot use the same variable to hold either a long or a double. You can – again, with a union – but this is stressing the eaze of having only one single function to the breaking point.
You might consider returning some tagged union. The Glib GVariant type could be inspirational, and since Glib is free software, you could study its source code. See also this answer.
So you would declare some public struct with an anonymous union inside:
struct choice_st {
bool islong;
union {
long i; // valid when islong is true
double d; // valid when islong is false
}
}
and you could return a value of that struct choice_st.
struct choice_st res;
if (foo) {
res.islong = true;
res.i = somelong;
return res;
}
else {
res.islong = false;
res.d = somedouble;
return res;
}
You might also decide to use C dynamic memory allocation, return a freshly malloc-ed pointer to struct choice_st, and adopt a convention about who is responsible of free-ing that pointer. (BTW, GVariant is doing something similar to this).
You sort of can do this. It's easier to show than explain, but I'll add an explanation if this isn't clear:
void add_or_divide_by_xor(unsigned int a, unsigned int b, unsigned short c,
unsigned long *add, unsigned double *divide) {
unsigned int xor = a ^ b;
if (add != NULL) {
*add = xor + c;
}
if (divide != NULL) {
*divide = (double)xor / (double)c;
}
}
Called:
unsigned long add;
unsigned double divide;
add_or_divide_by_xor(5, 17, 4, &add, NULL);
add_or_divide_by_xor(17, 6, 4, NULL, &divide);
Depending on your platform, double might be a superset of long. You should already know whether this is true (because you know what your algorithms do, and what their possible output values are); if you don't, consider the following:
double can represent integers up to 253 exactly
long is either a 32-bit or a 64-bit type
So if your long values are 32-bit, you can just always return double from your functions, and cast it to long outside your functions, where needed.
You could try something like this.
#include <stdio.h>
void* func1(int key){
static double interest;
static long term;
static long principle;
//your common code to modify values of interest, term and principle
//
//Let us give them some dummy values for demonstration
interest = 34.29347;
term = 5843535;
principle = 7397930;
//conditions
if(key == 1){
return &interest;
}
else if(key == 2){
return &term;
}else if(key == 3){
return &principle;
}else printf("%s\n","error!!");
}
int main()
{
printf("%f\n",*(double*)func1(1));
printf("%ld\n",*(long*)func1(2));
printf("%ld\n",*(long*)func1(3));
func1(4);
return 0;
}
Output
34.293470
5843535
7397930
error!!

C - Hashing Struct with n amount of unsigned int properties

I have a struct:
struct A
{
unsigned int a, b, c, d, ...
}
I want to make a function:
unsigned int A_hash(const A* const var)
{
return ...
}
The number returned needs to be very very large as modulus for HashTable insertion will not work properly if A_hash(var) < myHashTable.capacity.
I've seen questions like this before like "Hash function that takes in two integers", "hash function that takes in five integers", etc but what aboutn integers? I'm looking for a more general algorithm for decent hashing. It doesn't need to be enterprise-level.
I was thinking perhaps start with a massive number like
return (0x7FFFFFFFF & a) + (0x7FFFFFFFF & b) + ...
but I don't think this will be good enough. I also don't know how to stop the A_hash function from overflowing but that may be another problem all together.
I think implicitly you are asking how it is possible to treat the entire object just like a long byte-stream, like #bruceg explained. If I'm wrong, then you might as well ignore this answer, because this is what I will address. Note that this solution does not apply merely for hashing, but for anything that requires you to treat data like bytes (such as copying from/writing to memory or files).
I think what you are looking for is merely reading byte by byte. For this you can insipre yourself from std::ostream::write (which is a C++ method though). For example, you could write A_hash in such a way that you could invoke it like this :
int hash = A_hash((char*)&a, sizeof(a)); // where 'a' is of type 'struct A'.
You could write A_hash, for example, like this:
unsigned int A_hash(char* data, unsigned int dataSize)
{
unsigned int hash = someValue;
for (unsigned int i = 0; i < dataSize; ++i)
{
char byte = data[i];
doSomethingWith(hash);
}
return hash;
}
The great advantage of this method is that you don't need to rewrite the function if you add/remove fields to your struct ; sizeof(A) will expand/reduce at compile-time. The other great advantage is that it works for any value, so you can reuse that function with any type you want, including int, another struct, an enum, a pointer, ...

Why are function pointers useful?

So, I was looking over function pointers, and in the examples I have seen, particularly in this answer here. They seem rather redundant.
For example, if I have this code:
int addInt(int n, int m) {
return n+m;
}
int (*functionPtr)(int,int);
functionPtr = &addInt;
int sum = (*functionPtr)(2, 3); // sum == 5
It seems here that the creating of the function pointer has no purpose, wouldn't it be easier just to do this?
int sum = addInt(2, 3); // sum == 5
If so, then why would you need to use them, so what purpose would they serve? (and why would you need to pass function pointers to other functions)
Simple examples of pointers seem similarly useless. It's when you start doing more complicated things that it helps. For example:
// Elsewhere in the code, there's a sum_without_safety function that blindly
// adds the two numbers, and a sum_with_safety function that validates the
// numbers before adding them.
int (*sum_function)(int, int);
if(needs_safety) {
sum_function = sum_with_safety;
}
else {
sum_function = sum_without_safety;
}
int sum = sum_function(2, 3);
Or:
// This is an array of functions. We'll choose which one to call based on
// the value of index.
int (*sum_functions)(int, int)[] = { ...a bunch of different sum functions... };
int (*sum_function)(int, int) = sum_functions[index];
int sum = sum_function(2, 3);
Or:
// This is a poor man's object system. Each number struct carries a table of
// function pointers for various operations; you can look up the appropriate
// function and call it, allowing you to sum a number without worrying about
// exactly how that number is stored in memory.
struct number {
struct {
int (*sum)(struct number *, int);
int (*product)(struct number *, int);
...
} * methods;
void * data;
};
struct number * num = get_number();
int sum = num->methods->sum(number, 3);
The last example is basically how C++ does virtual member functions. Replace the methods struct with a hash table and you have Objective-C's method dispatch. Like variable pointers, function pointers let you abstract things in valuable ways that can make code much more compact and flexible. That power, though, isn't really apparent from the simplest examples.
They are one of those most useful things in C! They allow you to make a lot more modular software.
Callbacks
eg,
typedef void (*serial_data_callback)(int length, unsigned char* data);
void serial_port_data_received(serial_data_callback callback)
{
on_data_received = callback;
}
void data_received(int length, unsigned char* data)
{
if(on_data_received != NULL) on_data_received(length, data);
}
this means in your code you can use the general serial routines.....then you might have two things that use serial, modbus and terminal
serial_port_data_received(modbus_handle_data);
serial_port_data_received(terminal_handle_data);
and they can implement the callback function and do what's appropriate.
They allow for Object Oriented C code. It's a simple way to create "Interfaces" and then each concrete type might implement things different. For this, generally you will have a struct that will have function pointers, then functions to implement each function pointer, and a creation function that will setup the function pointers with the right functions.
typedef struct
{
void (*send)(int length, unsigned char* data);
} connection_t;
void connection_send(connection_t* self, int length, unsigned char* data)
{
if(self->send != NULL) self->send(length, data);
}
void serial_send(int length, unsigned char* data)
{
// send
}
void tcp_send(int length, unsgined char* data)
{
// send
}
void create_serial_connection(connection_t* connection)
{
connection->send = serial_send;
}
then other code can use use a connection_t without caring whether its via serial, tcp, or anything else that you can come up with.
They reduce dependencies between modules. Somtimes a library must query the calling code for things (are these objects equal? Are they in a certain order?). But you can't hardcode a call to the proper function without making the library (a) depend on the calling code and (b) non-generic.
Function pointers provide the missing pieces of information all the while keeping the library module independant of any code that might use it.
They're indispensable when an API needs a callback back to the application.
Another use is for the implementation of event-emitters or signal handlers: callback functions.
What if you're writing a library in which the user inputs a function? Like qsort that can work on any type, but the user must write and supply a compare function.
Its signature is
void qsort (void* base, size_t num, size_t size,
int (*compar)(const void*,const void*));

storing values in union in c

If we have a union with three variables int i, char c, float f; and we store a value in say the variable c now. and we forget what is the variable of the union that holds a value currently, after some time. for this is there any mechanism provided by the language using which we can find out whether it is i or c or f that currently holds a value.
It is not possible. The different members of a union all refer to the same memory adress, they are just different ways of seeing that memory. Modifiying a member of the union modifies all the other. You cannot distinguish one from another.
Well, the point of the union is that all of them will hold a value. The value you read might not make sense if you extract a different type than you put in, though.
You do have to keep track yourself of which type you put in if you intend to extract the same one. There is no language feature to track the situation for you.
#define VARIANT_FLOAT_TYPE 1
#define VARIANT_DOUBLE_TYPE 2
// and so on
struct variant_wb {
union {
float f;
double d;
int i;
char c;
};
int stored_type;
};
Then you could use it like this:
struct variant_wb var;
var.f = 1.23;
var.stored_type = VARIANT_FLOAT_TYPE;
You could also make inumerous functions to deal with this struct/union, or you could learn C++ and do it "properly", since that language has this type of feature. My C++ is not very great, maybe some guru could show how to do a similar solution but in the C++ way.
In C++/Qt/COM/DCOM there is the concept of a "Variant", that's roughly said a union which also stores how the union was accessed.
In C, you would have to provide something like this:
struct myCVariant
{
int variantType;
union
{
char v1;
int v2;
float v3;
} variantContent;
void initVariant()
{
variantType = 0;
}
void setChar(char a)
{
variantType = 1;
variantContent.v1 = a;
}
void setInt(int a)
{
variantType = 2;
variantContent.v2 = a;
}
// ... and so on
bool getChar(char* pa)
{
if (variantType == 1)
{
*pa = variantContent.v1;
return true;
}
return false; // Error reading a char where something else was stored
}
// ... and so on
};
You could copy some Variant implementation in some C++ source and port it to C. It's not completely the same, but it's similar. And it is somewhat typesafe (at least at runtime).
EDIT: hexa beat me by a second. And note, that I did not compile this, so my code might contain typos.
No.
C is a lower-level language. It's allowing you to write whatever you want to raw memory. In the end, whether it contains text, integers, or code, all memory contains bits. There is no really way to determine what those bits represent.
While all union members will "hold a value", there's no mechanism to determine what data type it was originally.
If you need to know this, then you should either store a flag that indicates the data type, or you should not be using a union.
It's OK if you forget because that is going to be written right there on the code and you can read it to find out.

Resources