Hi I have a simple question
char *a="abc";
printf("%s\n",a);
int *b;
b=1;
printf("%d\n",b);
Why the first one works but the second one doesnot work?
I think the first one should be
char *a="abc";
printf("%s\n",*a);
I think a stores the address of "abc". So why it shows abc when i print a? I think I should print *a to get the value of it.
Thanks
Ying
Why the first one works but the second one doesnot work?
Because in the first, you're not asking it to print a character, you're asking it to print a null-terminated array of characters as a string.
The confusion here is that you're thinking of strings as a "native type" in the same way as integers and characters. C doesn't work that way; a string is just a pointer to a bunch of characters ending with a null byte.
If you really want to think of strings as a native type (keeping in mind that they really aren't), think of it this way: the type of a string is char *, not char. So, printf("%s\n", a); works because you're passing a char * to match with a format specifier indicating char *. To get the equivalent problems as with the second example, you'd need to pass a pointer to a string—that is, a char **.
Alternatively, the equivalent of %d is not %s, but %c, which prints a single character. To use it, you do have to pass it a character. printf("%c\n", a) will have the same problem as printf("%d\n", b).
From your comment:
I think a stores the address of "abc". So why it shows abc when i print a? I think I should print *a to get the value of it.
This is where the loose thinking of strings as native objects falls down.
When you write this:
char *a = "abc";
What happens is that the compiler stores a array of four characters—'a', 'b', 'c', and '\0'—somewhere, and a points at the first one, the a. As long as you remember that "abc" is really an array of four separate characters, it makes sense to think of a as a pointer to that thing (at least if you understand how arrays and pointer arithmetic work in C). But if you forget that, if you think a is pointing at a single address that holds a single object "abc", it will confuse you.
Quoting from the GNU printf man page (because the C standard isn't linkable):
d, i
The int argument is converted to signed decimal notation …
c
… the int argument is converted to an unsigned char, and the resulting character is written…
s
… 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') …
One last thing:
You may be wondering how printf("%s", a) or strchr(a, 'b') or any other function can print or search the string when there is no such value as "the string".
They're using a convention: they take a pointer to a character, and print or search every character from there up to the first null. For example, you could write a print_string function like this:
void print_string(char *string) {
while (*string) {
printf("%c", *string);
++string;
}
}
Or:
void print_string(char *string) {
for (int i=0; string[i]; ++i) {
printf("%c", string[i]);
}
}
Either way, you're assuming the char * is a pointer to the start of an array of characters, instead of just to a single character, and printing each character in the array until you hit a null character. That's the "null-terminated string" convention that's baked into functions like printf, strstr, etc. throughout the standard library.
Strings aren't really "first-class citizens" in C. In reality, they're just implemented as null-terminated arrays of characters, with some syntactic sugar thrown in to make programmers' lives easier. That means when passing strings around, you'll mostly be doing it via char * variables - that is, pointers to null-terminated arrays of char.
This practice holds for calling printf, too. The %s format is matched with a char * parameter to print the string - just as you've seen. You could use *a, but you'd want to match that with a %c or an integer format to print just the single character pointed to.
Your second example is wrong for a couple of reasons. First, it's not legal to make the assignment b = 1 without an explicit cast in C - you'd need b = (int *)1. Second, you're trying to print out a pointer, but you're using %d as a format string. That's wrong too - you should use %p like this: printf("%p\n", (void *)b);.
What it really looks like you're trying to do in the second example is:
int b = 1;
int *p = &b;
printf("%d\n", *p);
That is, make a pointer to an integer, then dereference it and print it out.
Editorial note: You should get a good beginner C book (search around here and I'm sure you'll find suggestions) and work through it.
Related
In c programming when we print a string. We are not using * . But when print a number using printf we are using *. So how it is understanding, i am printing a string or int. Is understanding using %s operator?
Attaching an example code
#include<stdio.h>
int main(int argc,char* argv){
char data[]="This is an example of pointer";
char *pointerstringdata =data;
printf("print the string data is >> %s\n",pointerstringdata); /* Here we are not using * why? case -1*/
int numberdata =100;
int *pointerintdata=&numberdata;
printf("print the int data is >> %d\n",*pointerintdata); /* Here we are using * why? case -2*/
return 0;
}
when we print a string. We are not using * . But when print a number using printf we are using *
Because the d conversion specifier expects an int, whereas the s conversion specifier expects a pointer (to a char and with this to the 1st element of a 0-terminated char array, which in fact is what C uses to mimik what commonly is called a "string").
The C language has no provision for treating a string as a value. You cannot pass a string to function. The pointer pointerstringdata is just a pointer to a char, so *pointerstringdata is one char, not a string. Passing *pointerstringdata will pass only one character, not a string.
To print strings, when %s is used, printf expects the argument to be a pointer. It uses this pointer to read from memory, and it reads and prints characters until it finds null characters.
In contrast, C does support treating numbers as values, so they can be passed to functions directly.
The %s format specifier is expecting a pointer.
If you pass *pointerstringdata the function will receive the first character in the array, which the function will try to dereference, and probably cause a crash.
in
char data[]="This is an example of pointer";
char *pointerstringdata =data;
printf("print the string data is >> %s\n",pointerstringdata); /* Here we are not using * why? case -1*/
if you want to print all the string you have to give its address, no *
if you want to print its first character you do `printf("%c", *pointerstringdata);
in
int numberdata =100;
int *pointerintdata=&numberdata;
printf("print the int data is >> %d\n",*pointerintdata); /* Here we are using * why? case -2*/
you do not want to print the address memorized in pointerintdata but the value same in that address, so you have to dereference
there is no difference with a string ... except that you want to write all the string
a pointer is a pointer, whatever it is a pointer to a char or a pointer to an int
Disclaimer: This is an explanation about how it appear to the developer, this is not how it is after compiling the code (especially because the optimizer might change it all).
C is a very low level language. You need to understand that a variable always contains a value of a few bytes.
C is also one of the languages that made it very convenient to access larger structures.
The content of the variable can be:
A value (e.g: as you mentioned a number)
A address in the RAM
A structure that uses more consecutive ram (and C makes it nice to use it as if it was more than that)
stuct (fixed length)
array with fixed length
There is no real concept of having a dynamic length variable as a value, therefor strings as well as arrays of dynamic length only have the address in the variable.
As stings are variable length, the convention in C is:
Have an address in the variable
Read the real data byte by byte starting at that address
Read data until the byte is 0 (NULL)
That is called a null-terminated string.
This way you can pass data of variable length to printf, and printf will find out the length by looking for the first byte that is 0.
Converting variables containing address to those containing value works like this:
var_with_value = *var_with_address
var_with_address = &var_with_value
"var_with_address" is called a pointer.
In conclusion: You need to pass strings as address not as value, and numbers as value not as address, and that is the difference why you have to use *
Because pointers hold reference to the object. * dereference this object. So if the pointer holds the reference to the char object when we dereference it we get this object. So dereference char pointer is just the single char not the address of the first char in the string.
I was trying to learn pointers and I wrote the following code to print the value of the pointer:
#include <stdio.h>
int main(void) {
char *p = "abc";
printf("%c",*p);
return 0;
}
The output is:
a
however, if I change the above code to:
#include <stdio.h>
int main(void) {
char *p = "abc";
printf(p);
return 0;
}
I get the output:
abc
I don't understand the following 2 things:
why did printf not require a format specifier in the second case? Is printf(pointer_name) enough to print the value of the pointer?
as per my understanding (which is very little), *p points to a contiguous block of memory that contains abc. I expected both outputs to be the same, i.e.
abc
are the different outputs because of the different ways of printing?
Edit 1
Additionally, the following code produces a runtime error. Why so?
#include <stdio.h>
int main(void) {
char *p = "abc";
printf(*p);
return 0;
}
For your first question, the printf function (and family) takes a string as first argument (i.e. a const char *). That string could contain format codes that the printf function will replace with the corresponding argument. The rest of the text is printed as-is, verbatim. And that's what is happening when you pass p as the first argument.
Do note that using printf this way is highly unrecommended, especially if the string is contains input from a user. If the user adds formatting codes in the string, and you don't provide the correct arguments then you will have undefined behavior. It could even lead to security holes.
For your second question, the variable p points to some memory. The expression *p dereferences the pointer to give you a single character, namely the one that p is actually pointing to, which is p[0].
Think of p like this:
+---+ +-----+-----+-----+------+
| p | ---> | 'a' | 'b' | 'c' | '\0' |
+---+ +-----+-----+-----+------+
The variable p doesn't really point to a "string", it only points to some single location in memory, namely the first character in the string "abc". It's the functions using p that treat that memory as a sequence of characters.
Furthermore, constant string literals are actually stored as (read-only) arrays of the number of character in the string plus one for the string terminator.
Also, to help you understand why *p is the same as p[0] you need to know that for any pointer or array p and valid index i, the expressions p[i] is equal to *(p + i). To get the first character, you have index 0, which means you have p[0] which then should be equal to *(p + 0). Adding zero to anything is a no-op, so *(p + 0) is the same as *(p) which is the same as *p. Therefore p[0] is equal to *p.
Regarding your edit (where you do printf(*p)), since *p returns the value of the first "element" pointed to by p (i.e. p[0]) you are passing a single character as the pointer to the format string. This will lead the compiler to convert it to a pointer which is pointing to whatever address has the value of that single character (it doesn't convert the character to a pointer to the character). This address is not a very valid address (in the ASCII alphabet 'a' has the value 97 which is the address where the program will look for the string to print) and you will have undefined behavior.
p is the format string.
char *p = "abc";
printf(p);
is the same as
print("abc");
Doing this is very bad practice because you don't know what the variable
will contain, and if it contains format specifiers, calling printf may do very bad things.
The reason why the first case (with "%c") only printed the first character
is that %c means a byte and *p means the (first) value which p is pointing at.
%s would print the entire string.
char *p = "abc";
printf(p); /* If p is untrusted, bad things will happen, otherwise the string p is written. */
printf("%c", *p); /* print the first byte in the string p */
printf("%s", p); /* print the string p */
why did printf not require a format specifier in the second case? Is printf(pointer_name) enough to print the value of the pointer?
With your code you told printf to use your string as the format string. Meaning your code turned equivalent to printf("abc").
as per my understanding (which is very little), *p points to a contiguous block of memory that contains abc. I expected both outputs to be the same
If you use %c you get a character printed, if you use %s you get a whole string. But if you tell printf to use the string as the format string, then it will do that too.
char *p = "abc";
printf(*p);
This code crashes because the contents of p, the character 'a' is not a pointer to a format string, it is not even a pointer. That code should not even compile without warnings.
You are misunderstanding, indeed when you do
char *p = "Hello";
p points to the starting address where literal "Hello" is stored. This is how you declare pointers. However, when afterwards, you do
*p
it means dereference p and obtain object where p points. In our above example this would yield 'H'. This should clarify your second question.
In case of printf just try
printf("Hello");
which is also fine; this answers your first question because it is effectively the same what you did when passed just p to printf.
Finally to your edit, indeed
printf(*p);
above line is not correct since printf expects const char * and by using *p you are passing it a char - or in other words 'H' assuming our example. Read more what dereferencing means.
why did printf not require a format specifier in the second case? Is printf(pointer_name) enough to print the value of the pointer?
"abc" is your format specifier. That's why it's printing "abc". If the string had contained %, then things would have behaved strangely, but they didn't.
printf("abc"); // Perfectly fine!
why did printf not require a format specifier in the second case? Is printf(pointer_name) enough to print the value of the pointer?
%c is the character conversion specifier. It instructs printf to only print the first byte. If you want it to print the string, use...
printf ("%s", p);
The %s seems redundant, but it can be useful for printing control characters or if you use width specifiers.
The best way to understand this really is to try and print the string abc%def using printf.
The %c format specifier expects a char type, and will output a single char value.
The first parameter to printf must be a const char* (a char* can convert implicitly to a const char*) and points to the start of a string of characters. It stops printing when it encounters a \0 in that string. If there is not a \0 present in that string then the behaviour of that function is undefined. Because "abc" doesn't contain any format specifiers, you don't pass any additional arguments to printf in that case.
This might just be the dumbest question, but i havent found any explanation when it comes to char, just when it comes to int, which i can manage.
However, i got this huge problem, i've pointed the adress of my pointer to a char and from that char i want to print out the value.
This is how my code looks:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void function(char *pn) {
char text[64];
char nei;
text[64] = &pn;
printf("%s\n", *text[64]);
}
int main()
{
function("Hello");
getchar();
return(0);
}
I can't figure out whats wrong with it to be honest. Why cant I put a * in front of text[64], since thats how you print the value, correct?
'*' has meaning when applied to a pointer. Applied to a char, I'm not sure what it would do. So, no, putting a * in front of text[64] is not how you print the value.
In your code text is a 64 byte long array of char. Valid indexes into it are 0 to 63.
The expression text[64] refers to memory you don't have access to, or may be a reference into one of your other automatic variables. text[64] is beyond the end of the array.
void function(char *pn) {
char text[64];
char nei;
text[64] = &pn; /* <- this won't work */
strcpy(text, pn); /* <- probably will work, may overflow text if string at pn is too long */
printf("%s\n", *text[64]); /* <- this won't work */
printf("%s\n", pn); /* <- probably will work */
printf("%s\n", text); /* after strcpy above, will likely work */
}
You cannot use both * and [ ], and also text[64] is out of bounds as its said in comment. You can use function strcpy to copy one string to another.
char text[64]; declares text as an array of 64 characters.
printf("%s\n", *text[64]) makes no sense, because:
text[64] points to the character after the end of the array; i.e. text[63] is the last character in the array.
*text[64] attempts to dereference the 64th item in the text array. But each item is not a pointer, but a character.
Perhaps you meant &text[n] where n is a number between 0 and 63, which would be a pointer to a character within the array, and hence a string. In C a string (what %s expects) is a pointer to a character, and the string is that character and all following up until a NUL.
This bit of your question is unclear:
Why cant I put a * in front of text[64],
(answered above)
since thats how you print the value, correct
I have no idea what that bit means. As per the above, %s expects a char *, i.e. a pointer to a character.
If you are trying to copy the contents of the pointer *pn to the character array text then you better use strcpy() function.
strcpy(text,pn);
will let you copy the contents.
You trying to print out the contents of the array. you can't use the * and [] together.
In case of a array
for example
char text[64]
as you have mentioned in your code
printf("%x",text);
will print the start of the allocated memory where the array lies.
when you do text[0] the start of the allocated memory address will be added with 0 and the contents of that memory will given back.
This is how an array work
Now if you are to use a dereferencing operator * then *text will give the 0th element of the array
*(text + 1)
will give you the second element of the array and so and so forth.
one more thing you can't use
printf("%s",text);
as the value that you are passing to the function is not a string but a character array as it does not have '\0' at its end.
Why cant I put a * in front of text[64]
You can! but not the way you have tried to do it.
For example, in a declaration, char *text[64]; would be used to create an array of strings, each 64 bytes in length. And would require allocation of memory using malloc()orcalloc()`, or an initializer such as:
char *text[64]={"this is a string1","this is string2"};
Which creates an array of 2 strings, each with 64 bytes (although only partially used), which could be used like this:
printf("%s\n", text[0]);
printf("%s\n", text[1]);
since that's how you print the value, correct? (referring to:printf("%s\n", *text[64]);)
No.
The argument char *pn refers to a single string.
If you want to copy this argument to the local variable:
First, change the line:
text[64] = &pn;
to
if(!pn) return; //test and leave if pn is null pointer
strcpy(text, pn);
Then just use:
printf("%s\n", text);
to print the line
I'm on an embedded system so do not have access to a most of the standard library. I have a struct which contains char values.
I have a simple print function which simply outputs an unsigned char string to an attached screen. It does not support format specifiers like printf does.
This is the struct:
typedef struct my_options{
char test;
} my_options;
And this is where I'm trying to output the value:
struct my_options options;
print(options.test); //Here I get "implicit conversion of int to ptr"
How do I achieve this?
Create a char array to hold your char and then print it:
char wrapper[2];
wrapper[0] = options.test;
wrapper[1] = '\0';
print(wrapper);
Create a temporary 2-character long string that has the character to print, and then the terminator. Then pass that string to your print() function:
void print_options(const struct my_options *opt)
{
char tmp[] = { opt->test, '\0' };
print(tmp);
}
your member test if of the type char, where the print function expects an argument of the type const char * (assuming the const bit here, but that's what I'd expect, this as an asside). Passing the address of test then would seem like the appropriate solution, but is it?
No, of course it isn't. There is no absolute guarantee that the next byte after test will be '\0' (a string terminating char). What you, then, ought to do is create a wrapper string:
char char_wrapper[2] = {};//initializes according to standard
//but as Lundin pointed out, self-documenting code is important:
char_wrapper[0] = options.test;?
char_wrapper[1] = '\0';//explicit, so it's clear what this code does
print(char_wrapper);
That should work just fine.
You can, of course, write this as a one-liner:
char char_wrapper[2] = {options.test, '\0'};//same as before, only in 1 statement
print(char_wrapper);//print "string"
That should do it, really. You don't even have to explicitly write the terminating char, since the standard specifically states:
An array of character type may be initialized by a character string literal, optionally
enclosed in braces. Successive characters of the character string literal (including the
terminating null character if there is room or if the array is of unknown size) initialize the
elements of the array.
6.7.8 Initialization cf p. 138, semantics, point 14
Be that as it may, I'd still prefer to browse the web, or just set about writing your own minor implementation of printf so you can use format specifiers. Heck, it's one of the first exercises in the K&R book, and there's tons of solutions floating about on the net. check those out, and adapt them to your specific needs.
Or, perhaps define print to accept a size_t argument, to specify how many chars you want to pass to the output stream. and call it like so print(options.test, 1);
print is looking for a char*. You are passing an char which can also be represented as an int. Thus, the function is trying to implicitly convert an int to a pointer as it is telling you.
char ptr[2];
ptr[0] = options.test;
ptr[1] = '\0';
Would wrap the char into a char array, which in C will decay into a pointer when you pass it to a function.
#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.