I am trying to learn C, and I have come across char pointers, which do not really make sense to me...
I have seen many people do this:
char* something = "Hi";
printf("%s", something);
I thought a pointer is pointing to the memory adress of the variable? Should you not do something like *something = "Hi"?
A char pointer points to a single byte of memory. Since the string "Hi" takes more memory than a single byte, the char pointer just holds the address of the first character in the string, 'H'.
To demonstrate this, try dereferencing the pointer and printing it:
printf("%c\n", *something);
Otherwise, the %s option of printf (the one you are using) expects a pointer to the first character of a string and will print until it hits a zero byte.
It works. In the memory 3 Byte will be allocated for "Hi": 'H''i''\0', because " " means, that it is a string, which is terminated with 0 (\0). And you would like to point to the start of this sections, so "something" will contain the memory address of 'H'. In printf() %s means you will have a "string", which is terminated by 0 (\0). The printf will start to display characters from the address of H, which is saved in the "something" pointer and finishes when \0 found.
Related
Why *pointer is an integer but not the string content "Hello from pointer" Thanks!
int main(void) {
char *pointer;
pointer = "Hello from pointer";
printf("*pointer is %d\n", *pointer);
printf("\n");
}
the output is *pointer is 72
It's because the ASCII code for 'H' (which is the first element of the array) is 72. It is completely normal.
Here is the ASCII Code table
pointer = "Hello from pointer"; is pointing to the first letter of this string literal which is H and ASCII Value of 'H' is 72, that's why the output is 72.
In C, a constant character string always represents a pointer to that string. And therefore this statement is valid:
char *pointer = "Hello...";
This statement declares pointer as a pointer to character and assigns to pointer the constant character string "Hello..."
That'ss why when you printf("%d", *pointer); it outputs 72. Because, pointer is pointing to the first character of that constant string literal, which is 'H' and because of the format flag %d in printf() statement, it prints out the ASCII value of 'H', which is 72. Hope you got your explanation.
Here printf("*pointer is %d\n", *pointer); in this line you've used %d format specifier, not %s to print out the string pointer.
Again you should not de-reference the pointer variable when you print string from the string pointer. Try to search and find about String array vs String pointer.
So, the line should be printf("*pointer is %s\n", pointer);
More explanation:
char *pointer = "Hello from pointer";
After compiling this line, "Hello from pointer" will be stored in the memory. And like array variable, the pointer variable will hold the base address of this character array. So, the variable pointer will hold the address of H here.
Thus when you de-reference the pointer variable, it will show the value H. As the format specifier you used is %d, it's printing the integer value (ASCII Value) of the character H (72).
This is caused by a buffer overflow. (Read more here)
The direct answer is because 72 is the integer representation of the character "H" from "Hello from pointer".
Basically, there's two things going on.
1) That variable only expects you to give it one char
2) A pointer only points to a single part in memory, so since strings are treated sort of like "arrays" (per se), you're getting only the first value in the "array"
So if you were to print *pointer[1] you would get e. So the idea is to know the length of your string so you can safely determine how much space you need.
But remember, memory is volatile, so even though whatever compiler you use will open up a certain amount of "stack memory", you can overflow that with a long string.
If you don't know the length of your string and/or your string is very long, you can dynamically allocate it with malloc() and free().
I'm starting to understand pointers and how to dereference them etc. I've been practising with ints but I figured a char would behave similarly. Use the * to dereference, use the & to access the memory address.
But in my example below, the same syntax is used to set the address of a char and to save a string to the same variable. How does this work? I think I'm just generally confused and maybe I'm overthinking it.
int main()
{
char *myCharPointer;
char charMemoryHolder = 'G';
myCharPointer = &charMemoryHolder;
printf("%s\n", myCharPointer);
myCharPointer = "This is a string.";
printf("%s\n", myCharPointer);
return 0;
}
First, you need to understand how "strings" work in C.
"Strings" are stored as an array of characters in memory. Since there is no way of determining how long the string is, a NUL character, '\0', is appended after the string so that we know where it ends.
So for example if you have a string "foo", it may look like this in memory:
--------------------------------------------
| 'f' | 'o' | 'o' | '\0' | 'k' | 'b' | 'x' | ...
--------------------------------------------
The things after '\0' are just stuff that happens to be placed after the string, which may or may not be initialised.
When you assign a "string" to a variable of type char *, what happens is that the variable will point to the beginning of the string, so in the above example it will point to 'f'. (In other words, if you have a string str, then str == &str[0] is always true.) When you assign a string to a variable of type char *, you are actually assigning the address of the zeroth character of the string to the variable.
When you pass this variable to printf(), it starts at the pointed address, then goes through each char one by one until it sees '\0' and stops. For example if we have:
char *str = "foo";
and you pass it to printf(), it will do the following:
Dereference str (which gives 'f')
Dereference (str+1) (which gives 'o')
Dereference (str+2) (which gives another 'o')
Dereference (str+3) (which gives '\0' so the process stops).
This also leads to the conclusion that what you're currently doing is actually wrong. In your code you have:
char charMemoryHolder = 'G';
myCharPointer = &charMemoryHolder;
printf("%s\n", myCharPointer);
When printf() sees the %s specifier, it goes to address pointed to by myCharPointer, in this case it contains 'G'. It will then try to get next character after 'G', which is undefined behaviour. It might give you the correct result every now and then (if the next memory location happens to contain '\0'), but in general you should never do this.
Several comments
Static strings in c are treated as a (char *) to a null terminated
array of characters. Eg. "ab" would essentially be a char * to a block of memory with 97 98 0. (97 is 'a', 98 is 'b', and 0 is the null termination.)
Your code myCharPointer = &charMemoryHolder; followed by printf("%s\n", myCharPointer) is not safe. printf should be passed a null terminated string, and there's no guarantee that memory contain the value 0 immediately follows your character charMemoryHolder.
In C, string literals evaluate to pointers to read-only arrays of chars (except when used to initialize char arrays). This is a special case in the C language and does not generalize to other pointer types. A char * variable may hold the address of either a single char variable or the start address of an array of characters. In this case the array is a string of characters which has been stored in a static region of memory.
charMemoryHolder is a variable that has an address in memory.
"This is a string." is a string constant that is stored in memory and also has an address.
Both of these addresses can be stored in myCharPointer and dereferenced to access the first character.
In the case of printf("%s\n", myCharPointer), the pointer will be dereferenced and the character displayed, then the pointer is incremented. It repeasts this until finds a null (value zero) character and stops.
Hopefully you are now wondering what happens when you are pointing to the single 'G' character, which is not null-terminated like a string constant. The answer is "undefined behavior" and will most likely print random garbage until it finds a zero value in memory, but could print exactly the correct value, hence "undefined behavior". Use %c to print the single character.
I compiled and ran the following code and the results too are depicted below.
#include <stdio.h>
int main(void) {
char *ptr = "I am a string";
printf("\n [%s]\n", ptr);
return 0; }
** [I am a string]**
I want to understand how a string has been assigned inside a pointer char. As per my understanding the pointer can hold only an address, not a complete string. Here it is holding one whole sentence. I do not understand how being a pointer allows it to behave such way.
If I change the following line of code in the above example,
printf("\n [%c]\n", ptr);
It does not print one single charactor and stop. What it does is that it prints out an unrecognised character which is completely out of ASCII table. I do not understand how that too is happening. I would appreciate some light shred on this issue.
As per my understanding the pointer can hold only an address, not a
complete string
char *ptr = "I am a string";
Is a string literal the string is stored in the read-only location and the address in which the data is stored is returned to the pointer ptr.
It does not print one single charactor and stop. What it does is that
it prints out an unrecognised character which is completely out of
ASCII table. I do not understand how that too is happening
ptr is a pointer and using wrong format specifier in printf() lead to undefined behvaior.
With %s if you provide the address where the string is stored the printf() prints out the whole string
A pointer does not hold a string, it points to a string. (Easy to remember, it's called a "pointer", not a "holder"). To see the difference, write your postal address on a yellow sticky note. Does this piece of paper hold you? No, it points to you. It holds your address.
Pointers are computer equivalent of postal addresses (in fact things that pointers do hold are called addresses). They don't hold "real things" like strings, they tell where "real things" live.
Back to our string, the pointer actually points to the first character of the string, not to the string as a whole, but that's not a problem because we know the rest of the string lives right next to the first chsracter.
Now "%s" as a format specifier wants a pointer to the first character of a string, so you can correctly pass p to printf. OTOH %c wants a character, not a pointer, so passing p in this case leads to undefined behavior.
So how come we can say things like char* p = "abc"? String literals are arrays of characters, and an array in most cases decays into pointer to its first element. Array-to-pointer decay is another confusing property of C but fortunately there is a lot of information available on it out there. OTOH `char p = "abc" is not valid, because a character is not an array (a house is not a street).
Also
char *ptr = "I am a string";
automatically inserts a null character at the end. So when you do a printf with %s format specifier, it starts from the address of the string literal and prints upto the null character and stops.
I have learned that char *p means "a pointer to char type"
and also I think I've also learned that char means to read
that amount of memory once that pointer reaches its' destination.
so conclusively, in
char *p = "hello World";
the p contains the strings' address and
the p is pointing right at it
Qusetions.
if the p points to the string, shouldn't it be reading only the 'h'???
since it only reads the sizeof a char?
why does `printf("%s", p) print the whole string???
I also learned in Rithcie's book that pointer variables don't possess a data type.
is that true???
So your string "hello world" occupies some memory.
[h][e][l][l][o][ ][w][o][r][l][d][\0]
[0][1][2][3][4][5][6][7][8][9][A][B ]
The pointer p does, in fact, only point to the first byte. In this case, byte 0. But if you use it in the context of
printf("%s", p)
Then printf knows to print until it gets the null character \0, which is why it will print the entire string and not just 'h'.
As for the second question, pointers do posses a data type. If you were to say it outloud, the name would probably be something like type "pointer to a character" in the case of p, or "pointer to an integer" for int *i.
Pointer variables don't hold a data type, they hold an address. But you use a data type so you know how many bytes you'll advance on each step, when reading from memory using that pointer.
When you call printf, the %s in the expression is telling the function to start reading at the address indicated by *p (which does hold the byte value for 'h', as you said), and stop reading when it reaches a terminating character. That's a character that has no visual representation (you refer to it as \0 in code). It tells the program where a string ends.
Here *p is a pointer to some location in memory, that it assumes to be 1 byte (or char). So it points to the 'h' letter. So p[0] or *(p+0) will give you p. But, your string ends with invisible \0 character, so when you use printf function it outputs all symbols, starting from the one, where *p points to and till `\0'.
And pointer is just a variable, that is able to hold some address (4, 8 or more bytes).
For question:
I also learned in Rithcie's book that pointer variables don't possess a data type. is that true???
Simply put, YES.
Data types in C are used to define a variable before its use. The definition of a variable will assign storage for the variable and define the type of data that will be held in the location.
C has the following basic built-in datatypes.int,float,double,char.
Quoting from C Data types
Pointer is derived data type, each data type can have a pointer associated with. Pointers don't have a keyword, but are marked by a preceding * in the variable and function declaration/definition. Most compilers supplies the predefined constant NULL, which is equivalent to 0.
if the p points to the string, shouldn't it be reading only the 'h'???
since it only reads the sizeof a char? why does printf("%s", *p) print
the whole string???
change your printf("%s", *p) to printf("%c", *p) you see what you want. both calls the printf in different ways on the basis of format specifier i.e string(%s) or char(%c).
to print the string use printf("%s", p);
to print the char use printf("%c", *p);
Second Ans. : Pointers possesses a data type. that's why you used char *p .
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