Can someone help me understand why I would be getting "warning: cast to pointer from integer of different size" for the following two lines of code?
so I have a pointer to a string (char *string) and a double pointer (char **final) that needs to the store the address of the last char in string... I thought the following lines of code would work but I keep getting the error... How do I fix it?
char last = *string;
*final = (char *)last;
(char *)last
last is of type char. Casting it to a pointer means the numeric code of the character stored in last will be interpreted as an address. So if last contains A, then this will cause the value 65 to be interpreted as an address. (Assuming ASCII). The compiler is smart and indicates that this is probably not the behavior you intend.
If string is a pointer to the last character in the string, last is a copy of that character. Since it's just a copy of the value, it bears no relationship to the location in the original string. To save that pointer into what final points to, you should do:
*final = string;
To declare a variable you have to specify what type you want the variable to be, and then what you want to call the variable. If you want a variable of type "char", called "last", it can be achieved by the following syntax:
char last;
If you want a pointer to a variable of a certain data type, you add the asterisk symbol like so:
char *last;
Now you have a pointer that you can use to point at a place in memory which have to contain a char. If you are trying to create a "string" in c, that is nothing more but a series of char's, that are ordered consecutively in memory. You can use a char pointer to point at the first char in this series of char's, and then you can use specific functions that work on strings (for example strcpy or strlen), by giving this char pointer as input argument.
Now to your problem. Let's say you create a string like this:
char *str = "example";
what you have done is create a series of char's, namely
'e', 'x', 'a', 'm', 'p', 'l', 'e', '\0'
(where the '\0' is the NULL character that marks the end of the string. This is necessary for any functions working on strings to recognize where the string ends). The char pointer you have created called "str" points at the first char, that is 'e'. Remember, the pointer has the address of this char, and all the rest of the chars are stored in the address space following this first char.
To access a particular char in this string, you have to dereference the pointer "str". If you want the first char in the string, you do this:
char first = *char;
This will save the first char in a variable of type char called "first", that is in this case the letter 'e'. To get the second char you do this:
char second = *(char+1);
What you're actually doing is "reading" (dereferencing) the value that your char pointer "str" is pointing to + 1 step of size "char" in memory. In this example, this means that the variable of type char called "second" now contains (the ASCII-value representing) the second letter in the string, that is 'x'.
If you want the size of a string you can use the function strlen. The syntax is this:
int length = strlen(str);
where "str" is our char pointer that is pointing at the first char in our string (that is 'e'). strlen will return the length of the string, not including the NULL character '\0' that simply marks the end of the string. That means in our example, length will equal 7, since there are 7 letters in the word "example". If you want to extract the last letter of this string, now all you have to do is what we did before, but remember that indexing in C start at 0. This means that if you have a string of length 7, the last element of this string will be located at "index" 6. Thus, to get the last char of a string you have to do this:
char last = *(str+length-1);
or if you have not saved length to a variable of type int, you can do it like this instead:
char last = *(str+strlen(str)-1);
If you want a pointer, pointing to the last char of the string, you have to initialize a new char pointer and make it point to place (memory address) where the last char of "str" is located. By the same logic as before, this is given by the memory address of the char at "index" 6 of our original string "str". So you create a new pointer, and let that pointer point to this memory address like this:
char *last = str+strlen(str)-1;
Remember that you need to include the header file string.h at the top of your file like so:
#include <string.h>
Related
I'm recollecting my C programming skills after 1 year. So I decided to start from scratch. I got stuck with poineters
why i can do :
char *string="Hello";
printf ("%s",string);
But i can't do :
int *pt=23;
printf("%d",*pt);
Doesn't the pointer need to be an address ? but why the first example works?
Because using string literals to initialize a character pointer or array is a special allowed syntax, with specific rules. In your case you set a pointer to point at a string literal's address, the string literal itself having type char[] and existing in read-only memory.
For the integer case, yes it needs to be an address, or more specifically another integer pointer. You can't initialize a pointer with an integer. See:
"Pointer from integer/integer from pointer without a cast" issues
The string literal "Hello" is stored in memory as a character array like
char unnamed_literal[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
So in this declaration
char *string="Hello";
the pointer string is assigned with the address of the first character of the already existent array. It can be imaging like
char unnamed_literal[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
char *string = unnamed_literal;;
As for this declaration
int *pt=23;
then the value 23 is not a valid address that points to a valid object defined in your program. The compiler should issue a message that you are trying to assign an integer to a pointer. Thus this call
printf("%d",*pt);
invokes undefined behavior.
To make an analogy with the initialization of a pointer by string literal you could write for example
int a[] = { 1, 2, 3 };
int *pt = a;
This is syntaxic sugar from standard C:
What is actually stored in your char pointer is the address at which the string is loaded in memory when starting the program.
For an integer however, it will try to set the address of the pointer to 23 which is (and should be) invalid.
For example an integer, like:
int VAL = 10;
int *ptr = &VAL; /* ptr now points to val */
*ptr = DESIRED_VALUE; /* *(asterisk) here means dereference, meaning that the value of VAL will change */
or
int *&VAL = DESIRED_VALUE;
int variable_1 = 23;
int *pointer_to_int = &variable_1;
The first line is an integer variable, initialized to an integer value.
The second line is a pointer to integer variable, initialized to an address of an integer variable (the address of the variable variable_1, defined in the previous declaration.
char *p = "Charles Dickens";
This is a char pointer variable, initialized to the address of a string literal, which is a constant array of characters, composed of the characters between the quotes, plus an aditional \0 character, that represents the end of the string literal.
char c = 'a'; /* char variable initialized to value 'a' */
char *pointer_to_c = &c;
Probably you will find this last declaration very similar to the one above. The different thing is that in C you can use string literals, but a single character is similar to an integer, and this is the way pointer variables initialize: with variables addresses.
A few questions regarding C strings:
both char* and char[] are pointers?
I've learned about pointers and I can tell that char* is a pointer, but why is it automatically a string and not just a char pointer that points to 1 char; why can it hold strings?
Why, unlike other pointers, when you assign a new value to the char* pointer you are actually allocating new space in memory to store the new value and, unlike other pointers, you just replace the value stored in the memory address the pointer is pointing at?
A pointer is not a string.
A string is a constant object having type array of char and, also, it has the property that the last element of the array is the null character '\0' which, in turn, is an int value (converted to char type) having the integer value 0.
char* is a pointer, but char[] is not. The type char[] is not a "real" type, but an incomplete type. The C language is specified in such a way that, in the moment that you define a concrete variable (object) having array of char type, the size of the array is well determined in some way or another. Thus, none variable has type char[] because this is not a type (for a given object).
However, automatically every object having type array of N objects of type char is promoted to char *, that is, a pointer to char pointing to the initial object of the array.
On the other hand, this promotion is not always performed. For example, the operator sizeof() will give different results for char* than for an array of N chars. In the former case, the size of a pointer to char is given (which is in general the same amount for every pointer...), and in the last case gives you the value N, that is, the size of the array.
The behaviour is differente when you declare function arguments as char* and char[]. Since the function cannot know the size of the array, you can think of both declarations as equivalent.
Actually, you are right here: char * is a pointer to just 1 character object. However, it can be used to access strings, as I will explain you now: In the paragraph 1. I showed you that the strings are considered objects in memory having type array of N chars for some N. This value N is big enough to allow an ending null character (as all "string" is supposed to be in C).
So, what's the deal here?
The key point to understand this issues is the concept of object (in memory).
When you have a string or, more generally, an array of char, this means that you have figured out some manner to hold an array object in memory.
This object determines a portion of RAM memory that you can access safely, because C has assigned enough memory for it.
Thus, when you point to the first byte of this object with a char* variable, actually you have guaranteed access to all the adjacent elements to the "right" of that memory place, because those places are well defined by C as having the bytes of the array above.
Briefly: the adjacent (to the right) bytes of the byte pointed by a char* variable can be accessed, they are valid places to access, so the pointer can be "iterated" to walk through these bytes, up to the end of the string, without "risks", since all the bytes in an array are contiguous well defined positions in memory.
This is a complicated question, but it reveals that you are not understanding the relationship between pointers, arrays, and string literals in C.
A pointer is just a variable pointing to a position in memory.
A pòinter to char points to just 1 object having type char.
If the adjacent bytes of the pointed position correspond to an array of chars, they will be accessible by the pointer, so the pointer can "walk on" the memory bytes occupied by the array object.
A string literal is considered as an array of char object, which implictely add an ending byte with value 0 (the null character).
In any case, an array of T object has a well defined "size".
A string literal has an additional property: it's a constant object.
Try to fit and gather these concepts in your mind to figure out what's going on.
And ask me for clarification.
ADDITIONAL REMARKS:
Consider the following piece of code:
#include <stdio.h>
int main(void)
{
char *s1 = "not modifiable";
char s2[] = "modifiable";
printf("%s ---- %s\n\n", s1, s2);
printf("Size of array s2: %d\n\n", (int)sizeof(s2));
s2[1] = '0', s2[3] = s2[5] = '1', s2[4] = '7',
s2[6] = '4', s2[7] = '8', s2[9] = '3';
printf("New value of s2: %s\n\n",s2);
//s1[0] = 'X'; // Attempting to modify s1
}
In the definition and initialization of s1 we have the string literal "not modifiable", which has constant content and constant address. Its address is assigned to the pointer s1 as initialization.
Any attempt to modify the bytes of the string will give some kind of error, because the array content is read-only.
In the definition and initialization of s2, we have the string literal "modifiable", which has, again, constant content and constant address. However, what happens now is that, as part of the initialization, the content of the string is copied to the array of char s2. The size of the array s2 is not specified (the declaration char s2[] gives an incomplete type), but after initialization the size of the array is well determined and defined as the exact size of the copied string (plus 1 character used to hold the null character, or end-of-string mark).
So, the string literal "modifiable" is used to initialize the bytes of the array s2, which is modifiable.
The right manner to do that is by changing a character at the time.
For more handy ways of modifying and assigning strings, it has to be used the standard header <string.h>.
char *s is a pointer, char s[] is an array of characters. Ex.
char *s = "hello";
char c[] = "world";
s = c; //Legal
c = address of some other string //Illegal
char *s is not a string; it points to an address. Ex
char c[] = "hello";
char *s = &c[3];
Assigning a pointer is not creating memory; you are pointing to memory. Ex.
char *s = "hello";
In this example when you type "hello" you are creating special memory to hold the string "hello" but that has nothing to do with the pointer, the pointer simply points to that spot.
I have only recently started learning C. I was going through the concept of arrays and pointers, when I came across a stumbling block in my understanding of it.
Consider this code -
#include<stdio.h>
int main()
{
char string[]="Hello";
char *ptr;
ptr=string;
puts(*ptr);
return(0);
}
It compiles, but runs into segmentation fault on execution.
The warning that I get is:
type error in argument 1 to `puts'; found 'char' expected 'pointer to char'
Now *ptr does return a character "H" and my initial impression was that it would just accept a char as an input.
Later, I came to understand that puts() expects a pointer to a character array as it's input, but my question is when I pass something like this - puts("H"), isn't that the same thing as puts(*ptr), given that *ptr does contain the character "H".
"H" is a string literal that consists of 2 bytes 'H' and '\0'. Whenever you have "H" in your code, a pointer to the memory region with 2 bytes is meant. *ptr simply returns a single char variable.
By doing puts(*str), you're dereferencing the str variable. This would then try and use the 'H' character as a memory address (since that's what str) points to, then segfault since it will be an invalid pointer (since it will probably fall outside your process' memory). This is because the puts function accepts a pointer as an argument.
What you really want is puts(str).
As an aside, the latter example puts("h") populates the string table with "h" at compile time and replaces the definition there with an implicit pointer.
The puts() function takes a pointer to a string and what you are doing is specifying a single character.
Take a look at this Lesson 9: C Strings.
So rather than doing
#include<stdio.h>
int main()
{
char string[]="Hello";
char *ptr;
ptr=string; // store address of first character of the char array into char pointer variable ptr
// ptr=string is same as ptr=&string[0] since string is an array and an
// array variable name is treated like a constant pointer to the first
// element of the array in C.
puts(*ptr); // get character pointed to by pointer ptr and pass to function puts
// *ptr is the same as ptr[0] or string[0] since ptr = &string[0].
return(0);
}
You should instead be doing
#include<stdio.h>
int main()
{
char string[]="Hello";
char *ptr;
ptr=string; // store address of first character of the char array into char pointer variable ptr
puts(ptr); // pass pointer to the string rather than first character of string.
return(0);
}
When ever you enter string in gets or want to display it using puts you had to actually pass the location of the pointer or the string
for example
char name[] = "Something";
if you want to print that
you have to write printf("%s",name); --> name actually stores the address of the string "something"
and by using puts if you want to display
puts(name) ----> same as here address is put in the arguments
No.
'H' is the character literal.
"H" is, in effect, a character array with two elements, those being 'H' and the terminating '\0' null byte.
puts is waiting as input a string pointer so it's waiting a memory address. but in your example you provided the content of the memory which is *ptr. the *ptr is the content of the memory with address ptr which is h
ptr is memory address
*ptr is the content of this memory
the input parameter of puts is an address type but you have provided a char type (content of the address)
the puts start the printing character by character starting by the address you give it as input until the memory which contain 0 and then it stop printing
I have just started learning pointers, and after much adding and removing *s my code for converting an entered string to uppercase finally works..
#include <stdio.h>
char* upper(char *word);
int main()
{
char word[100];
printf("Enter a string: ");
gets(word);
printf("\nThe uppercase equivalent is: %s\n",upper(word));
return 0;
}
char* upper(char *word)
{
int i;
for (i=0;i<strlen(word);i++) word[i]=(word[i]>96&&word[i]<123)?word[i]-32:word[i];
return word;
}
My question is, while calling the function I sent word which is a pointer itself, so in char* upper(char *word) why do I need to use *word?
Is it a pointer to a pointer? Also, is there a char* there because it returns a pointer to a character/string right?
Please clarify me regarding how this works.
That's because the type you need here simply is "pointer to char", which is denoted as char *, the asterisk (*) is part of the type specification of the parameter. It's not a "pointer to pointer to char", that would be written as char **
Some additional remarks:
It seems you're confusing the dereference operator * (used to access the place where a pointer points to) with the asterisk as a pointer sign in type specifcations; you're not using a dereference operator anywhere in your code; you're only using the asterisk as part of the type specification! See these examples: to declare variable as a pointer to char, you'd write:
char * a;
To assign a value to the space where a is pointing to (by using the dereference operator), you'd write:
*a = 'c';
An array (of char) is not exactly equal to a pointer (to char) (see also the question here). However, in most cases, an array (of char) can be converted to a (char) pointer.
Your function actually changes the outer char array (and passes back a pointer to it); not only will the uppercase of what was entered be printed by printf, but also the variable word of the main function will be modified so that it holds the uppercase of the entered word. Take good care the such a side-effect is actually what you want. If you don't want the function to be able to modify the outside variable, you could write char* upper(char const *word) - but then you'd have to change your function definition as well, so that it doesn't directly modify the word variable, otherwise the Compiler will complain.
char upper(char c) would be a function that takes a character and returns a character. If you want to work with strings the convention is that strings are a sequence of characters terminated by a null character. You cannot pass the complete string to a function so you pass the pointer to the first character, therefore char *upper(char *s). A pointer to a pointer would have two * like in char **pp:
char *str = "my string";
char **ptr_to_ptr = &str;
char c = **ptr_ptr_ptr; // same as *str, same as str[0], 'm'
upper could also be implemented as void upper(char *str), but it is more convenient to have upper return the passed string. You made use of that in your sample when you printf the string that is returned by upper.
Just as a comment, you can optimize your upper function. You are calling strlen for every i. C strings are always null terminated, so you can replace your i < strlen(word) with word[i] != '\0' (or word[i] != 0). Also the code is better to read if you do not compare against 96 and 123 and subtract 32 but if you check against and calculate with 'a', 'z', 'A', 'Z' or whatever character you have in mind.
the *words is even though a pointer bt the array word in function and the pointer word are actually pointing to the one and the same thing while passing arguments jst a copy of the "pointee" ie the word entered is passed and whatever operation is done is done on the pointer word so in the end we have to return a pointer so the return type is specified as *.
Why are pointers to arrays of chars (ie. strings) written as below:
char *path
Instead of:
char *path[]
or something like that?
How could I create a pointer to a char and not a string?
char *path is not a pointer to a string, it is a pointer to a char.
It may be the case that char *path semantically points to a "string", but that is just in the interpretation of the data.
In c, strings often use char *, but only under the assumption that the pointer is to the first character of the string, and the other characters are subsequent in memory until you reach a null terminator. That does not change the fact that it is just a pointer to a character.
char *path is a pointer to char. It can be used to point at a single char as well as to point at a char in a zero-terminated array (a string)
char *path[] is an array of pointers to char.
A pointer to an array of char would be char (*path)[N] where N (the size of the array) is part of the pointer's type. Such pointers are not widely used because the size of the array would have to be known at compile time.
char *path[] is an array of pointers. char *path is a single pointer.
How could I create a pointer to a char and not a string?
A 'string' in C is simply a pointer to a char that has the convention of being the start of a sequence of characters that ends in '\0'. You can declare a pointer to a single char the same way, you just have to take care to use it according to the data it's actually pointing to.
This is similar to the concept that a char in C is just an integer with a rather limited range. You can use that data type as a number, as a true/false value, or as a character that should be displayed as a glyph at some point. The interpretation of what's in the char variable is up to the programmer.
Not having a first class, full-fledged 'string' data type is something that distinguishes C from most other high level languages. I'll let you decide for yourself whether it distinguishes C in a good or a bad way.