Control may reach end of non-void function C - c

I am not able to compile my code, I am getting error: control may reach the end of a non-void function
/**
* Returns true if value is in array of n values, else false.
*/
bool search(int value, int values[], int n)
{
//Binary search algorithm
int first = 0;
int last = n-1;
int middle = (first+last)/2;
if (n<1)
return false;
else
{
while (first <= last)
{
if (values[middle]==value)
return true;
else if(values[middle]<value)
first=middle+1;
else if (values[middle]>value)
{
last=middle-1;
}
middle=(first+last)/2;
}
}
if (first>last)
return false;
}
Can anyone look through my code and help me figure out where the issue is? I am struggling to see it myself! From my point of view, this function returns true or false

Your return type of bool means that your function is always expected to return a boolean value before it exits, no matter which path of execution it takes. As it stands now, it appears on inspection that you can "fall through" the last if and never hit a return statement. To verify otherwise would require stepping through your logic in a way the compiler cannot reasonably be expected to do. At the end simply change to say:
if (first>last) {
return false;
} else {
return true;
}
Or more concisely:
return (first > last) ? false : true;

In your code it's not possible for the function to fall off the end.
However, the compiler is not required to accurately diagnose whether a function can get to the end or not. In general, to do so would require solving the halting problem.
Instead, as a practical measure, your compiler is doing some basic checks and warning because it sees the if ( first > last ) return false;, it didn't do enough code analysis to determine that this branch can never be reached unless first > last.
To suppress this warning you could just remove the line if ( first > last ). BTW this is a warning, not an error; so it should not prevent your compilation.

Related

C-How to increase in recursion?An example of recursively judging prime numbers

I'm a programming rookie who has not yet started. I just learned recursion and there are some problems with the use of recursion. There is a homework is judge prime numbers :using int prime(int x); and return boolean value.
Initially I found that because the variable is initialized and assigned inside the function,the program can't achieve self-increment. Because every time it enters a new level of recursion, the variable will be reassigned. Even if you write a variable auto-increment statement, it will only auto-increase the variables stored in the current recursive stack. Once the variable enters a new recursive level, the variable is only initialized according to the definition and cannot be continuously auto-incremented.
The solution to the failure is as follows:
#include <math.h>
#define false 0
#define true 1
int prime(int x){
double high=sqrt(x);
int low=2;
if((x%low==0 && x!=2) || low>high){
return false;
}
else if(x<2){
return false;
}
else{
return true;
}
low++;
return prime(x);
}
When asking questions, I found a successful solution:
#include <math.h>
#define false 0
#define true 1
int prime(int x){
double high=mysqrt(x);
static int low=2;
if((x%low==0 && x!=2)||low>high){
return false;
}
else if(x<2){
return false;
}
else{
return true;
}
low++;
return prime(x);
}
But I can't understand why using static to modify the variable can make the variable correctly increment when entering a new layer of recursion instead of executing the previous int low=2;
Ask the master to solve the confusion for me, what happened to the two in the memory space?
In addition, there seems to be another solution, which seems to be to set a flag variable, but I did not understand it. Can someone provide other solutions?
In a nutshell, ordinary variables (int low;) get created for each function call independently, while static (static int low = 2;) are created once and shared between all the functions.
However, static is not the best approach to use in such cases, because different function calls may need to have different values of high/low.
Instead, you may add explicit parameters to the function, something like this (the algorithm is wrong, but it's the general principle):
int prime(int x) { return prime_impl(x, 2, sqrt(x)); }
int prime_impl(int x, int low, double high) {
if(x<2) {
return false;
}
else if((x%low==0 && x!=2)||low>high) {
return true;
}
else {
return prime_impl(x, low+1, high);
}
}

new preprocessor trick to me

(Below code is correct, not create by myself.)
(it is inside the config of a motor board.)
#define BTN_TABLE(X) X(BUTTON, PA1)
#define BTN_X_EXTERNS(A, B) extern Button A;
BTN_TABLE(BTN_X_EXTERNS)
#define BTN_X_ID(A, B) A##_ID
#define BTN_X_ENUM(A, B) BTN_X_ID(A, B),
typedef enum { BTN_TABLE(BTN_X_ENUM) NUM_BOARD_BUTTONS } BoardButtonID;
#define BTN_X_FROM_ENUM(A, B) else if (button_id == BTN_X_ID(A, B)) return &A;
static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (0) return 0;
BTN_TABLE(BTN_X_FROM_ENUM)
else return 0;
}
I don't get the meaning of if (0) return 0; and else return 0; in above example.
why place the Marco in between these two line?
I think we cannot place anything between if{} , else{} statement.
I think the intent behind this code was as follows:
We have some buttons; currently just one, but eventually there may be many more
Each button needs a corresponding global variable and a value in the BoardButtonID enum
We want a function which given the enum BoardButtonID value returns a pointer to the button's global variable
We want to achieve all this while only listing all buttons once.
#bolov has shown how the code expands. I'll note that one can add more buttons just by changing the definition of the BTN_TABLE macro:
#define BTN_TABLE(X) X(BUTTON, PA1) \
X(ANOTHER_BUTTON, PA2) \
X(YET_ANOTHER_BUTTON, PA3) \
X(OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP, PA4)
The PA1, PA2, ... aren't actually used in this version of the code; maybe they would have been used for something later.
Now you can see the effect (I've reformatted the output):
extern Button BUTTON;
extern Button ANOTHER_BUTTON;
extern Button YET_ANOTHER_BUTTON;
extern Button OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP;
typedef enum {
BUTTON_ID,
ANOTHER_BUTTON_ID,
YET_ANOTHER_BUTTON_ID,
OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP_ID,
NUM_BOARD_BUTTONS
} BoardButtonID;
static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (0)
return 0;
else if (button_id == BUTTON_ID)
return &BUTTON;
else if (button_id == ANOTHER_BUTTON_ID)
return &ANOTHER_BUTTON;
else if (button_id == YET_ANOTHER_BUTTON_ID)
return &YET_ANOTHER_BUTTON;
else if (button_id == OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP_ID)
return &OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP;
else
return 0;
}
And this makes it clear why the initial if is needed: the macro expansion in button_from_enum has no way to treat the first one specially. So it has to produce an else if for every button, including the first one, and the only way to make that valid is for there to be an if at the beginning. It needs to have a test that always fails, hence 0, and its corresponding "then" clause doesn't matter as it will never execute. The return 0 there may have just been chosen to shut up a compiler warning about the function possibly returning without a value. Of course, the return 0 in the final else clause can be reached, and serves as a default if someone passes a value that doesn't match any button.
You are right that if you put anything else in between the if and else, everything will break.
They could have defined it a little differently and used switch instead, which would have been slightly cleaner. I don't know why they didn't; maybe the compiler generates different code that they didn't like (e.g. a jump table that occupies more code space).
In any event, the resulting set of macros, while clever, are certainly not very easy to maintain. They should probably have considered writing a script instead that would generate the desired code from a simple list of buttons in a text file.
Or, they could have put the Button objects in an array instead of insisting on each one having its own variable. This would go nicely with their enum:
typedef enum {
BUTTON_ID,
ANOTHER_BUTTON_ID,
YET_ANOTHER_BUTTON_ID,
OH_GOD_NOT_ANOTHER_BUTTON_MAKE_THEM_STOP_ID,
NUM_BOARD_BUTTONS
} BoardButtonID;
Button all_the_buttons[NUM_BOARD_BUTTONS];
static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (button_id < NUM_BOARD_BUTTONS)
return &all_the_buttons[button_id];
else
return NULL;
}
This way still only requires listing the buttons once, and it involves no macros at all.
This is one of the most unreadable pieces of code I have seen.
I personally don't have neither the time, energy or willingness to analyze and figure out these horible macros. So I just dumped the preprocessor output and this is the code presented to the compiler:
extern Button BUTTON;
typedef enum { BUTTON_ID, NUM_BOARD_BUTTONS } BoardButtonID;
static __forceinline Button* button_from_enum(BoardButtonID button_id) {
if (0) return 0;
else if (button_id == BUTTON_ID) return &BUTTON;
else return 0;
}
it is inside the config of a motor board.
That explains the code. It is consistent with code that is generated by other software, rather than by a human. It is generated by some code that configures a software package to some target environment.
The purpose of code like this:
if (0) return 0;
BTN_TABLE(BTN_X_FROM_ENUM)
else return 0;
is to allow the generating code to put any number of else if lines between the if line and the else line. For example, in various circumstances, the generated code might be this:
if (0) return 0;
else return 0;
or this:
if (0) return 0;
BTN_TABLE(BTN_X_FROM_ENUM)
else return 0;
or this:
if (0) return 0;
BTN_TABLE(BTN_X_FROM_ENUM)
BTN_TABLE(BTN_Y_FROM_ENUM)
else return 0;
By using if (0) and else as bookends, the generating code is freed from having to have conditional cases such as “If there are zero conditions, just write return 0;. If there is one condition, write if (condition) return something; else return 0;. If there are multiple conditions, write if (first condition) return something; else if (second condition) return something;… else return 0;.
Instead, the generating code is simply:
Write if (0) return 0;.
For each condition, write an else if line for it (likely in the form of some BTN_TABLE macro use, the definition for which is emitted elsewhere in the generating code).
Write else return 0;.
Thus, while the resulting code is more complicated, the actual generating code is simpler.
I don't get the meaning of if (0) return 0; and else return 0; in above example.
The if (0) is needed simply so that the following lines can be any number of else if statements. The return 0; is never executed and is simply needed to complete the if statement grammatically.
The else return 0; statement provides a default in case none of the conditions are met.
why place the Marco in between these two line?
The generating code emits a macro invocation for every case it determines is needed in the target system.
I think we cannot place anything between if{} , else{} statement.
Of course you can, the else if statements are proper there.

In function there are two return statements and which return statement will execute?

int main()
{
int f=fun();
...
}
int fun()
{
return 1;
return 2;
}
In the above program, when a function is called from the main function and the function contains two return statements,
Will both return statements execute? or else
If only one return statement executes, why? Then what about another return statement whether executes or not?
Program control never reaches return 2; and an optimising compiler will remove it.
The only language I know that's insane enough to have two return statements that are reached is Java:
try {
return 1; // this is evaluated
} finally {
return 2; // this is the one actually returned
}
If you rember that a return statement corresponds to an assembly opcode like RTS ("return from sub-routine") that set the value of the Program Counter with the address of the instruction after the call, it will be obviously that the second return statement is never executed.

Binary Search in C using recursion

The program crashes in finding a number which is not available in the array.The code works perfectly when i search for elements which are available in the array.Help much appreciated.
#include<stdio.h>
int binarySearch(int a[],int s,int key)
{
int middle;
if(s!=1)
middle=s/2;
if(a[middle]==key)
return 1;
else if(key<a[middle])
binarySearch(a,middle,key);
else if(key>a[middle])
binarySearch(&a[middle],middle,key);
else
return 0;
}
void main()
{
int i;
int a[]={1,2,3,4,6,9,10,11};
for (i =0;i<8;i++)
printf("%i ",a[i]);
if(binarySearch(a,8,5))
printf("\nFound");
else
printf("\nNot Found");
}
Change
if(s!=1)
middle=s/2;
if(a[middle]==key)
return 1;
else if(key<a[middle])binarySearch(a,middle,key);
else if(key>a[middle])binarySearch(&a[middle],middle,key);
to
if (s != 1){
middle = s / 2;
if (a[middle] == key)
return 1;
else if (key<a[middle])binarySearch(a, middle, key);
else if (key>a[middle])binarySearch(&a[middle], middle, key);
}
The variable middle is initialized only if s!=1.
I have run this code and got the value Not Found for input 5.
If you are running your code in release mode, try building it in debug mode and run step by step you will see what happens when middle is used directly without assigning it a specific value. This is harmful.
Hope this helps.
The code if(key<a[middle])binarySearch(a,middle,key); does not return anything.
Try if(key<a[middle]) return binarySearch(a,middle,key);
This may still not work as you intend it to, but at least you will get past the major, immediately visible, cause of runaway recursion.
Because there is no case if the s == 1. "Middle" is not initialized and a[middle] is potential crash, or it will just go infinite.
A few notes:
Every branch of a recursive function should return something. You'll need to modify your recursive calls to return the call
Change
binarySearch(a, middle, key)
to
return binarySearch(a, middle, key)
Also, make sure middle is computed properly. You don't properly initialize it in the situation where s == 1. You'll want this to start at 0 most likely.

how to get out of "if" loop in c?

if(turn==2)
{
if(forward) /*then what to do if this if comes true for coming out of outer loop*/
if(columnHead>0)
{
columnHead--;
addr[columnHead] |=1<<(rowHead-1);
}
else
{
columnHead =7;
addr[columnHead] |=1<<(rowHead-1);
}
if(rowTail!=(rowHead-1))
{
addr[columnHead+columnSize] &=~(1<<rowTail);
columnSize++;
rowTail++;
}
else
{
addr[columnTail] &=~(1<<columnTail);
if(columnTail==0)columnTail=8;
columnTail--;
}
back=1;
}
I want to come out of outer if loop if it satisfies condition if(forward)
You should create function of this code, and return from the block where the condition becomes true.
A standard idiom is to use while(true){/*your code here*/ break; } around the whole block and use break statements as appropriate which will take you to the end of the while brace. Just remember to include the final break or your program will loop.
Whatever you do, don't use a goto as they are considered very poor programming style.
Some folk, from the C days where while(true) would issue a compile warning, use for(;;) instead.
The odd thing is, thinking about this some more, you could use
do {
/*your code here, using break for premature exit*/
} while (false);
which doesn't need the final break. Only I've never seen this in production code.
I guess just putting an else in there will do what you want. Also, please put braces around big blocks - it makes the else part unambiguous.
if(turn==2)
{
if(forward) {
if(columnHead>0)
{
columnHead--;
addr[columnHead] |=1<<(rowHead-1);
}
else
{
columnHead =7;
addr[columnHead] |=1<<(rowHead-1);
}
} else {
if(rowTail!=(rowHead-1))
{
addr[columnHead+columnSize] &=~(1<<rowTail);
columnSize++;
rowTail++;
}
else
{
addr[columnTail] &=~(1<<columnTail);
if(columnTail==0)columnTail=8;
columnTail--;
}
back=1;
}
}
Version after the author's comment:
if(turn==2 && !forward) {
if(rowTail!=(rowHead-1))
{
addr[columnHead+columnSize] &=~(1<<rowTail);
columnSize++;
rowTail++;
}
else
{
addr[columnTail] &=~(1<<columnTail);
if(columnTail==0)columnTail=8;
columnTail--;
}
back=1;
}
You probably have to go the other direction, that means:
You don't want to check wether
if(forward) is true, but instead you want to do if(!forward).
Though you'd need to check what type forward is. I guess it's an integer though.
You can try giving the return 0; or return something; when you need to get out of the if, before that u may want to put the entire code in a c syntax function like-
(int)someFunction(int turn, int forward,
int columnHead, int rowHead, int rowTail, int columnTail)/*have all the arguments with proper types declaration*/{
//your code with return 0;
}.
why go into the "if" in the first place.
change the outter if to:
if(turn==2 && forward) //not sure if your logic required `forward` or `!forward` you were ambiguous
{
//...
}

Resources