Why is this "%s" not allowed with value inside of pointer? - c

I know that pointer and exactly same to each other. The program below shows an error if i use %c and then loop through all the values of the string then i see no error but with %s i get an error.
Also if i use array i place of pointer and use arr[] with i see an error. Like arr[] = "Hello" and then use printf("%s", arr[]); .......i see an error too. What is wrong here?
#include <stdio.h>
#include <stdlib.h>
main()
{
char *ptr = "Hello";
printf("%d\n", ptr);
printf("%s\n", *ptr);
return 0;
}

Both calls of printf result in undefined behavior:
Passing a pointer for a parameter printed with %d is not allowed
Passing a non-pointer (in this case, that's a char) to %s is undefined behavior as well. It is likely to cause a crash because a non-pointer gets dereferenced.
In order to print a value of a pointer, cast the pointer to void*, and use %p format specifier:
printf("%p\n", ptr);
In order to print a string, pass ptr, not *ptr, to a parameter with %s format specifier:
printf("%s\n", ptr);

Related

%d specifier for an uninitialized character array

#include <stdio.h>
int main()
{
char a[8];
printf("%d\n",a) ;
return 0;
}
For the above code the output was this :- 2686744
What is the reason behind this output?
I found that the output doesn't depend on the content of the array, but on the size of the array.I just want the explanation.
char a[8];
printf("%d\n",a);
This code has undefined behavior.
The array expression a is implicitly converted to a char* value, equivalent to &a[0]. That value is then passed to printf -- but since the %d format requires an int argument, the behavior is undefined.
If int and char* happen to have the same size, and if they're passed as function arguments using the same mechanism, then it will likely print a decimal representation of the address of (the initial element of) the array.
But don't do that. If you want to print the address:
printf("%p\n", (void*)a);
You are printing the address of the array as an integer.
If you compile with -Wall to enable warnings your compiler should complain about that.

Will these statements all return an address?

Says you had a character array in C. Like this:
char array[];
Now, which of the statements below will print out the address. I know that 1) and 2) will, but does 3) also print out the address?
1) printf("Arrays adress is %x\n", array);
2) printf("Arrays adress is %x\n", &array[0]);
3) printf("Arrays adress is %x\n", &array);
None of them. All of them will print garbage value, i.e, your program's behavior is undefined
EDIT: As OP has changed his question now the answer is:
All of them will print address by using %p specifier and casting each of array, &array and &array[0] with void *.
char array[5]; //let's assume an array of 5 chars
printf("Arrays adress is %p\n", (void *)array);
printf("Arrays adress is %p\n", (void *)&array[0]);
printf("Arrays adress is %p\n", (void *)&array);
Assuming array shall read text and the declaration would be char text[] ="...something ..." and you'd use %p instead of %x and casted the values passed to void*: Yes, some addresses will be printed.
Not really, if you want to print out the memory address (a pointer value), I'd use the correct format:
printf("The address is: %p\n", &array);
For example, %x will just print the hex-value for whatever int is passed as the corresponding argument. Once you've done that, all three statements print out exactly the same:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char foo[] = "Some string";
printf("%p\n%p\n%p\n", (void *)foo, (void *)&foo, (void *)&foo[0]);
return 0;
}
Prints out the same thing, three times.
As H2CO3 kindly pointed out, you will need to cast to a void pointer for printf, though
Usually, an array evaluates to the address of its first element. That's why array, &array and &array[0] all churn out the same value. You can read all about it here

Query in C Pointers

I'm trying to print a pointer of char type in c , i'm able to see the values and it's memory address as below
char *ptr = "I am a string";
printf("\n value [%s]\n",ptr);
printf("\n address [%d]\n",&ptr);
But when i print directly the pointer as below, it's showing error as Segmentation fault
char *ptr = "I am a string";
printf("\n value [%s]\n",*ptr);
Please tell me what's going wrong here
Note: if i change the format in printf to [%d] or [%i] it's printing.
*ptr is a char, not a char pointer, and %s expects a char pointer (to a C-string). When treating the char as a pointer, printf tries to access an invalid memory address, and you get a segmentation fault.
The %s format specifier expects a pointer to a 0-terminated char array. If the corresponding argument to printf is *ptr, a char, that is a) undefined behaviour and b) probably leads to the value of the character (promoted to an int) and possibly some arbitrary adjacent bytes, being interpreted as a pointer. Following that presumed pointer is likely to access memory not allocated to your program.
When you pass in the format "%s" into printf, the function expects a pointer to an array of chars.

Can a pointer to a string be used in a printf?

I am thinking of something like:
#include <stdio.h>
#include <conio.h>
#include <stdlib.h>
int main(void) {
//test pointer to string
char s[50];
char *ptr=s;
printf("\nEnter string (s): ");
fgets(s, 50, stdin);
printf("S: %s\nPTR: %s\n", s, *ptr);
system("PAUSE");
return 0;
}
Or should I use a for loop with *(s+i) and the format specifier %c?
Is that the only possible way to print a string through a pointer and a simple printf?
Update: The printf operates with the adress of the first element of the array so when I use *ptr I actually operate with the first element and not it's adress. Thanks.
The "%s" format specifier for printf always expects a char* argument.
Given:
char s[] = "hello";
char *p = "world";
printf("%s, %s\n", s, p);
it looks like you're passing an array for the first %s and a pointer for the second, but in fact you're (correctly) passing pointers for both.
In C, any expression of array type is implicitly converted to a pointer to the array's first element unless it's in one of the following three contexts:
It's an argument to the unary "&" (address-of) operator
It's an argument to the unary "sizeof" operator
It's a string literal in an initializer used to initialize an array object.
(I think C++ has one or two other exceptions.)
The implementation of printf() sees the "%s", assumes that the corresponding argument is a pointer to char, and uses that pointer to traverse the string and print it.
Section 6 of the comp.lang.c FAQ has an excellent discussion of this.
printf("%s\n", ptr);
Is this what you want?
By the way, from printf(3), here's the documentation for the s conversion specifier (i.e %s):
If no l modifier is present: The const char * argument is expected to
be a pointer to an array of character type (pointer to a string).
Characters from the array are written up to (but not including) a
terminating null byte ('\0'); if a precision is specified, no more
than the number specified are written. If a precision is given, no
null byte need be present; if the precision is not specified, or is
greater than the size of the array, the array must contain a
terminating null byte.
you should do "printf("S: %s\nPTR: %s\n", s, ptr);
" instead of printf("S: %s\nPTR: %s\n", s, *ptr);
difference between ptr and *ptr is: ptr gives you the address in the memory of the variable you are pointing to and *ptr gives rather the value of the pointed variable In this case is *ptr = ptr[0]
this code will show what i mean:
printf("\tS: %s\n\tPTR: %s\n\tAddress of the pointed Value: %x\n\tValue of the whole String: %s\n\tValue of the first character of the String: %c\n", s, ptr,ptr,ptr,*ptr);
In my experience you should get segmentation fault when you try to use %s directive with *p.

Question about char pointers

I am confused with this program.
#include <stdio.h>
int main(void)
{
char* ptr="MET ADSD";
*ptr++;
printf("%c\n", ptr);
ptr++;
printf("%c\n", ptr);
}
Here's the output.
ET ADSD
T ADSD
My question is how does the pointer display the rest of the characters?
You are passing a wrong combination of parameters to printf: the %c format specification requires a char parameter, not a char*. So the result is undefined - in your case printf seems to print the whole char array, but this is just by pure chance. Use either
printf("%c\n", *ptr);
or
printf("%s\n", ptr);
You are actually trying to print as a char %c a pointer value char*. This is false. But then, I really don't understand why it prints all the chars. Are you sure you didn't use %s instead of %c?
The * operator as lower precedence over the ++ operator. Thus in your example the both lines
*ptr++;
ptr++;
have the same effect.
And you are using the wrong types in your printf statement.
Change
printf("%c\n", ptr);
to
printf("%s\n", ptr);
or
printf("%c\n", *ptr);
depending on what you want to output.
Btw, turning on compiler warnings helps in that case. E.g. the GCC prints:
d.c: In function ‘main’:
d.c:7: warning: value computed is not used
d.c:8: warning: format ‘%c’ expects type ‘int’, but argument 2 has type ‘char *’
d.c:11: warning: format ‘%c’ expects type ‘int’, but argument 2 has type ‘char *’
d.c:12: warning: control reaches end of non-void function
In C a string is a array of chars, and an array is simply a pointer to the first location of memory of the array.
So defining
char* ptr="MET ADSD";
you are declaring and initializing an array of chars, a string, by using a pointer to char,
The next trick comes if you consider this two factors:
pointers arithmetic in that using the operator ++ on a pointer increments its value, the memory address it is pointing to
char size which is almost everywhere 1 byte
So you are scaling the array along of two positions, and you print that by using %s and passing the pointer to it
EDIT I guess you put %c mistakenly in the example
If you are expecting 'E' as first and 'T' as second output. Give it like
#include <stdio.h>
int main(void)
{
char* ptr="MET ADSD";
*ptr++;
printf("%c\n", *ptr);
ptr++;
printf("%c\n", *ptr);
}
printf( ..., ptr) is passing the pointer, not the char it points to.
The correct version of the program would be:
#include <stdio.h>
int main(int argc, char* argv[])
{
const char* ptr = "MET ADSD";
ptr++;
printf("%c\n", *ptr);
ptr++;
printf("%c\n", *ptr);
return 0;
}
which will print
E
T
The output you are seeing makes no sense unless you are using %s. - %c is going to convert the value of ptr into an integer, truncate the int to 8bits (the width of a char), and print that character to the output. Not a string of characters.

Resources