Ignore output parameters in C - c

I have a function which returns some value and some parameters:
uint8 myFunction(uint8* param1);
uint8 myFunction(uint8* param1)
{
*param1 = 3;
return 1;
}
Later in my code I would like to use the function once with returning a value like:
uint8 a;
uint8 b;
a = myFunction(b);
...
...
and once with just ignoring the parameter, like:
a = myFunction(void);
How to do this in C?

I'd recommend adding a NULL check before dereferencing param1 - that would be wise anyway. Then you can just pass NULL where you want to ignore it.
uint8 myFunction(uint8* param1)
{
if (param1 != NULL)
{
*param1 = 3;
}
return 1;
}
calling code can then just pass NULL:
a = myFunction(NULL);
Of course, it would be good to clearly document this behavior.

Related

C language how to call a member of multi-dimensional array in corresponding to a structure

I have a problem with how to call a member of a structure. For example, there is a struct
typedef struct FAVORITE_TBL_S
{
UI32_T apple;
UI32_T banana;
UI16_T puzzle;
UI16_T car;
}FAVORITE_TBL_T;
And in the function, I have created a multi-dimensional array about this struct.
FUNCTION_NO_T
call_myFavoriteTbl(
const UI32_T unit,
const UI32_T value)
{
FUNCTION_NO_T ret = FUNCTION_E_GOOD;
UI8_T num_of_list = 4;
UI32_T i = 0;
FAVORITE_TBL_T *ptr_fav = NULL;
ptr_fav = priviate_alloc(sizeof(FAVORITE_TBL_T ) * num_of_list );
priviate_memset(ptr_fav, 0, sizeof(FAVORITE_TBL_T ) * num_of_list );
/* In this function, if I want to use member in the multi-dim array */
for (i = 0, i < value, i++)
{
if (BRAND_PINKLADY == ptr_fav[i]->apple)
{
printf("I love it!");
}
else
{
printf("I don't want to eat.");
}
if (BRAND_COSTAPICA == ptr_fav[i].banana)
{
printf("I love it!");
}
else
{
printf("I don't want to eat.");
}
}
return ret;
}
So why ptr_fav[i]->apple is wrong and ptr_fav[i].banana is right?
As ptr_fav is an array of FAVORITE_TBL_T values, ptr_fav[i] is a FAVORITE_TBL_T value. It is not a pointer to FAVORITE_TBL_T.
As such, the . notation is correct.
Now, because ptr_fav[i] is equivalent to *(ptr + i), you might write: (ptr_fav + i)->apple, though I'm not sure why you'd want to do that.
The -> operator is used to access a field on a pointer to a structure.
ptr_fav[i] has already dereferenced it and now you have structure value not pointer. If you want to use -> you should try (ptr_fav + i)->apple.

C programming: How to get rid of the QAC warning when pass 2D array as a const function argument?

I want to pass a 2D array to a function, and the value of the array will not be modified in that function. So I am thinking about doing this way:
#include <Windows.h>
static INT8 TwoDimArrayConst(const INT8 ai_Array[2][2]);
int main(void)
{
INT8 ai_Array[2][2] = { { { 1 }, { 2 } }, { { 3 }, { 4 } } };
(void)TwoDimArrayConst(ai_Array); // Message 0432: [C] Function argument is not of compatible pointer type.
return 1;
}
static INT8 TwoDimArrayConst(const INT8 ai_Array[2][2])
{
INT8 test = 0;
for (INT8 i = 0; i < 2; i++)
{
for (INT8 k = 0; k < 2; k++)
{
if (ai_Array[i][k] > 0)
{
test = 1;
}
}
}
if (test == 0)
{
test = 2;
}
return test;
}
However, it gave me the QAC error when I enabled depth 5 QAC setting as the one I put is the code comment above:
// Message 0432: [C] Function argument is not of compatible pointer type.
If I remove the const in the function declaration and definition, so the function is like:
static INT8 TwoDimArrayConst(INT8 ai_Array[2][2]);
this error will be gone, but there will be another error saying:
> The object addressed by the pointer parameter 'ai_Array' is not
> modified and so the pointer could be of type 'pointer to const'.
So how to resolve this dilemma? I cannot define ai_Array to be const array in the main fuction since some other function may still want to modify the value.
Also, I am looking for the solution that still maintain the double brackets(no need to pass row size and column size as separate arguments) in the function, instead of treat it as a 1D array.
the following proposed code:
uses the C library functions rather than the windows functions, since I'm running on linux, not windows
performs the desired functionality
cleanly compiles
takes advantage of arrays, in C, being laid out consecutively in memory
takes advantage of "accessing an array name degrades to the address of the first byte of the array"
removes all the unneeded braces (which are doing nothing but cluttering the code)
documents why each header file is included
passes the size of the array as an parameter to the called function (should always either do this or include some kind of 'marker' in the contents of the array)
all the above allows treating the array as a 1 dimensional array
breaks out of the loop in the called function as soon as the terminating condition is encountered
BTW: the header file: windows.h is not portable
and now, the proposed code:
//#include <Windows.h>
#include <stdio.h> // printf()
#include <stdint.h> // int8_t
static int8_t TwoDimArrayConst( const int8_t *ai_Array, size_t size );
int main(void)
{
const int8_t ai_Array[2][2] = { { 1, 2 }, { 3, 4 } };
int8_t returnValue = TwoDimArrayConst(( int8_t* const )ai_Array, sizeof( ai_Array) / sizeof( int8_t ));
printf( "%d\n", returnValue );
return 1;
}
static int8_t TwoDimArrayConst( const int8_t *ai_Array, size_t size )
{
int8_t test = 2;
for ( size_t i = 0; i < size; i++)
{
if (ai_Array[i] > 0)
{
test = 1;
break;
}
}
return test;
}
A run of the proposed code results in:
1

RubyInline: Error: too few arguments to function

I have the following C code:
VALUE find_index(VALUE arr, VALUE num_elements, VALUE element){
....
}
....
VALUE array_distance(VALUE arr1, VALUE arr2){
long arr1_len = RARRAY_LEN(arr1);
VALUE *c_arr2 = RARRAY_PTR(arr2);
long i;
for(i = 0; i < arr2_len; i++){
long arr1_index = find_index(arr1, arr1_len, c_arr2[i]);
....
}
}
When compiling this, I get the following error:
In function ‘VALUE array_distance(VALUE, VALUE, VALUE)’:
error: too few arguments to function ‘VALUE find_index(VALUE, VALUE, VALUE, VALUE)’
Can someone help with what is wrong here?
If you want to use your C functions in other C code inside, you need to use builder.c_raw instead of builder.c, because RubyInline actually tries to make your life easier by changing your code so you can write simple functions quickly. This is however misleading and keeps you from calling your C functions from inside other C functions, because the method signature is altered. This should get you started:
class Test
inline :C do |builder|
builder.c_raw <<-'EOC', :arity => 3
static VALUE
find_index(int argc, VALUE *argv, VALUE self) {
VALUE arr = argv[0];
VALUE num_elements = argv[1];
VALUE element = argv[2];
// actual code...
}
EOC
builder.c_raw <<-'EOC', :arity => 2
static VALUE
array_distance(int argc, VALUE *argv, VALUE self) {
long arr1_len = RARRAY_LEN(argv[0]);
VALUE *c_arr2 = RARRAY_PTR(argv[1]);
long i;
for(i = 0; i < arr2_len; i++){
VALUE[] find_index_argv = {arr1, arr1_len, c_arr2[i]};
long arr1_index = find_index(argc, find_indev_argv, self);
// more code...
}
// must have a return value!
return Qnil;
}
EOC
end
end

error: v.contents[30] is used uninitialized in this function

Here is my struct;
typedef struct _values {
int contents[MAX_CONTENTS];
... more ints;
} values;
In another function, I initialize this particular array with;
int contents[MAX_CONTENTS] = {0};
for (i = 0; i < MAX_CONTENTS; i++) {
v.contents[i] = contents[i];
}
And in my main I have this;
values v;
newValues (v);
I am getting the error whenever I try to modify an element in main like this;
v.contents[30] = 3;
This is the only error I am getting. What am I doing wrong?
v (and contents inside of it) may be getting passed by value. Change the prototype of your function to this:
void newValues(values *v);
Change how you're calling it to this:
newValues(&v);
And rather than:
v.contents[i] = /* ... */;
Use:
v->contents[i] = /* ... */;
You probably intend to copy like this:
for (i = 0; i < MAX_CONTENTS; i++) {
v.contents[i] = contents[i];
}

Changing pointer to a struct, passed by reference

I have this call on a file called 'PlayBoard.c':
MoveSucc = putBoardSquare(theBoard, getX, getY, nextTurn);
Where 'theBoard' is a pointer to struct Board. Inside the function I am changing the board's size by referencing the pointer to ANOTHER Board struct, a bigger one. Will it change 'theBoard' on 'PlayBoard.c', where MoveSucc is invoked?
EDIT: putBoardSquare is defined in another source file
EDIT: I've added the relevant functions
Boolean putBoardSquare(BoardP theBoard, int X, int Y, char val)
{
if (val != 'X' && val != 'O')
{
reportError(BAD_VAL);
return FALSE;
}
if (X<0 || Y<0)
{
reportError(OUT_OF_BOUND);
return FALSE;
}
if (X>theBoard->height || Y>theBoard->width)
{
theBoard = expandBoard(theBoard, X,Y);
}
printf("BOARD SIZE IS %d*%d\n",theBoard->height,theBoard->width);
if (theBoard->board[X][Y] == 'X' || theBoard->board[X][Y] == 'Y' )
{
reportError(SQUARE_FULL);
return FALSE;
}
if (val != turn)
{
reportError(WRONG_TURN);
return FALSE;
}
theBoard->board[X][Y] = val;
printf("PUT %c\n",theBoard->board[X][Y]);
changeTurn(val);
return TRUE;
}
static BoardP expandBoard(ConstBoardP theBoard, int X, int Y)
{
int newWidth = theBoard->width;
int newHeight = theBoard->height;
if (X>theBoard->height)
{
newHeight = (newHeight+1) * 2;
}
if (Y>theBoard->width)
{
newWidth = (newWidth+1) * 2;
}
BoardP newBoard = createNewBoard(newWidth,newHeight);
copyBoard(theBoard,newBoard);
printf("RETUNRNING NEW BOARD OF SIZE %d*%d\n",newHeight,newWidth);
return newBoard;
}
As you can see, when the user tries to place 'X' or 'O' outside the board, it needs to be expanded which happens (I know cause I've printed new board's size in expandBoard() and in putBoardSquare()). But the pointer in 'PlayBoard.c' doesn't seem to change anyway....
My question: how can I change the pointer of a struct passed as an argument to another function? In 'PlayBoard.c' I pass one struct as an argument, and I want putBoardSquare to refrence it to another struct, which will take effect in PlayBoard.c as well.
Am I clear?
EDIT
theBoard = expandBoard(theBoard, X,Y);
This assignment only changes a local variable. You'll have to add one level of indirection, as in:
MoveSucc = putBoardSquare(&theBoard, getX, getY, nextTurn);
Boolean putBoardSquare(BoardP *theBoard, int X, int Y, char val)
{
/* ... */
*theBoard = expandBoard(theBoard, X,Y);
/* ... */
}
Your question is confusing (perhaps you should post the code you have), but the error you have is cause simply by the definition of the struct not being available in PlayBoard.c. For instance, if you only have
struct foo;
void foo(struct foo *foov) { ... }
without a definition of foo available, as in
struct foo { int a; ... }
then you won't be able to access the members of the structure (see "opaque type").
If I understand correctly and you want to change where theBoard points to, you need to define it as a pointer to pointer, not as pointer.
MoveSucc = putBoardSquare(&theBoard, getX, getY, nextTurn);
and change the parameter in putBoardSquare() to ** and when you set the pointer do it like (assuming x is a pointer):
*theBoard = x;

Resources