Explanation regarding character pointer for string - c

Hi I'm new to programming.
In the following code str is a pointer to a character, so str should contain the address of the character 'h'. Therefore %p should be used to print that address. But I don't understand how %s is used for printing a pointer parameter.
#include<stdio.h>
int main (){
char s[] = "hello";
char *str = s;
int a[] = {1, 2, 3, 4, 5};
int *b = a;
printf("%s\n", str); // I don't understand how this works ?
printf("%c\n", *str); // This statement makes sense
printf("%c\n", *(str + 1)); // This statement also makes sense.
printf("%p\n",str); // This prints the address of the pointer str. This too makes sense.
printf("%d\n",*b); // makes sense, is the same as the second print.
// printf("%d",b); // I don't understand why str pointer works but this gives a compile error
return 0;
}

char s[] = "hello";
Declares an array of zero-terminated characters called s. Its the same as writing
char s[6] = { 'h', 'e', 'l', 'l', 'o', '\0' };
As you can see, the quotation marks are a shorthand.
char *str = s;
This declares str to be a pointer to a character. It then makes str point to the first character in s. In other words, str contains the address of the first character in s.
int a[] = {1, 2, 3, 4, 5};
Declares an array of integers. It initializes them to the values 1-5, inclusive.
int *b = a;
Declares b to be a pointer to an int. It then makes b point to the first int in a.
printf("%s\n", str);
The %s specifier accepts the address of the first character in the string. printf then walks from that address, printing the characters it sees, until it sees the \0 character at the end.
printf("%c\n", *str);
This prints the first character in str. Since str is pointing to a character (the first character in the string), then *str should obtain the character being pointed at (the first character in the string).
printf("%c\n", *(str + 1));
This prints the second character in str. This is the long way of writing str[1]. The logic behind this is pointer arithmetic. If str is the address of a character, then str + 1 is the address of the next character in the array. Since (str + 1) is an address, it may be dereferenced. Thus, the * obtains the character 1 character past the first character of the array.
printf("%p\n",str);
The %p specifier expects a pointer, just like %s would, but it does something else. Instead of printing the contents of a string, it simply prints the address the pointer is containing, in hex.
printf("%d\n",*b);
This prints the first int in the array pointed to by b. This is equivalent to writing b[0].
printf("%d",b);
b is an int *, not an int, which is what %d expects. If you were trying to print the address of the first element of the array, the specifier would be %p, not %d. Also, this line should not generate a compiler error. Instead, it should have been a runtime undefined behavior, since the compiler does not know what a printf format string is.

Related

Printf function prints another string too

Hi i am fairly new in C language and i was trying to understand the strings. As i know, strings are just an array of characters and there shouldn't be a difference between char a[]= "car" and char a[] = {'c','a','r'}.
When i try to print the string as:
char a[] = "car";
char b[] = "testing the cars";
printf("%s", a);
the output is just car and there's no problem.But when i try to print it as:
char a[] = {'c','a','r'};
char b[] = "testing the cars";
printf("%s", a);
it's printing the b too. Can you explain what's the reason of it?
The %s specifier of printf() expects a char* pointer to a null-terminated string.
In the first case, a and b are both null-terminated. Initializing a char[] array of unspecified size with a string literal will include the literal's null-terminator '\0' character at the end. Thus:
char a[] = "car";
is equivalent to:
char a[] = {'c', 'a', 'r', '\0'};
In the second case, a is NOT null-terminated, leading to undefined behavior, as printf("%s", a) will read past the end of a into surrounding memory until it eventually finds a '\0' character. It just happens that, in your case, b exists in that memory following a, but that is not guaranteed, the compiler can put b wherever it wants.

Print an array of char, but the ending is not expected

I don't understand why there are random char after abc. what is the reason? How to print out only abc? Thanks!
#include <stdio.h>
int main()
{
char arr[3];
char(*ptr)[3]; // declare a pointer to an array
arr[0] = 'a';
arr[1] = 'b';
arr[2] = 'c';
ptr = &arr;
printf("%s\n", arr);
//printf("%s\n", ptr);
return 0;
}
The string need to be terminated with a \0. Make sure to allocate enough space to store the terminator as well.
#include <stdio.h>
int main()
{
char arr[4];
char(*ptr)[4]; // declare a pointer to an array
arr[0] = 'a';
arr[1] = 'b';
arr[2] = 'c';
arr[3] = '\0'; // <-- terminator
ptr = &arr;
printf("%s\n", arr);
//printf("%s\n", ptr);
return 0;
}
Note that using char arr[4] you will have random content in your array. If instead you would use
char arr[4] = "abc";
This will lead to
char arr[4] = {'a', 'b', 'c', 0};
See how the other places are filled with a 0 so you don't have to set it yourself.
The reason of the random characters is that you are trying to output the array as a string using the conversion specifier %s.
But the character array arr does not contain a string (a sequence of characters terminated by the zero character '\0').
So to output it using the function printf you can do for example the following way:
printf( "%*.*s\n", 3, 3, arr );
From the C Standard (7.21.6.1 The fprintf function)
4 Each conversion specification is introduced by the character %.
After the %, the following appear in sequence:
— An optional precision that gives ... the maximum number of bytes to
be written for s conversions.
String must be terminated with 0 .
So you have to declare 4 element array.
char arr[4] = "abc";
The strlen function wich all printf function family uses, reads string till 0 value is found.
So strlen returned length of memory block that starts at your array beginning and ends with first zero.
This can cause undefined behavior.

C char pointer get a specific character

probably a dumb question but how do you access a specific character in a char pointer?
I've tried following...
char *pointer = "Hello";
printf("%s", pointer); // prints "Hello"
printf("%s", &pointer[0]); // also prints "Hello"
But what I want is printf(???) => "H". A single character. Or the "e". How is that possible?
pointer is a pointer to char, also called a char *.
After char *pointer = "Hello";, pointer points to the “H”.
When printf is given %s, it takes a char * and prints all the characters it finds starting at that location, until a null character is seen.
To tell printf to print a single character, pass it the actual character value (not a pointer) and use %c:
printf("%c", *pointer);
or:
printf("%c", pointer[0]);
or, for the “e” instead of the “H”:
printf("%c", pointer[1]);
char* pointer = "Hello";
Creates a pointer and assigns it to the base address of "Hello".
pointer and &pointer[0] are the same thing.
pointer[n] takes the address of "Hello" and offsets it by the number 'n', be sure not to index of the end of the address or you will read rubbish.
So:
pointer[0] = 'H'
pointer[1] = 'e'
pointer[2] = 'l'
pointer[3] = 'l'
pointer[4] = 'o'
pointer[5] = 0
You want to access the char of char* simply use [] operator, just like arrays.
char *pointer = "Hello";
printf("%s", pointer); // ok
printf("%s", &pointer[0]); // wrong way of accessing specific element (it is same as the base address.., thus %s prints the whole thing)
Instead you're accessing the address of the first element of char* or string literal.. why!
printf("%c", pointer[0]); // use this one
Just like arrays, access the required element.
However, to get it better, notice here:
#include <stdio.h>
int main() {
char *pointer = "Hello";
printf("%s\n\n", pointer); // ok
printf("%c", pointer[0]);
printf("%p == %p\n", (void *)&pointer[0],(void *)pointer);
// cast to void * to avoid undefined behavior
// pointed out by #ex nihilo
printf("%p", pointer+1);
return 0;
}
Output:
Hello
H0x55da21577004 == 0x55da21577004
0x55da21577005
as you can see, the pointer holds the address of the first element which is: &pointer[0] thus you get the same output.

Weird beahaviour of string pointers

#include <stdio.h>
int main()
{
char*m ;
m="srm";
printf("%d",*m);
return 0;
}
The output is 115. Can someone explain why it gives 115 as output?
*m is the same as m[0], i.e. the first element of the array pointed to by m which is the character 's'.
By using the %d format specifier, you're printing the given argument as an integer. The ASCII value of 's' is 115, which is why you get that value.
If you want to print the string, use the %s format specifier (which expects a char * argument) instead and pass the pointer m.
printf("%s\n", m);
You have a few problems here,
the first one is that you're trying to add three bytes to a char, a char is one byte.
the second problem is that char *m is a pointer to an address and is not a modifiable lvalue. The only time you should use pointers is when you are trying to point to data
example:
char byte = "A"; //WRONG
char byte = 0x61; //OK
char byte = 'A'; //OK
//notice that when setting char byte = "A" you will recieve an error,
//the double quotations is for character arrays where as single quotes,
// are used to identify a char
enter code here
char str[] = "ABCDEF";
char *m = str;
printf("%02x", *m); //you are pointing to str[0]
printf("%02x", *m[1]); //you are pointing to str[1]
printf("%02x", *m[1]); //you are pointing to str[1]
printf("%02x", *(m + 1)); //you are still pointing to str[1]
//m is a pointer to the address in memory calling it like
// *m[1] or *(m + 1) is saying address + one byte
//these examples are the same as calling (more or less)
printf("%02x", str[0]); or
printf("%02x", str[1]);
Pointers and arrays act similarly .Array names are also pointers pointing to the first element of the array.
You have stored "srm" as a character array with m pointing to the first element.
"%d" will give you the ASCII value of the item being pointed by the pointer.
ASCII value of "s" is 115.
if you increment your pointer (m++) then print it's ascii value , output will be ascii value of "r" - 114.
#include <stdio.h>
int main()
{
char *m ;
m="srm";
m++; //pointing to the 2nd element of the array
printf("%d",*m); //output = 114
return 0;
}

Character Pointer in C

Experts I've some doubts in this programme.
#include<stdio.h>
void main() {
char str1[] = "Hello";
char * p = "Hello", * s, * q;
p = "Bye";
printf("%s", p);
s = p;
printf("%s", s);
q = str1;
printf("\n%s", q);
}
Here p,s and q are character pointers. As we know pointers store the address of a variable and suppose if we used p=str1 then it should store the base address of array str1. Then here how p is acting like an array itself which is storing a string? I've not really understood what's character pointer. Is it not really a pointer? Because we are not using & and neither are we getting the address as an output. Please help. Thank you.
You are very much correct here:
As we know pointers store the address of a variable and suppose if we used p=str1 then it should store the base address of array str1.
Your first question:
Then here how p is acting like an array itself which is storing a string?
You can say p is acting like an array but in reality, it is just a pointer which is pointing to the base address of string str1 which is a null-terminated string.
Your second question:
I've not really understood what's character pointer. Is it not really a pointer?
A character pointer is again a pointer like the pointers to other types in C.
But there is catch here. when you do:
char a = 'A';
char *ptr = &a; // ptr points to character 'A'
Here ptr is pointer to a character.
But when you do:
char *str = "Hello";
char *ptr = str; // ptr points to first character of string str
Here ptr is pointer to a string
A point to note here is - pointer to a character is different from the pointer to a string.
In C, strings are defined as an array of characters. The difference between a character array and a string is the string is terminated with a special character ‘\0’.
So,
char str[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
char str[] = "Hello";
Both are same but there is a difference in the way they have been initialized.
Wherever in the program, we use str, this will give the base address of string "Hello". Similarly, string literals are also an array of characters with an exception that they can not be changed because the compiler may put them read-only data section.
So, if we have char *ptr = str then
ptr[0] == str[0]
ptr[1] == str[1]
.....
..... and so on
Because,
ptr[0] is *(ptr + 0) which is character at 0th location of string str and can also be written as *ptr and
ptr[1] is *(ptr + 1) which is a character at the 1st location of string str.
When we increment a pointer, it gets incremented in steps of the object size that the pointer points to. Here, ptr is pointer to char so, ptr+1 will give address of next character and *(ptr + 1) give the character at that location. That's why to the user it looks like its acting like an array.
Your third question:
Because we are not using & and neither are we getting the address as an output.
If I am getting it correctly you want to print the base address of the string, the pointer is pointing to.
In order to get the base address of string a pointer is pointing to you need to use %p. Like this:
#include<stdio.h>
int main() {
char str1[] = "Hello";
char * ptr = str1;
printf ("%s\n", str1);
printf ("%s\n", ptr);
printf ("%p\n", ptr);
printf ("%p\n", str1);
printf ("%p\n", &str1[0]);
return 0;
}
Output on my system:
Hello
Hello
0x7fff5e997b46
0x7fff5e997b46
0x7fff5e997b46
Here you can see - ptr, str and &str[0] giving same address.

Resources