Coming from a Java background I'm learning C, but I find those vague compiler error messages increasingly frustrating. Here's my code:
/*
* PURPOSE
* Do case-insensetive string comparison.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int compareString(char cString1[], char cString2[]);
char strToLower(char cString[]);
int main() {
// Declarations
char cString1[50], cString2[50];
int isEqual;
// Input
puts("Enter string 1: ");
gets(cString1);
puts("Enter string 2: ");
gets(cString2);
// Call
isEqual = compareString(cString1, cString2);
if (isEqual == 0)
printf("Equal!\n");
else
printf("Not equal!\n");
return 0;
}
// WATCH OUT
// This method *will* modify its input arrays.
int compareString(char cString1[], char cString2[]) {
// To lowercase
cString1 = strToLower(cString1);
cString2 = strToLower(cString2);
// Do regular strcmp
return strcmp(cString1, cString2);
}
// WATCH OUT
// This method *will* modify its input arrays.
char strToLower(char cString[]) {
// Declarations
int iTeller;
for (iTeller = 0; cString[iTeller] != '\0'; iTeller++)
cString[iTeller] = (char)tolower(cString[iTeller]);
return cString;
}
This generates two warnings.
- assignment makes pointer from integer without a cast
- cString1 = strToLower(cString1);
- cString2 = strToLower(cString2);
- return makes integer from pointer without a cast
- return cString;
Can someone explain these warnings?
This is an array, i.e. a pointer to the first element of a range of elements of the same data type. Note you're not passing the array by-value but by-pointer.
However, this returns a char. So your assignment
has different types on each side of the assignment operator .. you're actually assigning a 'char' (sort of integer) to an array, which resolves to a simple pointer. Due to C++'s implicit conversion rules this works, but the result is rubbish and further access to the array causes undefined behaviour.
The solution is to make
strToLower
returnchar*
.As others already noted, in one case you are attempting to return
cString
(which is achar *
value in this context - a pointer) from a function that is declared to return achar
(which is an integer). In another case you do the reverse: you are assigning achar
return value to achar *
pointer. This is what triggers the warnings. You certainly need to declare your return values aschar *
, not aschar
.Note BTW that these assignments are in fact constraint violations from the language point of view (i.e. they are "errors"), since it is illegal to mix pointers and integers in C like that (aside from integral constant zero). Your compiler is simply too forgiving in this regard and reports these violations as mere "warnings".
What I also wanted to note is that in several answers you might notice the relatively strange suggestion to return
void
from your functions, since you are modifying the string in-place. While it will certainly work (since you indeed are modifying the string in-place), there's nothing really wrong with returning the same value from the function. In fact, it is a rather standard practice in C language where applicable (take a look at the standard functions likestrcpy
and others), since it enables "chaining" of function calls if you choose to use it, and costs virtually nothing if you don't use "chaining".That said, the assignments in your implementation of
compareString
look complete superfluous to me (even though they won't break anything). I'd either get rid of themor use "chaining" and do
(this is when your
char *
return would come handy). Just keep in mind that such "chained" function calls are sometimes difficult to debug with a step-by-step debugger.As an additional, unrealted note, I'd say that implementing a string comparison function in such a destructive fashion (it modifies the input strings) might not be the best idea. A non-destructive function would be of a much greater value in my opinion. Instead of performing as explicit conversion of the input strings to a lower case, it is usually a better idea to implement a custom char-by-char case-insensitive string comparison function and use it instead of calling the standard
strcmp
.