I want to configure (module A) to send certain data to (module B) at certain slots of time.
(Module B) should send these configuration to (module A) during initialization.
The data is:
struct _data
{
int temp;
int velocity;
int time;
}
For example, (module A) should send 'temp' at first slot, then 'temp & velocity' at second slot, then 'time' at third slot .... etc
I am thinking about making making "configuration flags" structure:
struct _configuration
{
int temp_flag;
int time_flag;
int velocity_flag;
}
Then making an array of this structures:
struct _configuration arr[NUMBER_OF_SLOTS];
and configure using this array:
arr[0].temp_flag = 1;
arr[0].velocity_flag = 0;
arr[0].time_flag = 0;
arr[1].temp_flag = 1;
arr[1].velocity_flag = 1;
arr[1].time_flag = 0;
arr[2].temp_flag = 0;
arr[2].velocity_flag = 0;
arr[2].time_flag = 1;
.... etc
But I am not very happy with this approach ... does anyone has a better way or algorithm to do this task ?
Many thanks in advance
One of the many possible solutions is bitmasks (very popular in computer graphics). As you know, every number can be represented as sequence of 0 and 1, so they can be the flags that mean something. It's quite simple to use them in such way because we have bitwise operations. And there is no need to create some configuration structures.
const int USE_TEMP = 1 << 0; // 01
const int USE_VELOCITY = 1 << 1; // 010
const int USE_TIME = 1 << 2; // 0100
// ...
// you have 32 free-to-use bits
const int USE_ALL = 0111; // just for fun
struct _data {
int temp;
int velocity;
int time;
}
And it bring us to
int arr[NUMBER_OF_SLOTS];
arr[0] = USE_TEMP;
arr[1] = USE_TEMP | USE_VELOCITY;
arr[2] = USE_TIME;
Looks better, isn't it?
Checking values
When you need to check whether some of the parameters included in configuration, it's very simple
if( arr[i] & USE_TEMP ) {
// do smth with temp, it's included
}
or this way
int expected_flags = USE_TIME | USE_VELOCITY;
if( arr[i] & expected_flags == expected_flags ) {
// time and velocity enabled
}
or even declare special function (or scary macro) to check whether some parameters are in your config
bool check(int config, int flags) {
return config & flags == flags;
}
Changing configurations
What if you need to delete/add parameters?
int some_conf = USE_TEMP | USE_VELOCITY;
Simple way
// delete
if( check(some_conf, USE_VELOCITY) )
some_conf -= USE_VELOCITY; // <--- dangerous without if( )
// add
if( !check(some_conf, USE_TIME) )
some_conf += USE_TIME; // <--- dangerous without if( )
Safety way
// delete
some_conf &= ~USE_VELOCITY;
// add
some_conf |= USE_TIME;
Related
does anyone know about an elegant (efficient) alternative to using large global arrays in C for an embedded system, whereby the array is written to in an interrupt service routine and it is read elsewhere asynchronously:
I have no issues with the current implementation, however I was just wondering if it is the best option.
for example:
uint8_t array_data[20] = {0};
volatile bool data_ready = false;
someIsr(void){
for(uint8_t i = 0; i < 20; i++){
array_data[i] = some_other_data[i];
}
data_ready = true;
}
main(void){
for(;;){
if(data_ready){
write_data_somewhere(&array_data[0]);
data_ready = false;
}
}
}
Thanks
Using global arrays is often the best approach unless one would need to use the storage for other purposes when the interrupt routine isn't running. An alternative is to use a global pointer to data that may be stored elsewhere, but one must be very cautious changing that pointer while interrupts are enabled.
An important caveat with your code, by the way: although the Standard regards the implications of a volatile qualifier as implementation-defined, allowing for the possibility that implementations may treat a volatile write as a potential "memory clobber", the authors of gcc require the use of compiler-specific intrinsics to prevent operations on "ordinary" objects from being reordered across operations on volatile-qualified ones.
For example, given:
volatile unsigned short out_count;
int *volatile out_ptr;
int buffer[10];
__attribute__((noinline))
void do_write(int *p, unsigned short count)
{
__asm("");
out_ptr = p;
out_count = count;
do {} while(out_count);
__asm("");
}
void test(void)
{
buffer[0] = 10;
buffer[1] = 20;
do_write(buffer, 2);
buffer[0] = 30;
buffer[1] = 40;
buffer[2] = 50;
do_write(buffer, 3);
}
because the __asm intrinsics don't use gcc-specific syntax to indicate that they might "clobber" the contents of memory in ways the compiler can't understand (even though many compilers support the use of empty __asm intrinsics for that express purpose, and such intrinsics wouldn't really serve any other purpose), and because gcc can see that there's no way that do_write could alter the contents of buffer, it "optimizes out" the code that would store the values 10 and 20 into buffer before the first call to do_write.
Clang doesn't seem quite as bad as gcc. It doesn't seem to reorder writes across volatile writes, it seems to refrain from reordering reads across functions that are not in-line expanded, and it seems to treat empty asm directives as potential memory clobbers, but I I'm not familiar enough with its documentation to know whether such restraint is by design, or merely a consequence of "missed optimizations" which might be "fixed" in future versions.
Consider using translation unit scope rather than global scope. That is declare the array static in the translation unit in which it is used. That translation unit should contain in this case the ISR that writes the data and an access function to read the data. Anything else, including main() should be in other translation units in order that that do not have direct access to the array:
#include <stdbool.h>
#include <stdint.h>
static volatile uint8_t array_data[DATA_LEN] = {0};
static volatile bool data_ready = false;
void someIsr(void)
{
for(uint8_t i = 0; i < 20; i++)
{
array_data[i] = some_other_data[i];
}
data_ready = true;
}
bool getdata( char* dest )
{
bool new_data = data_ready ;
if( data_ready )
{
memcpy( desr, array_data, sizeof(array_data) ) ;
data_ready = false ;
}
}
Then main() in some other translation unit might have:
#include "mydevice.h"
int main( void )
{
uint8_t somewhare[DATA_LEN] = {0};
for(;;)
{
if( getdata( somewhere ) )
{
// process new data
}
}
}
The above is based on your example, and the aim here is to isolate the array so that outside of the ISR the access is enforced to be read-only. In practice it is likely that you will need a "safer" data structure or access method such as a critical-section, double-buffering or a ring buffer so that the data can be accessed without risk of it being modified while it is being read.
This is no less efficient that your original global access, it is simply a restriction of the visibility and accessibility of the array.
As I mentioned in my top comment, one of best ways is to implement a ring queue.
Although I done a few ring queue implementations, here's one I just cooked up for illustration purposes. It is a [cheap] simulation of an Rx ISR for a uart [which is fairly common in embedded systems].
It is fairly complete, but I've not debugged it, so it may have some issues with the queue index calculations.
Anyway, here's the code:
// queue.c -- a ring queue
#include <stdlib.h>
#include <unistd.h>
enum {
QMAX = 1024
};
typedef unsigned char qdata_t; // queue data item
typedef struct {
int qenq; // index for enqueue
int qdeq; // index for dequeue
int qmax; // maximum number of elements in queue
int qover; // number of queue overflows
qdata_t *qbuf; // pointer to queue's buffer
} queue_t;
queue_t *rxisr_q; // pointer to Rx qeueue
// cli -- disable interrupts
void
cli(void)
{
}
// sti -- enable interrupts
void
sti(void)
{
}
// uart_ready -- uart is ready (has Rx data available)
int
uart_ready(void)
{
int rval = rand();
rval = ((rval % 100) > 95);
return rval;
}
// uart_getc -- get character from uart receiver
int
uart_getc(void)
{
int rval = rand();
rval &= 0xFF;
return rval;
}
// qwrap -- increment and wrap queue index
int
qwrap(queue_t *que,int qidx,int inc)
{
int qmax = que->qmax;
qidx += inc;
if (inc > 0) {
if (qidx >= qmax)
qidx -= qmax;
}
else {
if (qidx < 0)
qidx += qmax;
}
return qidx;
}
// qavail_total -- total amount of space available (for enqueue)
int
qavail_total(queue_t *que)
{
int qlen;
qlen = que->qdeq - que->qenq;
if (qlen < 0)
qlen += que->qmax;
qlen -= 1;
return qlen;
}
// qavail_contig -- total amount of space available (for enqueue) [contiguous]
int
qavail_contig(queue_t *que)
{
int qlen;
qlen = que->qdeq - que->qenq;
if (qlen < 0)
qlen = que->qmax - que->qenq;
qlen -= 1;
return qlen;
}
// qready_total -- total amount of space filled (for dequeue)
int
qready_total(queue_t *que)
{
int qlen;
qlen = que->qenq - que->qdeq;
if (qlen < 0)
qlen += que->qmax;
return qlen;
}
// qready_contig -- total amount of space filled (for dequeue) [contiguous]
int
qready_contig(queue_t *que)
{
int qlen;
qlen = que->qenq - que->qdeq;
if (qlen < 0)
qlen = que->qmax - que->qdeq;
return qlen;
}
// qfull -- is queue full?
int
qfull(queue_t *que)
{
int next;
next = qwrap(que,que->qenq,1);
return (next == que->qdeq);
}
// qpush -- push single value
int
qpush(queue_t *que,qdata_t chr)
{
int qenq = que->qenq;
int qnxt;
int push;
qnxt = qwrap(que,qenq,1);
push = (qnxt != que->qdeq);
if (push) {
que->qbuf[qenq] = chr;
que->qenq = qnxt;
}
return push;
}
// qalloc -- allocate a queue
queue_t *
qalloc(int qmax)
{
queue_t *que;
que = calloc(1,sizeof(*que));
que->qbuf = calloc(qmax,sizeof(qdata_t));
return que;
}
// uart_rx_isr -- ISR for uart receiver
void
uart_rx_isr(void)
{
int chr;
queue_t *que;
que = rxisr_q;
while (uart_ready()) {
chr = uart_getc();
#if 0
if (qfull(que)) {
++que->qover;
break;
}
#endif
if (! qpush(que,chr)) {
++que->qover;
break;
}
}
}
int
main(int argc,char **argv)
{
int qlen;
int qdeq;
queue_t *que;
rxisr_q = qalloc(QMAX);
que = rxisr_q;
while (1) {
cli();
qlen = qready_contig(que);
if (qlen > 0) {
qdeq = que->qdeq;
write(1,&que->qbuf[qdeq],qlen);
que->qdeq = qwrap(que,qdeq,qlen);
}
sti();
}
return 0;
}
I'm trying to setup a device tree source file for the first time on my custom platform. On the board is a NXP PCA9555 gpio expander. I'm attempting to setup node for the device and am a bit confused.
Here is where I'm at with the node in the dts file:
ioexp0: gpio-exp#21 {
compatible = "nxp,pca9555";
reg = <21>;
interrupt-parent = <&gpio>;
interrupts = <8 0>;
gpio-controller;
#gpio-cells = <2>;
/*I don't understand the following two lines*/
interrupt-controller;
#interrupt-cells = <2>;
};
I got to this point by using the armada-388-gp.dts source as a guide.
My confusion is on what code processes the #interrupt-cells property. The bindings documentation is not very helpful at all for this chip as it doesn't say anything regarding interrupt cell interpretation.
Looking at the pca953x_irq_setup function in the source code for the pca9555 driver - I don't see anywhere that the #interrupt-cells property is handled. Is this handled in the linux interrupt handling code? I'm just confused as to how I'm suppose to know the meaning of the two interrupt cells.
pca953x_irq_setup for your convenience:
static int pca953x_irq_setup(struct pca953x_chip *chip,
int irq_base)
{
struct i2c_client *client = chip->client;
int ret, i;
if (client->irq && irq_base != -1
&& (chip->driver_data & PCA_INT)) {
ret = pca953x_read_regs(chip,
chip->regs->input, chip->irq_stat);
if (ret)
return ret;
/*
* There is no way to know which GPIO line generated the
* interrupt. We have to rely on the previous read for
* this purpose.
*/
for (i = 0; i < NBANK(chip); i++)
chip->irq_stat[i] &= chip->reg_direction[i];
mutex_init(&chip->irq_lock);
ret = devm_request_threaded_irq(&client->dev,
client->irq,
NULL,
pca953x_irq_handler,
IRQF_TRIGGER_LOW | IRQF_ONESHOT |
IRQF_SHARED,
dev_name(&client->dev), chip);
if (ret) {
dev_err(&client->dev, "failed to request irq %d\n",
client->irq);
return ret;
}
ret = gpiochip_irqchip_add_nested(&chip->gpio_chip,
&pca953x_irq_chip,
irq_base,
handle_simple_irq,
IRQ_TYPE_NONE);
if (ret) {
dev_err(&client->dev,
"could not connect irqchip to gpiochip\n");
return ret;
}
gpiochip_set_nested_irqchip(&chip->gpio_chip,
&pca953x_irq_chip,
client->irq);
}
return 0;
}
This is my first time working with device tree so I'm hoping it's something obvious that I'm just missing.
After looking at all of the comments I did some additional reading and figured out my answer.
I now understand that I was misinterpreting some properties of the device tree. I was previously under the impression that the driver had to specify how all properties were handled. I now see that linux will actually handle many of the generic properties such as gpios or interrupts (which makes a lot of sense).
The documentation on the actual interrupts binding was very helpful, not the documentation for the device driver.
Here is a bit more of a detailed explanation of how the translation from intspec to IRQ_TYPE* happens:
The function of_irq_parse_one copies the interrupt specifier integers to a struct of_phandle_args here. This arg is then passed to irq_create_of_mapping via a consumer function (e.g. of_irq_get). This function then maps these args to a struct irq_fwspec via of_phandle_args_to_fwspec and passes it's fwspec data to irq_create_fwspec_mapping. These functions are all found in irqdomain.c. At this point the irq will belong to an irq_domain or use the irq_default_domain. As far I can tell - the pca853x driver uses the default domain. This domain is often setup by platform specific code. I found mine by searching for irq_domain_ops on cross reference. A lot of these seem to do simple copying of intspec[1] & IRQ_TYPE_SENSE_MASK to the type variable in irq_create_fwspec_mapping via irq_domain_translate. From here the type is set to the irq's irq_data via irqd_set_trigger_type.
of_irq_parse_one:
/**
* of_irq_parse_one - Resolve an interrupt for a device
* #device: the device whose interrupt is to be resolved
* #index: index of the interrupt to resolve
* #out_irq: structure of_irq filled by this function
*
* This function resolves an interrupt for a node by walking the interrupt tree,
* finding which interrupt controller node it is attached to, and returning the
* interrupt specifier that can be used to retrieve a Linux IRQ number.
*/
int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_args *out_irq)
{
struct device_node *p;
const __be32 *intspec, *tmp, *addr;
u32 intsize, intlen;
int i, res;
pr_debug("of_irq_parse_one: dev=%s, index=%d\n", of_node_full_name(device), index);
/* OldWorld mac stuff is "special", handle out of line */
if (of_irq_workarounds & OF_IMAP_OLDWORLD_MAC)
return of_irq_parse_oldworld(device, index, out_irq);
/* Get the reg property (if any) */
addr = of_get_property(device, "reg", NULL);
/* Try the new-style interrupts-extended first */
res = of_parse_phandle_with_args(device, "interrupts-extended",
"#interrupt-cells", index, out_irq);
if (!res)
return of_irq_parse_raw(addr, out_irq);
/* Get the interrupts property */
intspec = of_get_property(device, "interrupts", &intlen);
if (intspec == NULL)
return -EINVAL;
intlen /= sizeof(*intspec);
pr_debug(" intspec=%d intlen=%d\n", be32_to_cpup(intspec), intlen);
/* Look for the interrupt parent. */
p = of_irq_find_parent(device);
if (p == NULL)
return -EINVAL;
/* Get size of interrupt specifier */
tmp = of_get_property(p, "#interrupt-cells", NULL);
if (tmp == NULL) {
res = -EINVAL;
goto out;
}
intsize = be32_to_cpu(*tmp);
pr_debug(" intsize=%d intlen=%d\n", intsize, intlen);
/* Check index */
if ((index + 1) * intsize > intlen) {
res = -EINVAL;
goto out;
}
/* Copy intspec into irq structure */
intspec += index * intsize;
out_irq->np = p;
out_irq->args_count = intsize;
for (i = 0; i < intsize; i++)
out_irq->args[i] = be32_to_cpup(intspec++);
/* Check if there are any interrupt-map translations to process */
res = of_irq_parse_raw(addr, out_irq);
out:
of_node_put(p);
return res;
}
EXPORT_SYMBOL_GPL(of_irq_parse_one)
irq_create_fwspec_mapping:
unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec)
{
struct irq_domain *domain;
struct irq_data *irq_data;
irq_hw_number_t hwirq;
unsigned int type = IRQ_TYPE_NONE;
int virq;
if (fwspec->fwnode) {
domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED);
if (!domain)
domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_ANY);
} else {
domain = irq_default_domain;
}
if (!domain) {
pr_warn("no irq domain found for %s !\n",
of_node_full_name(to_of_node(fwspec->fwnode)));
return 0;
}
if (irq_domain_translate(domain, fwspec, &hwirq, &type))
return 0;
/*
* WARN if the irqchip returns a type with bits
* outside the sense mask set and clear these bits.
*/
if (WARN_ON(type & ~IRQ_TYPE_SENSE_MASK))
type &= IRQ_TYPE_SENSE_MASK;
/*
* If we've already configured this interrupt,
* don't do it again, or hell will break loose.
*/
virq = irq_find_mapping(domain, hwirq);
if (virq) {
/*
* If the trigger type is not specified or matches the
* current trigger type then we are done so return the
* interrupt number.
*/
if (type == IRQ_TYPE_NONE || type == irq_get_trigger_type(virq))
return virq;
/*
* If the trigger type has not been set yet, then set
* it now and return the interrupt number.
*/
if (irq_get_trigger_type(virq) == IRQ_TYPE_NONE) {
irq_data = irq_get_irq_data(virq);
if (!irq_data)
return 0;
irqd_set_trigger_type(irq_data, type);
return virq;
}
pr_warn("type mismatch, failed to map hwirq-%lu for %s!\n",
hwirq, of_node_full_name(to_of_node(fwspec->fwnode)));
return 0;
}
if (irq_domain_is_hierarchy(domain)) {
virq = irq_domain_alloc_irqs(domain, 1, NUMA_NO_NODE, fwspec);
if (virq <= 0)
return 0;
} else {
/* Create mapping */
virq = irq_create_mapping(domain, hwirq);
if (!virq)
return virq;
}
irq_data = irq_get_irq_data(virq);
if (!irq_data) {
if (irq_domain_is_hierarchy(domain))
irq_domain_free_irqs(virq, 1);
else
irq_dispose_mapping(virq);
return 0;
}
/* Store trigger type */
irqd_set_trigger_type(irq_data, type);
return virq;
}
EXPORT_SYMBOL_GPL(irq_create_fwspec_mapping);
I'm new in C programming. I'm developing a priority queue in C'99 with the heap data structure.
I'm using heapifyDown() in combination with swapValues() to sort the heap array for extracting the first element (min-heap) pqueue_extractMin() function. My structure looks like this:
typedef struct ProrityQueue_s PriorityQueue;
typedef struct PriorityQueue_Entry_s *PriorityQueue_Entry;
struct ProrityQueue_s {
int size, last;
char error;
PriorityQueue_Entry *entries;
};
struct PriorityQueue_Entry_s {
char *value;
float priority;
};
For information – Full code for information on gist: https://gist.github.com/it4need/ddf9014bfda9fe6a64bb01a7417422bc
Questions:
Insertion into the Priority queue ("minheap") looks good. Everything is fine. But when I'm extract more than one element at once, I will get this error: "Process finished with exit code 11".
Is this line allowed to copy the whole contents of the last element to the first of the heap? priorityqueue->entries[0] = priorityqueue->entries[priorityqueue->last];
swapValues(priorityqueue, currentPositionIndex, smallestChild); Can I swap values of whole Structure elements? -> implementation (bottom).
HeapifyDown():
void heapifyDown(PriorityQueue *priorityqueue)
{
int currentPositionIndex = 0;
while(currentPositionIndex < priorityqueue->last)
{
int smallestChild = currentPositionIndex;
int leftChildIndex = (2 * currentPositionIndex) + 1;
int rightChildIndex = (2 * currentPositionIndex) + 2;
smallestChild = (priorityqueue->entries[leftChildIndex]->priority < priorityqueue->entries[smallestChild]->priority && priorityqueue->last > leftChildIndex)
? leftChildIndex : smallestChild;
smallestChild = (priorityqueue->entries[rightChildIndex]->priority < priorityqueue->entries[smallestChild]->priority && priorityqueue->last > rightChildIndex)
? rightChildIndex : smallestChild;
if(smallestChild == currentPositionIndex)
{
break;
}
swapValues(priorityqueue, currentPositionIndex, smallestChild); // #todo: Why does this line break the function on two function calls by negative values
currentPositionIndex = smallestChild;
}
}
SwapValues():
void swapValues(PriorityQueue *priorityqueue, int firstIndex, int secondIndex)
{
// #todo: Does this work properly?
PriorityQueue_Entry tmp_entry = priorityqueue->entries[firstIndex];
priorityqueue->entries[firstIndex] = priorityqueue->entries[secondIndex];
priorityqueue->entries[secondIndex] = tmp_entry;
}
extractMin():
char *pqueue_extractMin(PriorityQueue *priorityqueue)
{
if(isEmpty(priorityqueue))
{
priorityqueue->error = ERROR_PRIORITY_QUEUE_EMPTY;
}
priorityqueue->last--;
char *tmp = priorityqueue->entries[0]->value;
priorityqueue->entries[0] = priorityqueue->entries[priorityqueue->last]; // #todo: Is this allowed?
heapifyDown(priorityqueue); // #todo: Why does this line break the extractMin() function on two function calls -> check swapValues() in heapifyDown()
return tmp;
}
Full code for information on gist: https://gist.github.com/it4need/ddf9014bfda9fe6a64bb01a7417422bc
I'm using the LXLE 14.04 distribution of Linux. I want to write a C program to read commands, interpret and perform them. I'd like the program to be efficient, and I do not want to use a linked list. The commands are operations on sets. Each set can contain any of the values from 0 through 127 inclusive. I decided to represent a set as an array of characters, containing 128 bits. If bit at position pos is turned on then the number pos is in the set and if the bit at position pos is turned off then the number pos is not present in the set. For example, if the bit at position 4 is 1, then the number 4 is present in the set, if the bit at position 11 is 1 then the number 11 is present in the set.
The program should read commands and interpret them in a certain way. There are a few commands: read_set, print_set, union_set, intersect_set, sub_set and halt.
For example, the command read_set A,1,2,14,-1 in the terminal will cause the reading of values of the list into the specified set in the command. In this case the specified set in the command is A. The end of the list is represented by -1. So after writing this command, the set A will contain the elements 1,2,14.
This is what I have so far. Below is the file set.h
#include <stdio.h>
typedef struct
{
char array[16]; /*Takes 128 bits of storage*/
}set;
extern set A , B , C , D , E , F;
This is the file main.c
#include <stdio.h>
#include "set.h"
#include <string.h>
#include <stdlib.h>
set A , B , C , D , E , F; /*Variable definition*/
set sets[6];
/*Below I want to initialize sets so that set[0] = A set[1] = B etc*/
sets[0].array = A.array;
sets[1].array = B.array;
sets[2].array = C.array;
sets[3].array = D.array;
sets[4].array = E.array;
sets[5].array = F.array;
void read_set(set s,char all_command[])
{
int i, number = 0 , pos;
char* str_num = strtok(NULL,"A, ");
unsigned int flag = 1;
printf("I am in the function read_set right now\n");
while(str_num != NULL) /*without str_num != NULL get segmentation fault*/
{
number = atoi(str_num);
if(number == -1)
return;
printf("number%d ",number);
printf("str_num %c\n",*str_num);
i = number/8; /*Array index*/
pos = number%8; /*bit position*/
flag = flag << pos;
s.array[i] = s.array[i] | flag;
str_num = strtok(NULL, ", ");
if(s.array[i] & flag)
printf("Bit at position %d is turned on\n",pos);
else
printf("Bit at position %d is turned off\n",pos);
flag = 1;
}
}
typedef struct
{
char *command;
void (*func)(set,char*);
} entry;
entry chart[] = { {"read_set",&read_set} };
void (*getFunc(char *comm) ) (set,char*)
{
int i;
for(i=0; i<2; i++)
{
if( strcmp(chart[i].command,comm) == 0)
return chart[i].func;
}
return NULL;
}
int main()
{
#define PER_CMD 256
char all_comm[PER_CMD];
void (*ptr_one)(set,char*) = NULL;
char* comm; char* letter;
while( (strcmp(all_comm,"halt") != 0 ) & (all_comm != NULL))
{
printf("Please enter a command");
gets(all_comm);
comm = strtok(all_comm,", ");
ptr_one = getFunc(comm);
letter = strtok(NULL,",");
ptr_one(sets[*letter-'A'],all_comm);
all_comm[0] = '\0';
letter[0] = '\0';
}
return 0;
}
I defined a command structure called chart that has a command name and function pointer for each command. Then I have created an array of these
structures which can be matched within a loop.
In the main function, I've created a pointer called ptr_one. ptr_one holds the value of the proper function depending on the command entered by the user.
The problem is, that since user decides which set to use,I need to represent the sets as some variable, so that different sets can be sent to the function ptr_one. I thought about
creating an array in main.c like so
set sets[6];
sets[0] = A;
sets[1] = B;
sets[2] = C;
sets[3] = D;
sets[4] = E;
sets[5] = F;
And then call the function ptr_one in the main function like this ptr_one(sets[*letter-'A'] , all_command).
That way, I convert my character into a set.
The problem is that while writing the above code I got the following compile error:
error: expected ���=���, ���,���, ���;���, ���asm��� or ���attribute��� before ���.��� token
I also tried the following in the file main.c
sets[0].array = A.array;
sets[1].array = B.array;
sets[2].array = C.array;
sets[3].array = D.array;
sets[4].array = E.array;
sets[5].array = F.array;
But I got this compile error expected ���=���, ���,���, ���;���, ���asm��� or ���attribute��� before ���.��� token
I know similar questions have been asked, by they don't seem to help in my
specific case. I tired this set sets[6] = { {A.array},{B.array},{C.array},{D.array},{E.array},{F.array} } too but it did not compile.
What's my mistake and how can I initialize sets so that it holds the sets A though F?
Here is a code to insert a data in a binary trie. This code works perfectly if I compile it with a basic gcc main.c -o main .
/**
* Insert a new gateway in the tree, at the position corresponding to the
* subnet address.
*
* addr : Subnet address
* netmask : Subnet mask
* gw : gateway identifier
*
* return : void.
*/
void insertMyAlgo(unsigned int addr, unsigned int netmask, unsigned int gw)
{
struct node* noeud;
int i;
int maskBit = countMaskBit(netmask);
// Going down in the tree until next mask bit = 0.
noeud = arbre;
for (i = 31; i > 31 - maskBit; i--)
{
// Bit = 1, go down in the right child.
if ((addr >> i) & 0x1)
{
if (noeud->fd == NULL)
noeud->fd = allocNode();
noeud = noeud->fd;
}
// Bit = 0, go down in the left child.
else
{
if (noeud->fg == NULL)
noeud->fg = allocNode();
noeud = noeud->fg;
}
}
// Insert the gateway in the node corresponding to our subnet address.
noeud->gateway = gw;
}
I would like to use the -O option to optimize time spent in looking up the tree, finding a specific key. I get a segfault when I execute my main with this -O options.
Gdb gave me the following informations :
Program received signal SIGSEGV, Segmentation fault. insertMyAlgo
(addr=12288, netmask=<optimized out>, gw=3238068734)
at mainbinaireBench.c:125 125 if (noeud->fg == NULL)
(gdb) print noeud->fg Cannot access memory at address 0x8
So the error seems to be here :
// Bit = 0, go down in the left child.
else
{
if (noeud->fg == NULL)
noeud->fg = allocNode();
noeud = noeud->fg;
}
I really don't know why there is this error, and why the program works without this -O option. I would really like to make it works, if some of you guys could help me to understand, it would be very nice.
Thank you !
It is not possible to know what is wrong for certain without a Short Self Contained Example
But there are debugging thechniques which may help you in finding what the problem is.
Add several asserts to your code :
void insertMyAlgo(unsigned int addr, unsigned int netmask, unsigned int gw)
{
struct node* noeud;
int i;
int maskBit = countMaskBit(netmask);
// Going down in the tree until next mask bit = 0.
assert( arbre!=NULL );
noeud = arbre;
for (i = 31; i > 31 - maskBit; i--)
{
// Bit = 1, go down in the right child.
if ((addr >> i) & 0x1)
{
if (noeud->fd == NULL)
{
noeud->fd = allocNode();
assert( noeud->fd!=NULL );
assert( noeud->fd->fd==NULL );
assert( noeud->fd->fg==NULL );
}
noeud = noeud->fd;
}
// Bit = 0, go down in the left child.
else
{
if (noeud->fg == NULL)
{
noeud->fg = allocNode();
assert( noeud->fg!=NULL );
assert( noeud->fg->fd==NULL );
assert( noeud->fg->fg==NULL );
}
noeud = noeud->fg;
}
}
// Insert the gateway in the node corresponding to our subnet address.
noeud->gateway = gw;
}
If any of those asserts fail now you have a better idea of what is happening. If none fail you have reduced your search space, the problem is elsewhere.
You may even leave the asserts there after you have finished debugging. Just define NDEBUG for release builds and all the code in asserts will be omited.