Strange C String Output - c

I was trying to learn strings in C when I came across this code.
#include <stdio.h>
int main(){
char s[] = "Hello world";
printf("%s" , s);
printf("%s" , &s);
return 0;
}
Both gave Hello World as output. According to my understanding, this output is Ok for First case. How is it working for the second one? Please clarify.

Taking the address of an array is the same as taking the address of it's first element. When the array's name is used, then it also decays to the address of it's first element- so the expressions s and &s yield the same result.

s returns the address of the first item in the array and &s returns the address of the array itself -- these happen to be the same.
In general, if you wish to be more explicit, the expression &s[0] can also be used to return the address of the first item.

s and &s return the same address and hence. This address is the location where "H" from "Hello world" is stored.
Because,
The name of the array decays to the address of the first element in an array &
The address of first element is same as address of the array.

Just for what it may be worth, if you want to get technical, your second version:
printf("%s" , &s);
has undefined behavior, and only works by accident. By explicitly taking the address, you're getting the address of the array (which is fine) but the result has the type "pointer to array of 12 characters", rather than the type "pointer to char", as required for printf's %s conversion. Since the types don't match, the result is undefined behavior.
In reality, however, that's purely a technicality -- the code will work just fine on every implementation of C of which I'm aware.
If you wanted to demonstrate that the difference exists, you could do so pretty easily though. For example:
char string[] = "hello world";
printf("without &: %p, %p\n", (void *)string, (void *)(string+1));
printf("with &: %p, %p\n", (void *)&string, (void *)(&string+1));
In the first case, string decays to a pointer to char, so on the first line, the second pointer will be exactly one greater than the first. On the second line, we're adding one to a pointer to an array of characters, so when we add one, it'll actually add the size of the array. Running this on my machine, I get results like this:
without &: 0038F96C, 0038F96D
with &: 0038F96C, 0038F978

char s[] is similar to char *s that is a charecter pointer that points to the first element of the array (it contains the address of the first element stored).
we can also store strings by storing the address of the first character. during the time of execution, computer start taking characters from that address one by one and make a string until it reaches a null character('\0').
in the above example 's' and '%s' represents the same value (the address of the starting character) hope you will get it.
if you use char s[10] (fixed length array) you will understand everything.

s is equivalent to &s[0] so we are passing address of s[0] not the address of pointer that is pointing to s[0] so it will print Hellow world in second case.
s is name of array not a pointer.

Related

Why does char* of an array point to the entire array instead of the address?

I've seen some similar questions asked on here, but haven't been able to find a concise answer.
In learning pointers, I've come to understand that
in a case of
int test=1; int* p = &test;
printing "p" with printf("%p", p); will give the address of test, while printing *p with printf("%d", *p); will give the actual value of test, which is what ptr p points to.
Now, for doing this with a char, doing
char word[] = "test"; char* ptr = &word[0];
then printing ptr with printf("%s", ptr); gives the output "test", but I expected it to give the address of word[0].
I have figured out that if I do printf("%p", ptr); it does print the address.
So my question is, does this pointer contain both the address and the value of the array test[]? Or does printf just grab what it needs based off of which of %s or %p you use, and in that case, why couldn't you just do printf("%d",test); in my earlier example and get the value of test rather than the address? Is the fact that I'm using %s automatically outputting the entire array since it starts at that address?
%s tells printf to take the pointer it is given and print the first character that is there, then the character after that, then the character after that, and so on until printf finds a null character (a character that has value zero).
So, this not about a pointer pointing to the “entire array.” The pointer just points to one thing. It is about the command given to printf. %p says “print the value of the pointer.” %s says “print the characters at the location pointed to.”
… why couldn't you just do printf("%d",test); in my earlier example and get the value of test rather than the address?
%d is a command to printf to print the value of the int it is passed. You should not pass it a pointer for this because printf is expecting an int. That is just what the command is for.

C Language Pointer Used With Arrays

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 am pretty curious about char pointers

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 .

Character Pointers in C

#include <stdio.h>
int main(void){
char *p = "Hello";
p = "Bye"; //Why is this valid C code? Why no derefencing operator?
int *z;
int x;
*z = x
z* = 2 //Works
z = 2 //Doesn't Work, Why does it work with characters?
char *str[2] = {"Hello","Good Bye"};
print("%s", str[1]); //Prints Good-Bye. WHY no derefrencing operator?
// Why is this valid C code? If I created an array with pointers
// shouldn't the element print the memory address and not the string?
return 0;
}
My Questions are outlined with the comments. In gerneal I'm having trouble understanding character arrays and pointers. Specifically why I can acess them without the derefrencing operator.
In gerneal I'm having trouble understanding character arrays and pointers.
This is very common for beginning C programmers. I had the same confusion back about 1985.
p = "Bye";
Since p is declared to be char*, p is simply a variable that contains a memory address of a char. The assignment above sets the value of p to be the address of the first char of the constant string "Bye", in other words the address of the letter "B".
z = 2
z is declared to be char*, so the only thing you can assign to it is the memory address of a char. You can't assign 2 to z, because 2 isn't the address of a char, it's a constant integer value.
print("%s", str[1]);
In this case, str is defined to be an array of two char* variables. In your print statement, you're printing the second of those, which is the address of the first character in the string "Good Bye".
When you type "Bye", you are actually creating what is called a String Literal. Its a special case, but essentially, when you do
p = "Bye";
What you are doing is assigning the address of this String literal to p(the string itself is stored by the compiler in a implementation dependant way (I think) ). Technically address to the first element of a char array, as Richard J. Ross III explains.
Since it is a special case, it does not work with other types.
By the way, you should likely get a compiler warning for lines like char *p = "Hello";. You should be required to define them as const char *p = "Hello"; since modifying them is undefined as the link explains.
As to the printing code.
print("%s", str[1]);
This doesnt need a dereferencing operation, since internally %s requires a pointer(specifically char *) to be passed, thus the dereferencing is done by printf. You can test this by passing a value when printf is expecting a pointer. You should get a runtime crash when it tries to dereference it.
p = "Bye";
Is an assignment of the address of the literal to the pointer.
The
array[n]
operator works in a similar way as a dereferrence of the pointer "array" increased by n. It is not the same, but it works that way.
Remember that "Hello", "Bye" all are char * not char.
So the line, p="Bye"; means that pointer p is pointing to a const char *i.e."Bye"
But in the next case with int *
*z=2 means that
`int` pointed by `z` is assigned a value of 2
while, z=2 means the pointer z points to the same int, pointed by 2.But, 2 is not a int pointer to point other ints.So, the compiler flags the error
You're confusing something: It does work with characters just as it works with integers et cetera.
What it doesn't work with are strings, because they are character arrays and arrays can only be stored in a variable using the address of their first element.
Later on, you've created an array of character pointers, or an array of strings. That means very simply that the first element of that array is a string, the second is also a string. When it comes to the printing part, you're using the second element of the array. So, unsurprisingly, the second string is printed.
If you look at it this way, you'll see that the syntax is consistent.

Could someone clarify this one confusion I have with C Strings, arrays versus pointers

Just a quick question.
I can write
char string[] = "Hello world";
char *p = string;
printf("%s", p);
And have it print Hello world as output. But how is the pointer working here?
Each point in an array has a separate memory location, right? So the string array being 12 long, would take up 12 memory spaces. I thought a pointer could only point to one memory location, not 12. How is the pointer p achieving this?
With normal arrays and pointers if you want to scale the array you do *p++, as you're going through each memory location and printing its value. Why is that you have to traverse the array 1 by 1 there, but here it simply points to the whole thing?
It just seems to me like with one (int arrays) you're incrementing the pointers as each pointer can only point to one memory location, but with char arrays it can point to all of them somehow.
You're right, a pointer can only point to one memory location. When dealing with arrays, the pointer points at the location of the first element. When you use printf, it basically takes the pointer (pointing to the first element of the string), and prints until reaching the null terminating character, \0.
Here is a good explanation of pointers vs arrays in c:
http://www.cs.bu.edu/teaching/cpp/string/array-vs-ptr/
I thought a pointer could only point to one memory location, not 12. How is the pointer p achieving this?
p is a pointer to char and not a pointer to an array. It points to the first element of the string array.
Now the value of an array is a pointer to its first element so this declaration:
char *p = string;
is actually equivalent to:
char *p = &string[0];
If you increment the pointer:
p++;
p will point to the next element of the array, that is to string[1].
The pointer to an array is really a pointer to the first address... And printf will scan from that address on untill it finds the null char... %c and %s differ on that behavior
You use %s so it prints till it '\0'.
Why is that you have to traverse the array 1 by 1 there, but here it
simply points to the whole thing?
Here, you use a pointer to a char, and you wanted to print the string. so it's fine. Suppose, if you are using an pointer to an int or other types, this will not quite work. So pointer arithmetic like p++ is used.

Resources