Why is some of my code being skipped? - c

My program is exhibiting some odd behavior when I step through it in the debugger. In the following excerpt, it checks pktNum != ~invPktNum and then proceeds directly the the second return 1; statement.
The debugger shows that pktNum is an unsigned char that is 0x01 and invPktNum is an unsigned char that is 0xFE.
/* Verify message integrity. */
if (pktNum != ~invPktNum) {
return 1;
}
ccrc = crc16_ccitt(msg, XModem_Block_Size);
if ( (((ccrc>>8) & 0xFF) != crcBuf[0])
|| ((ccrc & 0xFF) != crcBuf[1]) ) {
return 1;
}

The compiler has folded the two return 1 cases into the exact same code. Both if tests branch to the same assembly instruction. Each instruction can only be tagged with a single line number for the debugger, so you see that strange behavior. If you compile with -g and without -O (or even more explicitly use -O0) it will make distinct cases and things will be more clear.

Unary ! is logical-NOT. If the operand is 0 the result is 1, otherwise the result is 0. This means that !invPktNum is 0, so the if expression is true.
You are probably looking for unary ~, which is bitwise-NOT.
By the way, it may appear in a debugger as if the second return 1; is being executed rather than the first, because the compiler may have reordered the code and combined those two return 1; statements together (particularly if optimisation is enabled).

!(0xFE) is 0. Maybe what you wanted was ~(0xFE)?

Check compiler optimizations are definitely disabled for debug mode. (Just to be different to everybody else)

You're comparing an int to a bool. That's bad style to begin with, and some compilers will complain.
Maybe you mixed up ! and ~? !invPktNum will return false if invPktNum is non-false, and true if it's false. I'm pretty sure you meant ~invPktNum.

Related

For loop without the second condition, i.e. the boolean check?

I have to write a function that calculates the floor of log base 16 of an unsigned int passed in. There are restrictions as to what operators and what constants we are allowed to use, and we can only use specifically for loops.
For clarity, we cannot use any conditional statements(if, else, switch ... ). The function prototype is:
int floor_log16(unsigned int x);
Allowed operators: ++ -- = & | ~ ^ << ! >>
Allowed constants: 1 2 3 4 8 16
I wrote a version of the program as follows:
int floor_log16(unsigned int x) {
int index=1;
int count=(1!=1);
count--;
for(; index<=x; index<<=4) {
count++;
}
return count;
}
which seems to work as desired. However, I realized that based on the later functions and description of the needed functionality we have to write, I noticed that under "allowed operators" sometimes > and < were listed.
I deduce this implies that since for the floor_log16 function listed above, we weren't explicitly told to use > or <, I can only assume that the solution posted above will not be accepted.
This leaves me rather confused because I don't understand how you can possibly have a for loop without a boolean check?
Isn't the whole idea of a loop to iterate while a condition is met?
Well, first of all, for-loop without the boolean check is perfectly fine. For example,
for (;;)
is a common way of writing
while (true)
Second, having a for-loop with other parts but without boolean check is still useful as you can exit it with return or break.
And the last thing. There are tons of ways of getting a boolean without using < and >. For example, you can simply use i to check that i != 0 and so on.
For example if you want to check that a < b you can check for (a - b) < 0 instead. Implementing addition (and hence subtraction) with bitwise operators is a well known interview question (you should really try to do this yourself, it's fun), and checking that your int is negative is as easy as looking at its most significant bit.
I don't like to spoil your task but consider about for condition like 'comparison to 0'. This doesn't require any explicit operator. One of possible way to get it is something like this:
// This cycle will end as soon as index is 0.
for (;index; index = (index >> 4))
{
// ...
}
If you XOR any unsigned with itself, it becomes 0. So int count=(1!=1); could be changed to int count = 1 ^ 1.
As for the loop condition, Roman's idea of comparison to 0 seems like the most natural way to go.

C program interesting behaviour

I have stumbled upon a piece of code that generates some interesting results while debugging someone else's program.
I have created a small program to illustrate this behavior:
#include <stdio.h>
int main()
{
char* word = "foobar"; int i, iterator = 0;
for (i = 0; i < 6; i++ && iterator++)
printf("%c", word[iterator]);
return 0;
}
I know that this is not the right way to print a string. This is for demonstration purpose only.
Here I expected the output to be "foobar", obviously, but instead it is "ffooba". Basically it reads the first character twice, as if the first time iterator++ is executed nothing happens.
Can anyone explain why this happens?
The thing is iterator++ actually isn't executed the first time. The ++ operator returns the current value of a variable and then increments it, so the first time through, i++ will be equal to 0. && short-circuits, so iterator++ is not executed the first time.
To fix this, you could use the comma operator which unconditionally evaluates both, rather than the short-circuiting &&.
The result of i++ is the current value of i which is zero on first iteration. This means iterator++ is not executed on first iteration due to short circuting (the right-hand side of && is only executed if the left-hand side is "true").
To fix you could use the comma operator (as already suggested or) use ++i which will return the value of i after the incremement (though comma operator is more obvious that both must always be evaluated).
You really should learn to use a debugger like e.g. gdb and to compile with warnings and debugging info like gcc -Wall -g (assuming a Linux system). A recent gcc with -Wall gives you a warning about value computed is not used before the && operation.
The increment part of your for loop is strange. It is i++ && iterator++ (but it should be i++, iterator++ instead).
When i is 0 (on the first iteration), i++ gives 0 as result, so it is false, so the iterator++ is not executed.
I am reading K&R about logic operators,let me quote the origin words of book,which can explain your question.
"Expressions connected by && or || are evaluated left to right, and
evaluation stops as soon as the truth or falsehood of the result is known."
Have a good understanding of these,the outputs wont puzzle.

Legal uses of setjmp and GCC

Using GCC (4.0 for me), is this legal:
if(__builtin_expect(setjmp(buf) != 0, 1))
{
// handle error
}
else
{
// do action
}
I found a discussion saying it caused a problem for GCC back in 2003, but I would imagine that they would have fixed it by now. The C standard says that it's illegal to use setjmp unless it's one of four conditions, the relevant one being this:
one operand of a relational or equality operator with the other operand an integer constant expression, with the resulting expression being the entire controlling expression of a selection or iteration statement;
But if this is a GCC extension, can I guarantee that it will work under for GCC, since it's already nonstandard functionality? I tested it and it seemed to work, though I don't know how much testing I'd have to do to actually break it. (I'm hiding the call to __builtin_expect behind a macro, which is defined as a no-op for non-GCC, so it would be perfectly legal for other compilers.)
I think that what the standard was talking about was to account for doing something like this:
int x = printf("howdy");
if (setjmp(buf) != x ) {
function_that_might_call_longjmp_with_x(buf, x);
} else {
do_something_about_them_errors();
}
In this case you could not rely on x having the value that it was assigned in the previous line anymore. The compiler may have moved the place where x had been (reusing the register it had been in, or something), so the code that did the comparison would be looking in the wrong spot. (you could save x to another variable, and then reassign x to something else before calling the function, which might make the problem more obvious)
In your code you could have written it as:
int conditional;
conditional = setjump(buf) != 0 ;
if(__builtin_expect( conditional, 1)) {
// handle error
} else {
// do action
}
And I think that we can satisfy ourselves that the line of code that assigns the variable conditional meets that requirement.
But if this is a GCC extension, can I guarantee that it will work under for GCC, since it's already nonstandard functionality? I tested it and it seemed to work, though I don't know how much testing I'd have to do to actually break it. (I'm hiding the call to __builtin_expect behind a macro, which is defined as a no-op for non-GCC, so it would be perfectly legal for other compilers.)
You are correct, __builtin_expect should be a macro no-op for other compilers so the result is still defined.

C exit function not doing what I thought it would

When I use a debugger I can tell the exit is not exiting the function. Am I using the exit function wrong? (i must be) how do I fix this?
int is_prime(int x,char array[]){
int divider = (x-1);
float test;
while(x>-1){
test = isdigit((x % divider)); //isdigit returns !0 if digit
if(divider == '1'){
return(1); //if divider reaches 1 then the number is prime
exit;
}
if(test == '0'){
return (0);//not prime
exit;
}
divider--;
}
}
The name of a function by itself (with no parenthesis after it) just gives you the address of a function without calling it. In C the most basic statement is an expression which is evaluated for its side effects, with the resulting value of the expression ignored. So a statement like exit; or 3; which has no side effects is legal but doesn't actually do anything and might as well be deleted. Some compilers will give you warnings about such meaningless statements, though you may have to turn on extra diagnostic warnings to get them. Using such options (such as -Wall for gcc) is a very good idea and will help you avoid some pitfalls like this.
You must call it:
exit(0);
Also, if you put it after return, it will never be called, since return returns from the function.
EDIT: And, as others have said, exit exits the program, so you probably don't want to use exit here.
Besides the bugs of returnand exit you have a bug also in the way you use ints and characters. isdigit is a function that is only applied to characters, giving true if a character is between '0' and '9', but one should know that the character notation in C is only a fancy way of writing a codepoint (ASCII most of the time). So when you write '1' in a C program, the compiler will see 49, if you write 'a' the compiler sees in reality 97. This means that isdigit return true for the values 48 to 57, probably not what you intended. In the line where you compare divider with '1', in reality you're comparing it with 49 (except on IBM mainframe, where '1' is 241)
Your loop is infinite, it depends on the value of x, but x isn't changed in the loop, so the condition in the while can never change.
EDIT: Here the corrected code
int is_prime(uint_t x)
{
uint_t divider;
if(x <= 3)
return 1;
for(divider = x-1; ; divider--) {
if(x % divider == 0)
return 0; //not prime
if(divider == 1)
return 1; //if divider reaches 1 then the number is prime
}
}
Read exit(3)'s manual.
The statement:
exit;
gives the following warning with GCC:
C:\temp\test.c:71: warning: statement with no effect
What happening is that you have an expression that evaluates to the address of the exit() function - but that expression doesn't actually do anything with that address. it's similar to if you had a statement like:
1 + 2;
It's valid C, but it has no effect on anything.
To call the function, as Thomas Padron-McCarth said, you have to have the argument list (even if they're empty for some functions):
exit(0);
exit exits the process, not the function. You want return.

What is the meaning of '==' in C?

What is the meaning of == and how does it differ from =?
How do I know which one to use?
== is a test for equality. = is an assignment.
Any good C book should cover this (fairly early on in the book I would imagine).
For example:
int i = 3; // sets i to 3.
if (i == 3) printf("i is 3\n"); // prints it.
Just watch out for the heinous:
if (i = 4) { }
which is valid C and frequently catches people out. This actually assigns 4 to the variable i and uses that as the truth value in the if statement. This leads a lot of people to use the uglier but safer:
if (4 == i) {}
which, if you accidentally use = instead of ==, is a compile-time error rather than something that will bite you on the backside while your program is running :-)
The logical-or operator is two vertical bar characters, one after the other, not a single character. Here it is lined up with a logical-and, and a variable called b4:
||
&&
b4
No magic there.
a == b is a test if a and b are equal.
a = b is called an assignment, which means to set the variable a to having the same value as b.
(You type | with Shift-\ in the US keyboard layout.)
== tests equality
= assigns a value
neither are related to ||
I might add that in Finnish and Swedish keyboards. Pipe symbol; |; of OR is AltGr (the right alt) and < key. IF you are using Mac on the other hand it is Alt-7 key.
Gave me a lot of sweat when I first started typing on these keyboards.
Now that you know the difference between '==' and '=", let me put you some words of caution. Although '==' is used as a standard test of equality between comparable variables and '=' used as an internally type-casted assignment, the following programming error is quiet common.
In the below example and similar codes, '=' is know as "Always true" conditional operator.
#include<stdio.h>
int main()
{
int i = 10, j = 20;
if ( i = j )
printf("Equal\n");
else
printf("NOT Equal\n");
return 0;
}
So, the word of caution is "Never use '=' in if statements, unless you have something evil in your mind."

Resources