I don't know why the below code give invalid Initializer error. Is there something wrong?
void ssd_write(uint8_t data){
uint8_t txBuffer[1] = data; <--- error
i2cTransaction.slaveAddress = 0x78;
i2cTransaction.writeBuf = txBuffer;
i2cTransaction.writeCount = 1;
i2cTransaction.readBuf = NULL;
i2cTransaction.readCount = 0;
I2C_transfer(i2c, &i2cTransaction);
I2C_close(i2c);
}
It should be
uint8_t txBuffer[1] = {data};
Yoou are declaring an array of 1 element and initializing it. You should be aware that in this case you are assigning to writeBuf the decayed pointer pointing to the array's first element.
Otherwise you are simply doing an invalid operation by trying to assign the variable to the declared array.
Or more simply you might wanted (Because it is illogical to have an array to store just a single value - you can but that's hardly the thing we do)
uint8_t txBuffer = data;
After you do this, you might want to do i2cTransaction.writeBuf = &txBuffer; if it expects a uint8_t*.
Related
Right now I am trying to implement an Init function for Pre-configured staff. However as in the following code when I try to implement certain function I receive an error initializer element is not constant. I have read many questions with same error however I couldn't relate one to my case.
The code is as follows:
#define CURR_CONFIG_X 4
#define CURR_CONFIG_Y 4
#define CURR_CONFIG_Z 4
typedef struct {
bool *tblX;
bool *tblY;
bool *tblZ;
} indicesInUse_t;
typedef struct {
tblPreCfgs_t *tblPreCfgs;
indicesInUse_t *tblEntryIndicesInUse;
} tblMgmt_t;
indicesInUse_t cfgIndicesInUse(indicesInUse_t *currIndicesInUse); //error takes place in this line
static indicesInUse_t currTblIndicesInUse = cfgIndicesInUse(&currTblIndicesInUse);
static tblMgmt_t flowTbleMgmt = {
.tblEntryIndicesInUse = &currTblEntryIndicesInUse,
};
indicesInUse_t cfgIndicesInUse(indicesInUse_t *currIndicesInUse) {
for (uint16_t index = 0; index < CURR_CONFIG_X; index++) {
currIndicesInUse->tblX[index] = true;
}
for (uint16_t index = 0; index < CURR_CONFIG_Y; index++) {
currIndicesInUse->tblYindex] = true;
}
for (uint16_t index = 0; index < CURR_CONFIG_Z; index++) {
currIndicesInUse->tblZ[index] = true;
}
return *currIndicesInUse;
}
Here's an instance of where you will get the error:
static indicesInUse_t currTblIndicesInUse = cfgIndicesInUse(&currTblIndicesInUse);
Here currTblIndicesInUse is a static variable, so its initializer must be a constant expression. That means it cannot contain dynamically executed code, such as a function call.
There are two ways this can be solved. One is to change the initializer so that it's a constant expression. The other is to remove the initializer, and instead initialize the variable with an assignment statement (inside a function). You would then call that function to initialize it.
For example, the simplest constant initializer would be something like:
static indicesInUse_t currTblIndicesInUse = {NULL, NULL, NULL};
The NULL values could also be the addresses of static bool variables, or bool arrays.
To initialize it dynamically, you'd simply call a function, passing it the address of the struct. The function would then simply set the fields of the structure, e.g.
s_ptr->tblX = ptr_x;
s_ptr->tblY = ptr_y;
s_ptr->tblZ = ptr_z;
You would need to fill in the specifics yourself, depending on what you want to achieve.
Note that in the original posted code, even if the dynamic initializer were allowed, it still wouldn't work because space is never allocated
for the pointer variables. It might be helpful to read a tutorial on how pointers work.
I have been blocking for a while now on a function whose purpose is to assign a value to the respective cells of the sent pointed array:
void assign(T** pointerArray, U linkedListOfValues) {
size_t i = 0;
while (linkedListOfValues != NULL) {
*pointerArray[i++] = convert(linkedListOfValues->current); // Crash here, when add a second (or more) item
linkedListOfValues = linkedListOfValues->next;
}
}
As commented in the code, when I add more than one element to this pointed array, the program stops. There is no error message or warning. I use this function as such:
T* array = malloc(size * sizeof(T));
assign(&array, myLinkedList);
size represents the number of elements present in the linked list, and returns a correct value; the types used (U and T) are very arbitrary, and the convert function converts an element of type U into an element of type T.
The tests I performed did not find any errors in the convert function and in the dynamic allocation.
When I try without using this function, the program works correctly:
T* array = malloc(size * sizeof(T));
size_t i = 0;
while (linkedListOfValues != NULL) {
array[i++] = convert(linkedListOfValues->current);
linkedListOfValues = linkedListOfValues->next;
}
I don't understand what makes my function crash, since I only make a reference, using pointers, to the initial array. What's my mistake?
Ps: I started the C again a little while ago, maybe the solution is obvious, excuse me if that's the case.
If I understood it right, I think what you mean to do is something like this:
T* array = malloc(size * sizeof(T));
assign(array, myLinkedList);
void assign(T* pointerArray, U linkedListOfValues) {
size_t i = 0;
while (linkedListOfValues != NULL) {
pointerArray[i++] = convert(linkedListOfValues->current);
linkedListOfValues = linkedListOfValues->next;
}
}
Hello i am trying to write a function which return the number of elements of the array passed as parameter, the function have to work on an array of any type.
I tried this:
int nb_elems(void* array)
{
void* end = array;
while(*end != NULL) // The last element have to be null, it is not counted.
end++;
return end - array;
}
As you can guess, it doesn't work.
In fact it doesn't even compile, i get these errors:
Error: Illegal indirection. < while(*end != NULL) >
Error: void * : size unknown. < while(*end != NULL) >
Error: void * : size unknown. < return end - array >
First, could you tell me if what i am trying to do is possible?
Second, is the way i am trying to achieve this makes sense, or am i completely missing the point?
Then, why do i get these errors, what does they means?
Thanks for your help!
As C does not pass arrays, nb_elems(void* array) received a pointer. The void *pointer does not know how many elements (nor the type) which its points to.
Since it needs to "work on an array of any type", code needs to define how to compare an arbitrary type with NULL.
To your function, you need to pass the pointer, the size of an array element and a function to use to test against NULL.
int nb_elems(void* array, size_t esize, int (*cmp)(void *ptr)) {
char *ptr = array;
int count = 0;
while (*cmp(ptr) == 0) {
ptr += esize;
count++;
}
return count;
}
because you are checking != NULL i suppose you have an array of pointers. with array of pointer your code could work because you know the size of pointers even if it is a void pointer.
if my assumptions were right you could code it like this:
int nb_elems(void** array) {
void** end = array;
while(*end != NULL) {
end++;
}
return end - array;
}
but this code only works with pointer to pointer or array of pointer.
usage:
int** iptrs = (int**)malloc(3 * sizeof(int*));
iptrs[0] = (int*)malloc(sizeof(int));
*(iptrs[0]) = 42;
iptrs[1] = (int*)malloc(sizeof(int));
*(iptrs[1]) = 23;
iptrs[2] = NULL;
printf("%d", nb_elems(iptrs));
the example prints 2
No, the way your are doing it is not possible, because to do pointer arithmetic (here the ++ and the -) the compiler has to know the size of the base type of the array.
Also void* is a pointer to void, that is to a "non-type". So *end has type void and you can't compare it to anything, in particular not to NULL, which could be a pointer type or an integer. Just use 0 if you compare a base type for being zero.
Before starting to even try to do this for pointers of any type, you should try the same for pointers to a known type, say unsigned or double. If you change your code with that in mind, it has good chances to work.
The reason your code doesn't compile, is because of the fact that the compiler cannot determine the size of a void. Take for example the ++ operator. We could roughly translate this to:
end = end + sizeof(void);
The size of a void is not defined, so the compiler cannot generate any code for this, giving you one error.
Next you try to dereference a void pointer. This would give you something with the type void. But since a void does not represent anything (it represents nothing), the compiler cannot tell what this should be. You then use the equality operator to compare nothing to NULL. You cannot compare nothing to something, so this will generate an error.
In C, it is impossible to implement a function that would do something like this, simply because of the fact that you cannot tell what the type of the void* will be. You at least need to know the type your passed to your function and what type-specific value will be used to terminate the array. C does not offer this functionality, making the implementation of such a function impossible.
If you have an actual array, not a pointer, you can use sizeof(array) / sizeof(array[0]) to determine the number of elements in it.
i have an array with an initial size
int size = 5; //initial size ofwordsArray
wfpPointer wordsArray = new WordFrequencyPair[size];
where wfpPointer is a typedef for a pointer that points to the adress of a variable of type WordFrequencyPair.
now when i detect that my array is full i call the following function to expand it:
int expandWordsArray(WordFrequencyPair wordsArrayIn[], int currentSize){
int newSize = currentSize * 2;
wfpPointer newArray = new WordFrequencyPair[newSize];
for(int i = 0; i < currentSize; i++)
newArray[i] = wordsArrayIn[i];
delete [] wordsArrayIn;
wordsArrayIn = newArray;
return newSize;
}
the thing is when i write this code in the main without calling the function it works perfectly fine and the array expands. From within the function however my program crashes. Note: eclipse gives me no errors and compiles the program without trouble.
Plz help
Thank you
You are passing the array (that is, a pointer to the first element of the array) by value. The function deletes, the array (using the original value of the pointer), then constructs a new array on the heap and points the local pointer to it.
Meanwhile, back in the calling code (main), the pointer hasn't changed and the old array has been deleted. When you try to dereference the pointer, BOOM!
You should pass the pointer by reference:
int expandWordsArray(WordFrequencyPair *&wordsArrayIn, int currentSize)
How should I write my code to example a specific array index of an array that happens to be a member of a structure? The following code is giving me problems.
// main.c
void clean_buffers(void); // prototype
struct DEV_STATUS {
unsigned char ADDR;
unsigned char DEV_HAS_DATA;
unsigned char ETH_HAS_DATA;
unsigned char DATA[20];
};
struct DEV_STATUS g_cmdQueue[60] = {0};
void main(void) {
clean_buffers();
while (1) {
;// MCU tasks
}
}
void clean_buffers(void) {
unsigned char theCount = 0;
byte queIdx;
for (queIdx = 0; queIdx < 59; queIdx++) {
struct DEV_STATUS *p_struct;
unsigned char *p_data;
p_struct = &g_cmdQueue[queIdx];
p_data = &p_struct->DATA;
p_struct->ADDR = 0;
p_struct->DEV_HAS_DATA = 0;
p_struct->ETH_HAS_DATA = 0;
theCount = 0;
while(*(p_data+theCount) != 0) {
*(p_data+(theCount++)) = 0;
}
}
} // EOF main.c
I get a compiler error "struct/union member expected" on the following line:
p_data = &p_struct->DATA;
How should I write a pointer if I was to access, for example, the specific value of structure member DATA[3]? I'm confused, I thought that as p_data = &p_struct->DATA; is defined, I should be able to get it by using *(pdata+3) but I guess I'm missing something.
Are you sure you are compiling the same code you posted here?
If your compiler complains at this line
p_data = &p_struct->DATA;
with a "struct/union member expected" message, your compiler is probably broken.
Note, that &p_struct->DATA is a perfectly valid expression in C. There's absolutely no problems with this expression by itself.
The problem here is just that this is not what you need in your case. &p_struct->DATA returns a pointer to the entire array 'DATA', i.e a pointer of type unsigned char (*)[20]. You are trying to assign this value to a pointer of type unsigned char *. This is illegal in C, since the types are completely different, but traditionally C compilers responded to it with a mere "type mismatch" warning and performed an implicit conversion (which, BTW, means that your original code, albeit "dirty", should still work as intended).
Even if some compiler decides to flag this mismatch as an error (which is fine), it still should not complain about any problems of "struct/union member expected" kind. There's no such problems here.
P.S. As other already said, what you really need is p_data = &p_struct->DATA[0], but that still does not explain your compiler's strange behavior. Could it be that 'DATA' is a macro defined somewhere before the 'clean_buffers' definition?
Added 10/19/2009: Nate, in your code you access your array using an index theCount. Since you are using the index access anyway, there's really no reason to even create the pointer you are trying to create. The code will work perfectly fine without any additional pointer, just acess the DATA field directly
theCount = 0;
while (p_struct->DATA[theCount] != 0) {
p_struct->DATA[theCount++] = 0;
(I'd probably use a for cycle here).
If you really insist on creating this pointer and still using the index access, the code should look something like the following (the others already suggested that more than once)
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
theCount = 0;
while (p_data[theCount] != 0) {
p_data[theCount++] = 0;
Moreover, you can opt for a more "exotic" variant :)
unsigned char (*p_data)[20]; /* <- note: declared differently */
...
p_data = &p_struct->DATA; /* <- note: your original version */
...
theCount = 0;
while ((*p_data)[theCount] != 0) {
(*p_data)[theCount++] = 0;
However, returning to a unsigned char *p_data version, since you create that pointer, it might make more sense to use a "sliding pointer" technique instead of using index access
unsigned char *p_data;
...
p_data = p_struct->DATA; /* or &p_struct->DATA[0] */
...
while (*p_data != 0) {
*p_data++ = 0;
As always, it is all a matter of personal preference. Of course, nothing of this will work until you get rid of that interference from the macro.
Lose the & in
p_data = &p_struct->DATA;
p_struct is already a pointer. Afterwards, use p_data[] to access your array.
What you should write is one of two things:
p_data = p_struct->DATA; // DATA is the address of the first element.
OR
p_data = &p_struct->DATA[0]; // taking the address of the first element.
Simply remove the & at the beginning, like this:
p_data = p_struct->DATA;
That is special sintax for arrays (remember they are passed always as reference) and it is equivalent to:
p_data = &p_struct->DATA[0];
And yes, now you can use *(pdata+3)
Hope it helps.
Oops! Thank you AndreyT
struct DEV_STATUS *p_struct;
unsigned char *p_data;
p_struct = &g_cmdQueue[queIdx];
p_data = &p_struct->DATA;
p_struct is a pointer to struct DEV_STATUS.
&p_struct is the address of a pointer to struct DEV_STATUS (or a pointer to a pointer to a struct DEV_STATUS).
You probably want to change that line to
p_data = p_struct->DATA;
Oh ... your clean_buffers() function does not "clean" the element g_cmdQueue[59].
And, because it is a global object, the array g_cmdQueue is initialized to all zeros even before the first statement of main() exceutes.