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*
Related
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.
void skip(char *msg)
{
puts(msg+6);
}
char *message="Don't call me";
skip(message);
My doubt is why we don't use
puts(*(msg+6)) to display text from 7th character onward;
according to me (msg+6) refers to memory and *(msg+6) content
*msg is essentially a reference to a single char, not to the string of char's. due to this char * and char[] are essentially the same thing and you don't need to dereference character pointer in C because compiler automatically print fully string from given base address upto '\0' not get. you can also refer this for more info .
#include <stdio.h>
void skip(char *msg) {
puts(msg + 6);
}
int main() {
char *message = "Don't call me";
skip(message);
}
This is what you can find in puts manual:
int puts(const char *s);
as you can see it also expects pointer to a content as a parameter, rather than an actual value.
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'm learning the C language.
My question is:
Why is the param of strlen a "const" ?
size_t strlen(const char * string);
I'm thinking it's because string is an address so it doesn't change after initialization. If this is right, does that mean every time you build a function using a pointer as a param, it should be set to a constant ?
Like if I decide to build a function that sets an int variable to its double, should it be defined as:
void timesTwo(const int *num)
{
*num *= 2;
}
or
void timesTwo(int *num)
{
*num *= 2;
}
Or does it make no difference at all ?
C string is a pointer to a zero-terminated sequence of characters. const in front of char * indicates to the compiler and to the programmer calling the function that strlen is not going to modify the data pointed to by the string pointer.
This point is easier to understand when you look at strcpy:
char * strcpy ( char * destination, const char * source );
its second argument is const, but its first argument is not. This tells the programmer that the data pointed to by the first pointer may be modified by the function, while the data pointed to by the second pointer will remain constant upon return from strcpy.
The parameter to strlen function is a pointer to a const because the function is not expected to change what the pointer points to - it is only expected to do something with the string without altering it.
In your function 'timesTwo', if you intend to change the value that 'num' points to, you should not pass it in as a pointer-to-const. So, use the second example.
Basically, the function is promising that it will not modify the contents of of the input string through that pointer; it says that the expression *string may not be written to.
Here are the various permutations of the const qualifier:
const char *s; // s may be modified, *s may not be modified
char const *s; // same as above
char * const s; // s may not be modified, *s may be modified
const char * const s; // neither s nor *s may be modified
char const * const s; // same as above
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...