Shake sort using MACRO - c

Shake sort of vector:
program works, but:
I was trying to use the same function for bubble up and bubble down for shake sort (bubble up to get the MAX value to the right and bubble down to get the min value to the left). In order to do it I was trying to use the following MACRO which does not compile:
sign is '+' and oper is '>' for bubble
sign is '-' and oper is '<' for bubble down
for bubble up -
start is iterator i (iterated the Vector indices)
end is n-1-i;
for bubble down -
swap start and end values
#define bubble_up_down(var_t, pVector, _Is_swp, start, end, sign, oper)\
{\
var_t current_index;\
var_t current_val;\
var_t next_val;\
for (current_index = *(start) ; current_index (oper) *(end) ; (sign)(sign)current_index){\
{\
VectorGet((pVector), current_index, &current_val);\
VectorGet((pVector), current_index(sign)1, &next_val);\
if(current_val (oper) next_val)\
{\
VectorSet((pVector), current_index, next_val);\
VectorSet((pVector), current_index(sign)1, current_val);\
*(_Is_swp) = 1;\
}\
}\
}
Need your advice to fix this macro.

It is not really clear why you want to use a macro here. Do you want to avoid duplicaing code? Or do you want to make your sorting routine type independent?
Anyway, your macro has several errors:
You've probably read that you should guard macro arguments with parentheses. That is usually good advice, because macros are text replacements; for example infamous SQ(x + 1) will resolve to x + 1*x + 1. In your case, the advice is wrong-headed. You will get syntactically wrong "operators" such as (-) and (<) in your code. Just use sign and oper.
Even so, sign sign will resolve to - - or + +, which is not what you want. You could rewrite i++ to the equally valid i = i + 1 or you could use the token-pasting operator, sign##sign, which would produce -- or ++.
Macros aren't functions. You are probably going to invoke your macro inside a function. All local variables that are in scope hen you invoke the macro are also in scope for the macro. That means there is probably no need to define all these pointers.
Why do you pass the array element type, var_t? I reckon that SetVector and GetVector aren't macros, so the type independence falls flat.
If var_t is the type of your array elements, your index isn't necessarily of the same type; it should be an integer type. (Your elements must be comparable with the < operator, so it is one of the arithmetic types, but image what happens if you have an array of char that is longer than 256 elements?)
If your elements are of arithmetic type, there's probably no need for the GetValue and SetValue calls. You can just assign values with the = operator .
All this makes me think that you don't really know what you're doing. That plus the known pitfalls and shortcomings of macros are a good reason not to use any macros here.
Addendum In comments, The PO has said that the macro should achieve two things: It should avoid repeated code and it should make the sorting independent of the types of the array elements. These are two different things.
Writing short local macros to avoid repeating code can be a useful technique, especially, if the code needs to keep variables in sync in several places. Is it useful in your situation?
So you've got your upward-bubbling code:
int done = 0;
while (!done) {
done = 1;
for (int i = 1; i < n; i++) {
if (a[i - 1] > a[i]) {
swap(a, i - 1, i);
done = 0;
}
}
}
(This uses a swap function to swap two array elements. It is more straightforward than your version, because it doesn't use get/set accessor functions.) Now you write the downward-bubbling counterpart:
while (!done) {
done = 1;
for (int i = n - 1; i > 0; i--) {
if (a[i - 1] > a[i]) {
swap(a, i - 1, i);
done = 0;
}
}
}
These two snippets differ only in the loop control. Both visit all indices from 1 to n - 1. So your macro needs to pass the start and end values. But it also needs to know which way the comparison goes – less than or greater than – and whether to increment or to decrement the index. That's four pieces of data for a simple loop.
You could try to get rid of the comparison and use != for both directions. But then your loops will fail if the array is empty.
The above backwards loop will already fail on empty arrays when you use an unsigned integer as index. Forward and backward lops are asymmetric an C, because the lower and upper bounds are asymmetric, too: Lower bound are always inclusive, upper bound are always exclusive. This forward loop:
for (unsigned int i = 0; i < n; i++) ...
Has the following backward equivalent:
for (unsigned int i = n; i-- > 0; ) ...
Here, the decrement occurs in the condition and the update part is empty. The advantage is that it uses exactly the same bounds, 0 and n, verbatim, but by decrementing before entering the loop body, the same valid range of numbers, 0 to n - 1 are visited. And it works with unsigned ints, which are a natural choice for looping variables.
To cut a long story short: Forward and backward loops are asymmetric in C, so it is not easy to write a macro for them. C's for syntax is more verbose than for i = 1 to n, but that's how it is. Embrace it and alleviate the typing pain by chosing appropriate index names: it's i, not current_index.
Can you make the code less redundant without macros? Of course: You can write two functions for bubbling up and down once:
static int bubble_up(int a[], int n)
{
int done = 1;
for (int i = 1; i < n; i++) {
if (a[i - 1] > a[i]) {
swap(a, i - 1, i);
done = 0;
}
}
return done;
}
static int bubble_down(int a[], int n)
{
int done = 1;
for (int i = n; i-- > 1; ) {
if (a[i - 1] > a[i]) {
swap(a, i - 1, i);
done = 0;
}
}
return done;
}
(These functions are static, i.e. private to the current compilation unit.) Now your actual sorting functions look like this:
void sort_bubble_up(int a[], int n)
{
int done = 0;
while (!done) {
done = bubble_down(a, n);
}
}
void sort_bubble_down(int a[], int n)
{
int done = 0;
while (!done) {
done = bubble_down(a, n);
}
}
void sort_shaker(int a[], int n)
{
int done = 0;
while (!done) {
done = bubble_up(a, n) || bubble_down(a, n);
}
}
If you are not afraid of empty loop bodies, you can even get them down to:
void sort_bubble_up(int a[], int n)
{
while (bubble_down(a, n)) { }
}
void sort_bubble_down(int a[], int n)
{
while (bubble_down(a, n)) { }
}
void sort_shaker(int a[], int n)
{
while (bubble_up(a, n) || bubble_down(a, n)) { }
}
All this code works only for int arrays, though. The standard library's way of approaching type independence is to work on the byte level via void * pointers and user-defined comparison functions. The sorting function qsort does this, for example.
C++ and other languages have templates, where you can write an algorithm for several types. When you "instantiate" a template, the compiler creates a function for just this type, which is then called.
You could emulate this with macros. If you just want to call your macro in the function body, you could define:
#define BUBBLE_SORT(ARRAY, N, TYPE) do { \
int done = 0; \
int i; \
\
while (!done) { \
done = 1; \
\
for (i = 1; i < N; i++) { \
if (ARRAY[i - 1] > ARRAY[i]) { \
TYPE sawp = ARRAY[i]; \
\
ARRAY[i] = ARRAY[i - 1]; \
ARRAY[i - 1] = swap; \
done = 0; \
} \
} \
} \
} while (0)
and then use the macro like so:
char c[] = "Mississippi";
BUBBLE_SORT(c, strlen(c), char);
(That do { ... } while (0) thing around thze macro makes the macro behave like a function call, sort of. The new scope of the loop body allows for local variables.)
The problem here is that such multi-line macros are hard to debug. When there is an error in the body, you just get the number of the line where the macro is invoked in an error message. (But you can use -E with most compilers to see how the preprocessor resolves that macro.)
Conclusion:
Macros can be useful, but you have to know what you are doing. In general, try to avoid them, because they are hard to debug and often hard to understand for others. (And this other person might be you half a year later.)
If you must use macros, try to make then look as natural as possible. Passing operators like > or + should make you wary.
Use functions, not macros, for common code.
Embrace C's way to deal with different types. It will be more useful (if less fun) to learn how qsort works than to fiddle with macros for a bubble sort implementation.
If you really need to write a lot of type-independent code, you probably shouldn't use C.

Related

C for loop optimisation by embedding statements into loop-head itself

Just wondering if these variations of for loops are more efficient and practical.
By messing with the c for loop syntax i can embedd statements that would go in the loop-body into the loop-head like so:
Example 1:
#include <stdio.h>
int main(int argc, char ** argv)
{
// Simple program that prints out the command line arguments passed in
if (argc > 1)
{
for(int i = 1; puts(argv[i++]), i < argc;);
// This does the same as this:
// for(int i = 1; i < argc; i++)
// {
// puts(argv[i]);
// }
}
return 0;
}
I understand how the commas work in the for loop it goes through each statement in order, evaluates them then disregards all but the last one which is why it is able to iterate using the "i < argc"condition. There is no need for the final segment to increment the i variable as i did that in the middle segment of the loop head (in the puts(argv[i++]) bit).
Is this more efficient or is just just cleaner to seperate it into the loop body rather than combine it all into one line?
Example 2:
int stringLength(const char * string)
{
// Function that counts characters up until null terminator character and returns the total
int counter = 0;
for(counter; string[counter] != '\0'; counter++);
return counter;
// Same as:
//int counter = 0;
// for(int i = 0; string[i] != '\0'; i++)
//{
// counter++;
//}
//return counter;
}
This one seems more efficient than the version with the loop body as no local variable for the for-loop is initialised. Is it conventional to do these sorts of loops with no bodies?
Step 1: Correctness
Make sure code is correct.
Consider OP's code below. Does it attempt to print argv[argc] which would be bad?
if (argc > 1) {
for(int i = 1; puts(argv[i++]), i < argc;);
I initially thought it did. So did another user. Yet it OK.
… and this is exactly why code is weak.
Code not only should be correct, better code looks correct too. Using an anti-pattern as suggested by OP is rarely1 as good thing.
Step 2: Since code variations have the same big O, focus on understandably.
Sculpt your code – remove what is not needed.
for (int i = 1; i < argc; i++) {
puts(argv[i]);
}
What OP is doing is a trivial optimization concern.
Is premature optimization really the root of all evil?
Is it conventional to do these sorts of loops with no bodies?
Not really.
The key to the style of coding is to follow your group's style guide. Great software is often a team effort. If your group's likes to minimize bodies, go ahead. I have seen the opposite more common, explicit { some_code } bodies.
Note: int stringLength(const char * string) fails for strings longer than INT_MAX. Better to use size_t as the return type – thus an example of step 1 faltering.
1 All coding style rules, except this rule, have exceptions.

How would I modify this code so that it prints the output of the path it takes to get from point A to B

This code answers the question: Given a 2 dimensional matrix where some of the elements are filled with 1 and rest of the elements
are filled. Here X means you cannot traverse to that particular points. From a cell you can either traverse to left, right, up or down. Given two points in the matrix find the shortest path between these points.
I need help implementing a way to print the path between the two points, ex (1,3) -> (1,4), etc. Please help
#include <stdio.h>
#include <stdlib.h>
char arr[5][5]={ {'1','1','1','1','1'},
{'1','S','X','1','1'},
{'1','1','1','1','1'},
{'X','1','1','E','1'},
{'1','1','1','1','X'} };
int minimum[20];
int ind=0;
void addToMin(int len)
{
minimum[ind++]=len;
}
int IsInPath(int (*path)[5],int r,int c)
{
if(path[r][c]==0) return 0;
else return 1;
}
int isValid(int r,int c)
{
if((r>=0 && r<=4) && (c>=0 && c<=4))
return 1;
else
return 0;
}
void findMin(int (*path)[5],int len,int r,int c)
{
int path2[5][5];
int i,j;
for(i=0;i<;5;i++)
for(j=0;j<;5;j++)
path2[i][j]=0;
if(arr[r][c]=='E')
{
addToMin(len);
}
else if(arr[r][c]=='X' || (arr[r][c]=='1' && IsInPath(path,r,c)))
{
return;
}
else if((arr[r][c]=='1' && !IsInPath(path,r,c)) || arr[r][c]=='S')
{
for(i=0;i<;5;i++)
for(j=0;j<;5;j++)
path2[i][j]=path[i][j];
path2[r][c]=1;
len++;
if(isValid(r,c-1))
findMin(path2,len,r,c-1);
if(isValid(r-1,c))
findMin(path2,len,r-1,c);
if(isValid(r,c+1))
findMin(path2,len,r,c+1);
if(isValid(r+1,c))
findMin(path2,len,r+1,c);
}
}
int main()
{
int i,j,flag=0,min=9999;
int path[5][5];
for(i=0;i<;5;i++)
for(j=0;j<;5;j++)
path[i][j]=0;
for(i=0;i<;5;i++)
{
for(j=0;j<;5;j++)
{
if(arr[i][j]=='S')
{
findMin(path,0,i,j);
flag=1;
break;
}
}
if(flag==1) break;
}
for(i=0;i<ind;i++)
{
if(minimum[i]<min)
min=minimum[i];
}
printf("Minimum Distance =%d",min);
return 0;
}
regarding Your question: I need help implementing a way to print the path between the two points.
The comment by #Serge gives an excellent method of tracing the path from start to finish, with out also displaying any steps that were not kept. Here is a repeat of that comment:
use an array of x/y pairs or a list to record the path.
increment index on the way forward and decrement it before return (or add/remove last element from the list).
print the contents when reach the endpoint.
You will get a few different paths.
regarding statements like:
for(i=0;i<;5;i++)
the for() statement has 3 parameters separated via semicolons, not 4 parameters. Therefore, the semicolon between the i< and 5 should not be there.
There are several such syntax errors in the posted code.
The posted code contains the 'magic' number 5, buried all through the code. 'magic' numbers are numbers with no basis. 'magic' numbers make the code much more difficult to understand, debug, etc. Suggest:
#define MAX_ROWS 5
#define MAX_COLS 5
Then using those names throughout the code.
regarding:
int i,j,flag=0,min=9999;
and
if(path[r][c]==0) return 0;
else return 1;
Please follow the axiom: only one statement per line and (at most) one variable declaration per statement. I.E.
int i;
int j;
int flag=0;
int min=9999;
and
if( path[r][c]==0 )
return 0;
else
return 1;
or even:
return ( path[r][c] == 0 )? 0 : 1;
regarding:
int path[5][5];
for(i=0;i<;5;i++)
for(j=0;j<;5;j++)
path[i][j]=0;
This can be reduced to:
int path[5][5] = {0};
regarding:
int (*path)[5]
That expression/parameter might work when a parameter is a pointer to a pointer, as when working with a linked list, but is not correct for this problem. Suggest:
int path[][5]
as the main thing the compiler needs to know is the length of each row in the matrix.
For ease of readability and understanding:
Please consistently indent the code. Indent after every opening brace '{'. Unindent before every closing brace '}'. Suggest each indent level be 4 spaces.
insert an appropriate space: inside parens, inside braces, inside brackets, after semicolons, after commas, around C operators.
separate code blocks: for if else while do...while switch case default via a single blank line.
separate functions via 2 or 3 blank lines. Be consistent.
The compiler can read code those formatting is very 'messed up'. However, us humans work best with uniform, clean formatting of code.
regarding:
char arr[5][5]={ {'1','1','1','1','1'},
{'1','S','X','1','1'},
{'1','1','1','1','1'},
{'X','1','1','E','1'},
{'1','1','1','1','X'} };
In C, the compiler can determine the size of such data elements so, unless there is a very good reason to declare the sizes yourself, much better to let the compiler do it. Suggest:
char arr[][] =
{
{ '1','1','1','1','1' },
{ '1','S','X','1','1' },
{ '1','1','1','1','1' },
{ 'X','1','1','E','1' },
{ '1','1','1','1','X' }
};
Please explain the meaning of S, E, and X as their meaning is not clear from your question, nor easily derived from the posted code.
it is good coding/design practice to limit the scope of variables. Therefore statements like:
for( i=0; i<5; i++ )
are much better written as:
for( int i=0; i<5; i++ )
also, since indexes like 'i' will never be <0, much better to use size_t, as in:
for( size_t i=0; i<5; i++ )

Is it cheating to use 'static' when writing a recursive algorithm?

As part of a programming assignment, I'm required to write a recursive function which determines the largest integer in an array. To quote the exact task:
Write a recursive function that finds the largest number in a given list of
integers.
I have come up with two solutions, the first of which makes two recursive calls:
int largest(int arr[], int length){
if(length == 0)
return 0;
else if(arr[length - 1] > largest(arr,length -1))
return arr[length];
else return largest(arr,length -1);
}
The second one makes only one, however it uses a static variable n:
int largest(int arr[], int length){
static int n = -1;
if(length == 0)
return n;
else if (arr[length - 1] > n)
n = arr[length - 1];
return largest(arr, length - 1);
}
I was wondering whether it would be considered cheating use static variables for such a task. Either way, which one is considered better form? Is there a recursive method which tops both?
I wouldn't say that it's cheating to use static variables this way - I'd say that it's incorrect. :-)
Imagine that you call this function multiple times on a number of different arrays. With the static variable introduced, the value of n never resets between calls, so you may end up returning the wrong value. Generally speaking, it's usually poor coding style to set things up like this, since it makes it really easy to get the wrong answer. Additionally, if your array contains only negative values, you may return -1 as the answer even though -1 is actually bigger than everything in the array.
I do think that the second version has one nice advantage over the first - it's much, much faster because it makes only one recursive call rather than two. Consider using the first version, but updating it so that you cache the value returned by the recursive call so that you don't make two calls. This will exponentially speed up the code; the initial version takes time Θ(2n), while the updated version would take time Θ(n).
There is nothing cheating using a static inside function, recursive or otherwise.
There can be many good reasons for why to do so, but in your case I suspect that you are coming up with a wrong solution -- in as largest will only work once in the lifetime of the program running it.
consider the following (pseudo) code;
main() {
largest([ 9, 8, 7]) // would return 9 -- OK
largest([ 1, 2, 3]) // would return 9 ?? bad
}
The reason being that your largest cannot tell the difference between the two calls, but if that is what you want then that is fine.
Edit:
In answer to your comment, something like this will have a better big-O notation than your initial code;
int largest(int arr[], int length){
int split, lower,upper;
switch (length) {
case 1: return arr[0];
case 2: if (arr[1]>arr[0]) return arr[1]; else return arr[0];
default:
if (len <= 0) throw error;
split = length/2;
lower = largest(arr,split);
upper = largest(arr+split,length-split);
if (lower > upper) return lower; else return upper;
}
}
Alternatively, the obvious solution is;
int largest(int arr[], int length){
if (length <= 0) thor error;
int max = arr[0];
for (int i=1; i<length; i++)
if (arr[i] > max) max = arr[i];
return max;
}
which has no recursion at all
It is actually a terrible design, because on the second execution of the function does not return a correct result.
I don't think you need to debate whether it is cheating, if it is wrong.
The first version is also incorrect, because you return arr[length] instead of arr[length-1]. You can eliminate the second recursive call. What can you do instead of calling the same function (with no side-effects) twice with the same arguments?
In addition to the excellent points in the three prior answers, you should practice having more of a recursion-based mind. (1) Handle the trivial case. (2) For a non-trivial case, make a trivial reduction in the task and recur on the (smaller) remaining problem.
I propose that your proper base case is a list of one item: return that item. An empty list has no largest element.
For the recursion case, check the first element against the max of the rest of the list; return the larger. In near-code form, this looks like the below. It makes only one recursive call, and has only one explicit local variable -- and that is to serve as an alias for the recursion result.
int largest(int arr[], int length){
if(length == 1)
// if only one element, return it
return arr[0];
else n = largest(arr,length-1))
// return the larger of the first element or the remaining largest.
return arr[length-1] > n ? arr[length-1] : n
}
Is there a recursive method which tops both?
Recursion gets a bad name when with N elements cause a recursion depth of N like with return largest(arr,length -1);
To avoid this, insure the length on each recursion is halved.
The maximum recursive depth is O(log2(N))
int largest(int arr[], int length) {
if (length <= 0) return INT_MIN;
int big = arr[0];
while (length > 1) {
int length_r = length / 2;
int length_l = length - length_r;
int big_r = largest(&arr[length_l], length_r);
if (big_r > big) big = big_r;
length = length_l;
}
return big;
}
A sneaky and fast method that barely uses recursion as finding the max is trivial with a loop.
int largest(int arr[], int length) {
if (length <= 0) return INT_MIN;
int max = largest(NULL, -1);
while (length) {
length--;
if (arr[length] > max) max = arr[length];
}
return max;
}

How to make a variable value passage for preprocessor?

Here I know that the following code simply copies the character i rather than its value to the preprocessor statement (which makes a error for undefined symbol i in compile-time).
What I want is:
Is their a way such that the compiler treats, i as a variable with some value rather than a character ?
#include <stdio.h>
#define PRINT(x) printf("%d \n", y ## x)
int main(void) {
int y1=0 , y2=1 , y3=4;
for(int i=1; i <= 3; ++i) {
PRINT(i);
}
return 1;
}
About the pre-processor
First of all, I think there's a need to clarify how the preprocessor works: it pre-processes the input files, which means it runs before the compiler. Unfortunatly, for historical reasons, it doesn't know anything about C or C++, doesn't parse anything, and just does very simple textual operations on words and parenthesis. Just to illustrate my point:
#define this __FILE__
#define file -- Hell no!
#define fine(a, b) fine: a ## _ ## b
Ok, so this is not a valid C or C++ file
But the preprocessor will run just fine(go, try!)
Run this with a pre-processor, for example gcc -x c -E -P test.txt and you'll get:
Ok, so "test.txt" is not a valid C or C++ -- Hell no!
But the preprocessor will run just fine: go_try!
So, obviously, when the preprocessor sees PRINT(i) in your code, it replaces it with printf("%d \n", yi) without thinking much about it. And it has absolutely no idea i is a variable, don't even think about evaluating it's value.
Solutions
Basically, what you want is print a bunch of numbers.
You could simply do
printf("0\n1\n4\n");
But this lacks makes changing numbers cumbersome,
so let's go with
printf("%d\n%d\n%d\n", 0, 1, 4);
Which makes it easy to change a number, but not to add/remove one.
Ok so how about:
printf("%d\n", 0);
printf("%d\n", 1);
printf("%d\n", 4);
Yeah, you can change/add/remove numbers easily but as any sane programmer you hate repetition. So, we need some kind of loop.
By far the simplest and most straightforward way to iterate in C is at runtime, using an array:
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/sizeof(int); ++i) {
printf("%d\n", y[i]);
}
If you want, you can hide the printf using a function:
inline void print_int(int* y, int i) { print_int(y[i]); }
int [] y = { 0, 1, 4 };
for(int i = 0; i < sizeof(y)/4; ++i) print_int(y, i);
And going further with functions:
inline void print_int(int x) { printf("%d\n", x); }
inline void print_int(int* y, int i) { print_int(y[i]); }
inline void print_ints(int * y, int n)
{
for(int i = 0; i < n; ++i)
print_int(y, i);
}
template<int n> // C++
inline void print_ints(const int[n] & y) { print_ints(&y[0], n); }
int [] y = { 0, 1, 4 };
print_ints(y); // C++
// or in C:
print_ints(y, sizeof(y)/sizeof(int));
Now, what if you absolutely want the generated code to look like solution 3. ? This means you need the iteration to happen at compile-time. Tricky!
That's where the preprocessor can come into play. There are (hacky) ways to make it do this kind of things. I strongly recommend not implementing this yourself (except to play), but use the Boost.preprocessor library instead:
#define PRINTER(R,D, NUMBER) printf("%d\n", NUMBER);
#define NUMBERS (0, 1, 4)
BOOST_PP_LIST_FOR_EACH(PRINTER, _, BOOST_PP_TUPLE_TO_LIST(NUMBERS))
// will expand to printf("%d\n", 0); printf("%d\n", 1); printf("%d\n", 4);
Under standard C, this is not possible; during preprocessing, the compiler simply sees the identifier i as simply that - an identifier. It does not know that i is of type int, or that it's even a variable in the first place.
The easiest way to achieve what's intended is to use an array, like so:
int i;
int y[] = { 0, 1, 4 };
for (i = 0; i < 3; i++) // NOTE: arrays in C start at index 0, not 1
{
printf("%d \n", y[i]);
}
Also note that I got rid of the macro, as you want to use the value of a runtime variable i to select another runtime variable.

What is the utility of a bool variable in C?

What is the advantage of using bool variable in the code below instead of an int to set the value 1 or 0? What difference does it make?
#include<stdio.h>
int main(void)
{
int p,d;
_Bool isPrime;
for ( p = 2; p <= 50; p++){
isPrime = 1;
for (d = 2; d < p; d++)
if (p %d == 0)
isPrime = 0;
if (isPrime != 0)
printf("%i ",p);
}
printf("\n");
return 0;
}
It's useful for making your intent clear. When you declare a variable as Bool_, it's obvious it's never supposed to have a value other than true and false.
A more conventional way to write your example code would be:
#include
int main(void)
{
for (int p = 2; p <= 50; p++) {
bool isPrime = true;
for (int d = 2; d < p; d++) {
if (p % d == 0) isPrime = false;
}
if (!isPrime) printf("%i ", p);
}
printf("\n");
return 0;
}
I just use plain ints as my boolean type without any typedefs or special defines or enums for true/false values. If you follow my suggestion below on never comparing against boolean constants, then you only need to use 0/1 to initialize the flags anyway. However, such an approach may be deemed too reactionary in these modern times. In that case, one should definitely use since it at least has the benefit of being standardized.
Whatever the boolean constants are called, use them only for initialization. Never ever write something like
if (ready == TRUE) ...
while (empty == FALSE) ...
These can always be replaced by the clearer
if (ready) ...
while (!empty) ...
Note that these can actually reasonably and understandably be read out loud.
Give your boolean variables positive names, ie full instead of notfull. The latter leads to code that is difficult to read easily. Compare
if (full) ...
if (!full) ...
with
if (!notfull) ...
if (notfull) ...
Both of the former pair read naturally, while !notfull is awkward to read even as it is, and becomes much worse in more complex boolean expressions.
Boolean arguments should generally be avoided. Consider a function defined like this
void foo(bool option) { ... }
Within in the body of the function, it is very clear what the argument means since it has a convenient, and hopefully meaningful, name. But, the call sites look like
foo(TRUE);
foo(FALSE):
Here, it's essentially impossible to tell what the parameter mean without always looking at the function definition or declaration, and it gets much worse as soon if you add even more boolean parameters.. I suggest either
typedef enum { OPT_ON, OPT_OFF } foo_option;
void foo(foo_option option);
or
#define OPT_ON true
#define OPT_OFF false
void foo(bool option) { ... }
In either case, the call site now looks like
foo(OPT_ON);
foo(OPT_OFF);
which the reader has at least a chance of understanding without dredging up the definition of foo.

Resources