I have a function that currently returns unsigned char. However, I want to cast that unsigned char to a char* but I keep getting cast to/from pointer from/to integer of different size warning.
Let foo be the function that return an unsigned char
I tried something like this:
char* convert = (char*)foo();
The reason for converting to char* is because I need to use the strcasecmp function to perform a string compare.
To achieve what you want, use the following code:
char array [2];
array [0] = (char) foo ();
array [1] = '\0';
...
... strcasecmp (array, ...);
This builds an array containing a string of a single character which you can then use.
You can't cast a non-pointer function return value into a pointer at all. Think about it, where would this pointer point to?
You can, however, save the result to a variable and have a pointer to it.
For example,
char tmp = (char) foo();
char * ptr = &tmp;
Edit:
As another answer said, if you want to use strcasecmp you would need a char array where the last byte is the null terminator.
Related
I am writing a simple function in C that should build a char array from string "abc" – so it should build {'a','b','c'} – and return a pointer to that array. Here is my code for this function:
char * makeArr()
{
static char arr[3];
sprintf(arr, "%s\n", "abc");
return arr;
}
Problems occur when I call this method in main:
int main(int argc, char *argv[])
{
char *arr[3];
arr = makeArr();
return 0;
}
The compiler is complaining about casting / conflicting types. I've been playing with pointers, casting and dereferencing for quite a while now, but can't seem to get it to work. Please let me know where my logic is wrong.
Hmm ... there are several errors in this code. Let's start with the most obvious your compiler complains about:
char *arr[3];
This line declares arr to be an array of three pointers to char. What you return from your function is a single pointer to a char -> doesn't match.
Next:
static char arr[3];
sprintf(arr, "%s\n", "abc")
Here you reserve 3 chars. the sprintf() will write 5 chars. %s is replaced by the 3 characters in your string literal "abc". You add a newline character and then a 0 is added as the marker for the end of the "string". Makes 5. This btw is undefined behavior. You write past the end of your array. Code like this can be compiled, but there's no guarantee at all about what will happen at runtime.
Doing a cut here. You should read about arrays and pointers in C. If the text you're reading claims they are the same ... stop right there and find a better text. They aren't.
I'll try to explain this here briefly, so it's suitable for the Q&A style.
An array in C indeed is a contiguous space of several values. char arr[3] means a variable that holds 3 chars.
On the other hand, a char * is just a pointer pointing to a char -- this could be the first element of an array.
In C, you can't pass arrays as function parameters, and you can't return arrays from a function. Trying to do so leads to an implicit conversion: What is actually passed is a pointer to the first element of that array.
I think the last bit of information missing is what a string literal in C is: it's an array (anonymous, e.g., it doesn't have a name) containing all the characters in the double quotes plus a 0 appended. The 0 marks the end of a "string" in C.
In an expression, a string literal evaluates to a pointer to the first element.
So, something like this:
char *foo = "bar";
will lead to foo pointing to the b of the array. It's like writing
static const char no_name_0[] = { 'b', 'a', 'r', 0 };
char *foo = &(no_name_0[0]);
Among other things, you confused:
char arr[3]; // array of 3 chars.
and,
char *arr[3]; // array of 3 pointers to char.
In main(), you should only write char *arr;
Firstly, char arr[3]; is too snall to store "abc\n". It must have at least 5 elements including terminating null-character.
Then, char *arr[3]; is a 3-element array of char*.
You should assign makeArr()'s return value (it has char* type) to arr[0] or another element, or you should change the type of arr in main function to char*, which is the same type as makeArr()'s return value.
Moreover, this makeArr() doesn't make any array and returns (a pointer to) the existing array. Yoy should use malloc() to "make an array".
UPDATE:
Assigning a value of char* to the array char arr[10]; seems invalid in C.
You should use strcpy() or strncpy() (safer than strcpy()) to copy the string stored in the array between arrays.
Pass the array as an argument and modify it in the called function, would be easier. If you're statically creating the array and there's no need to allocate memory, don't, just pass around your pointers to the functions to be modified by reference
void makeArr(char arr[]){
sprintf(arr, "%s\n", "abc");
}
Simply pass the existing declared array to the makeArr function...
int main(int argc, char *argv[]) {
char arr[10];
makeArr(arr);
return 0;
}
You couldn't assign the result of makeArr to arr. I guess that's your casting error. Oversimplifying, arr points to the place on the stack where the array of 10 characters is allocated. So, I'd pass in arr to makeArr as a char*. So, you'd end up with something like this:
#include <stdio.h>
char * makeArr(char *arr)
{
sprintf(arr, "%s\n", "abc");
return arr;
}
int main(int argc, char *argv[])
{
char arr[10];
makeArr(arr);
printf("%s\n", arr);
return 0;
}
struct command
{
char *abc[1000];
};
One of the variable is defined in a structure. This char pointer array contains the value after reading the value from file. For example {123,121}.
Now I want to cast these value in array of array of char, something like this:
char a1[][1000]= s1->abc[j];
I am not sure about the syntax... So how should I cast these values in array abc in a1.
If I understand correctly you have an array of 1000 char*, that might have different length (in your example, length is 2). And s1 type is struct command.
Then I think you meant:
char a1[1000][] = s1->abc;
Or:
char a1[] = s1->abc[j];
But I am not sure why you would want to do that instead of:
char * a1[1000] = s1->abc;
Or
char ** a1 = s1->abc
Be careful with indexes though...
I have a char array. I take its address and pass it to a function which accepts a double char pointer:
char result[1024+1];
memset(result, 0, sizeof(result));
executeGetQuery(query, &(result));
Function definition: int executeGetQuery(char * query, char ** queryResultData)
I get this compile time error
warning: argument #2 is incompatible with prototype:
prototype: pointer to pointer to char : line 1531
argument : pointer to array[1025] of char
I've always passed arrays as pointers in C before. Why am I getting this error? Is my compiler to blame?
EDIT: What is the fix?
EDIT2: I want the function to write something to the result array which is why I am passing a char** instead of char*. What is then another way, the way, to have a function write to a param which I pass in?
char** here means the function will write into given memory location, something like:
int executeGetQuery(char * query, char ** queryResultData) {
char* buffer = malloc( ... );
/* get the query results into buffer */
*queryResultData = buffer;
...
}
You can't do that with array, its address is not writable.
What is the fix?
In this case (you don't need the char **) use char * both in the prototype and the calling code
int executeGetQuery(char *query, char *queryResultData);
executeGetQuery(query, result);
I'd also include a size argument for protecting against buffer overflows
int executeGetQuery(char *query, char *queryResultData, size_t len);
executeGetQuery(query, result, sizeof result);
Edit:
to change the contents of the array do something like
int executeGetQuery(char *query, char *queryResultData, size_t len) {
queryResultData[0] = 'H'; /* changing */
queryResultData[1] = 'i'; /* the contents */
queryResultData[2] = '\0'; /* of the array */
}
You can see the change in the calling function
executeGetQuery(NULL, result, sizeof result);
printf("result is now %s\n", result); /* should print "Hi" */
&result is not type char **. It is of type char (*)[1025].
You have to pass a pointer to a pointer to char to your function:
char *p;
executeGetQuery(query, &p);
The function probably takes a char** because it will allocate the result buffer for you and use the return value to indicate errors, for example. Therefore, it will return the buffer by modifying a char-pointer provided by you. To do this it needs to access its memory location. That's why the function takes a char**. So to use it correctly, you would need to do:
char *foo;
executeGetQuery(query, &foo); // foo now points to the result buffer
Although you can use arrays in some contexts, where pointers are required in C, they are not the same. Your example makes it easy to see why: result is already an allocated memory region (most likely on the stack, if it's a local variable), so it can decay into a pointer pointing to its first element, but it cannot be a lvalue, like a pointer can.
I'm not sure I can explain this 100% understandably, but the compiler is correct. A char** is a pointer to a memory location where a char pointer is stored.
You're not passing in a memory location storing a pointer, but instead try to pass in the address of a char array. You can manually assign the char array to a char pointer variable and use the address of that variable, but the compiler won't automatically create that temporary variable for you.
I study C. Digging in some C source code where I found that line. I have read about pointers, but I did not see such an example.
char *uppercase (char *s);
What that mean ?
It's a declaration of a function that takes a char pointer and returns a char pointer.
That means that the function takes a pointer to a character and returns a pointer to a character i.e the start of the string.
char *uppercase (char *s);
is the same as
char* uppercase (char *s);
Its return type is char*; it returns a pointer.
uppercase is afunction which returns a char type address ( that is, it can be stored in a char pointer ) as its written as char *uppercase...
uppercase() takes a char pointer as argument char *s...
therefore its written as char *uppercase( char *s).
In C the location of the * doesn't matter as long as it is somewhere between the type and name. So char* s is the same as char *s and even char * s.
The same applies to functions and their return types, char* uppercase() is equivalent to char *uppercase() and char * uppercase().
White-space is more or less ignored in C so when writing your own code I recommend you pick one format and stick with it.
The location of the asterisk * can be anywhere: between return type or function name.
It is more logical to keep it on the return type's end i.e. char*
I am using two buffers which are of unsigned char and when I used the function strcpy, there is a compilation error which says "invalid conversion of unsigned char * to char *". Can anyone please tell me what difference does an unsigned buffer vs. signed buffer makes to the output? This is the program which I had tried.
main()
{
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
strcpy(buff,dst);
printf("The string is %s\n",buff);
}
Now when i typecast the parametrs passed in strcpy to (char *),This programe works fine as shown below
main()
{
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
strcpy((char *)buff,(char *)dst);
printf("The string is %s\n",buff);
}
2nd Question: Does typecasting to char* in the string function create any issues?
Please do let me know if you need any more inputs.
You can just change:
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
to
char buff[20] = "Michael";
char dst[20] = "Jackson";
To think of it logically, A string cannot be signed or unsigned, it is not a numeric value to be treated that way, it is just an char array and you should declare and use it so.
Why do you get the error?
strcpy has the prototype:
char *strcpy(char *restrict s1, const char *restrict s2);
And what you are passing to it is, unsigned char*, when a function is called parameter type checking takes place and the compiler finds that you are not calling the function with proper type parameters and hence it complains about it, When you apply a cast the function arguments match and hence compilation passes.
Does typecasting to char in the string function create any issues?*
No, in this case it doesn't.
Though it makes more sense to change your usage of unsigned char for the reasons mentioned above in the answer.
Suggestion:
Strcpy is not safe, so you are much better off using strncpy, it allows you to explicitly specify how many characters to copy, rather than rely on null terminator of the source string, Also this helps avoiding buffer overflow since you explicitly specify a length.
The way you are using it should be fine.
But you shouldn't use unsigned char arrays with string handling functions. In C strings are char arrays, not unsigned char arrays. Since passing to strcpy discards the unsigned qualifier, the compiler warns.
As a general rule, don't make things unsigned when you don't have to.
strcpy wants char *'s, plain and simple. Cast your buffers to char *'s and you'll be fine. Then there's the whole safety problem with using strcpy in the first place...