Pointers in C, I'm so confused - arrays

Currently I'm following this pdf on C pointers. The code below was meant as a demonstration but confused me beyond belief. Firstly, my understanding of pointers to arrays is that they are initialized in heap memory with the memory address of the first element in the array hence why: ptr = &my_array[0]; /* and */ ptr = my_array; are the same thing. My first issue with this code is that he created a pointer that doesn't point to a memory address. I thought pointer initialization would usually involve the & and the value of pA would be the memory address of the first element of the array, but when he prints the pointer to the screen THE WHOLE STRING PRINTS OUT. Why? On top of that, when I put another * on pA it prints the first character of the array. Why? On top of that, he uses ++ on *pA and *pB which makes no sense to me because the output shows that *pA is the first character in the array not a memory address.
Sorry this concept has been tough for me to wrap my head around. Is the PDF just bad at explaining pointers or am I grossly misunderstanding something?
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char strA[80] = "A string to be used for demonstration purposes";
char strB[80];
int main(int argc, char *argv[]){
char *pA; /* a pointer to type character */
char *pB; /* another pointer to type character */
puts(strA); /* show string A */
pA = strA; /* point pA at string A */
puts(pA); /* show what pA is pointing to */
pB = strB; /* point pB at string B */
putchar('\n'); /* move down one line on the screen */
printf("\n%c\n", *pA);
while(*pA != '\0') /* line A (see text) */
{
*pB++ = *pA++; /* line B (see text) */
}
*pB = '\0'; /* line C (see text) */
puts(strB); /* show strB on screen */
return 0;
}
Output:
A string to be used for demonstration purposes
A string to be used for demonstration purposes
A
A string to be used for demonstration purposes
EDIT:
Thanks for the help everyone :), sorry about the noobie question. I read Programming in C by Stephen G. Kochan and its amazing section on pointers helped a lot.

char strA[80] = "A string to be used for demonstration purposes";
This makes an 80 character long space in the global section of the executable - it isn't dynamically allocated so it doesn't need to be deallocated. If strA is used as a pointer it is equivalent to &strA[0] as you expect.
Those 80 characters are filled with the string on the right side of the equals - including the terminating character at the end of the string. That terminating character is really important because that's how you find the end of the printable data in the array.
puts(strA); /* show string A */
When you puts(strA), that function prints EVERY character from the address passed in up to that terminating character - there is a loop inside that function.
pA = strA; /* point pA at string A */
puts(pA); /* show what pA is pointing to */
Then pA is filled with the value of &strA[0] and then when puts(pA); is called, the function receives the same address it received the last time so it does the same thing as last time: it prints EVERY character from the address passed in up to that terminating character.
printf("\n%c\n", *pA);
while(*pA != '\0') /* line A (see text) */
The * character gives you the contents at the location of the pointer - so *strA gives the same thing as strA[0] - the first character of the string. And *pA is the same as *strA because they both point to the same address.
*pB++ = *pA++; /* line B (see text) */
The reason *pA++ confuses you is because you don't know whether the * or the ++ is done first. What happens is: pA++ increments the pointer and returns the original value it had. Then the * takes that original value of the pointer and gives its content - the character where pA originally pointed.

According to the C Standard (6.3.2.1 Lvalues, arrays, and function designators)
3 Except when it is the operand of the sizeof operator or the unary &
operator, or is a string literal used to initialize an array, an
expression that has type ‘‘array of type’’ is converted to an
expression with type ‘‘pointer to type’’ that points to the initial
element of the array object and is not an lvalue. If the array object
has register storage class, the behavior is undefined.
So these two assignment statements
ptr = &my_array[0];
and
ptr = my_array;
are equivalent because the array designator my_array used as an initializer is implicitly converted to pointer to its first element.
In C strings are character arrays that contain sequences of characters terminated with the zero terminating character '\0'.
For example the string literal "Hello" is stored as a character array with this sequence of characters
{ 'H', 'e', 'l', 'l', 'o', '\0' }
The function puts is specially designated to output strings.
It is declared the following way
int puts(const char *s);
the calls of the function
puts(strA);
puts(pA)
are equivalent because again the array designator strA used as an argument in the first call is implicitly converted to pointer to its first element.
Dereferencing a pointer like in this call
printf("\n%c\n", *pA);
you get the object pointed to by the pointer. As the pointer pA points to the first character of the array strA then this character is outputted.

As a follow up to Vlad's answer, which is great, I just wanted to add a small bit of code which really helped me to understand pointers. I find that it is really helpful to make predictions and then write code and make observations until I understand.
[ttucker#zim stackoverflow]$ cat ptr.c
#include <stdio.h>
int main() {
char *foo = "stuff";
while (*foo != '\0') {
printf("%lu: %c (%d), %lu\n", &foo, *foo, *foo, foo);
foo++;
}
return 0;
}
[ttucker#zim stackoverflow]$ gcc -o ptr ptr.c
[ttucker#zim stackoverflow]$ ./ptr
140730183740528: s (115), 94216543457284
140730183740528: t (116), 94216543457285
140730183740528: u (117), 94216543457286
140730183740528: f (102), 94216543457287
140730183740528: f (102), 94216543457288
# A second execution is included to show that the memory addresses change.
[ttucker#zim stackoverflow]$ ./ptr
140723360085232: s (115), 94198997999620
140723360085232: t (116), 94198997999621
140723360085232: u (117), 94198997999622
140723360085232: f (102), 94198997999623
140723360085232: f (102), 94198997999624

Firstly, my understanding of pointers to arrays is that they are initialized in heap memory with the memory address of the first element in the array hence why: ptr = &my_array[0]; /* and */ ptr = my_array; are the same thing.
The only time "heap" memory comes into play is when you're using malloc, calloc, or realloc, or library functions that call them behind the scene. pA and pB occupy the same memory as any other type of variable declared in that scope.
but when he prints the pointer to the screen THE WHOLE STRING PRINTS OUT.
The puts function takes the address of the first character in a string and "walks" down the string, printing each character, until it sees the string terminator, sort of like
void myputs( const char *str ) // str points to the first character in a 0-terminated string
{
while ( *str ) // while we haven't seen the string terminator
putchar( *str++ ); // print the current character and advance the pointer
}
On top of that, he uses ++ on *pA and *pB which makes no sense to me because the output shows that *pA is the first character in the array not a memory address.
The line
*pB++ = *pA++;
is roughly equivalent to writing:
*pB = *pA;
pB = pB + 1;
pA = pA + 1;
Postfix ++ has higher precedence than unary *, so *pA++ is parsed as *(pA++) - you're dereferencing the result of pA++. The result of pA++ is the current value of pA, and as a side effect pA is incremented. Since pA and pB are pointers, adding 1 advances them to point to the next object in the sequence, not necessarily the next byte (although in this particular case, the next object is the next byte).

Related

What is the use of "*&" in the code below

What is the use of *& in the printf statement and how is the output R?
#include <stdio.h>
int main() {
char* str = "ReplyCodeChallenge";
printf("%c\n", *&*str);
return 0;
}
and the output is: R
This is just a matter of multiple referencing and dereferencing.
str is a string pointer
*str is equivalent to *(str + 0) which is the same as str[0]
&(*str) denotes the address of str[0]
*(&*str) simply dereferences that address and gives str[0] back to you
The brackets don't matter here because both & and * fall under the same precedence group and their associativity is from right to left.
Since str[0] is 'R', that's your output.
By this example, you can conclude that *& or (*&*&...) makes no significant difference. But not always, you may see that syntax used in function headers to receive an argument of pointer-type through pass-by-reference mechanism.
char* str = "ReplyCodeChallenge"; defines str to be a pointer to char and initializes it to point to the first character of "ReplyCodeChallenge". ("ReplyCodeChallenge" is a string literal, which is effectively an array. In this use, it is automatically converted to a pointer to its first element, and that pointer is used as the initial value for str.)
str is a pointer to char, which points to the 'R'.
*str is that char, because * gives the thing that a pointer (an address) points to.
&*str is the address of that char, because & gives the address (a pointer) of a thing.
*&*str is that char, again because * gives the thing that a pointer points to.
There are already enough good answers but I add also mine -- like in any expression, you first of all need to split it in parsing tree, in order to detect the order of evaluation of subexpressions.
*&*str
Here you have 3 applications of 2 unary operators, each of them is
prefix unary-operator. So they have the same precedence, so the parsing tree is like that
(*(&(*str)))
The first application *(str) will return the first character from the beginning of str, which has the same address as str itself. So, &*str will be the address of str. So your applications will reduce to
*str
which is the 1st character (integer that represents the ASCII code) from string.
* - dereferences the object referenced by the pointer
& - gets reference to the object
char *p = "ABCD; - &*p, &*&*p, &*&*&*p, &*&*&*p... - does nothing, it is still reference stored in the pointer.
*&*p, *&*&*p, *&*&*&*p, *&*&*&*p... - just dereferences the char referenced by the pointer p, in this case 'A'
https://godbolt.org/z/ijffmP

Using a string in CS50 library

Hi all I have a question regarding a passing a string to a function in C. I am using CS50 library and I know they are passing string as a char array (char pointer to a start of array) so passing is done by reference. My function is receiving array as argument and it returns array. When I change for example one of the element of array in function this change is reflected to original string as I expect. But if I assign new string to argument, function returns another string and original string is not change. Can you explain the mechanics behind this behaviour.
#include <stdlib.h>
#include <cs50.h>
#include <stdio.h>
string test(string s);
int main(void)
{
string text = get_string("Text: ");
string new_text = test(text);
printf("newtext: %s\n %s\n", text, new_text);
printf("\n");
return 0;
}
string test(string s)
{
//s[0] = 'A';
s = "Bla";
return s;
}
First example reflects change in the first letter on both text and newtext strings, but second example prints out text unchanged and newtext as "Bla"
Thanks!
This is going to take a while.
Let's start with the basics. In C, a string is a sequence of character values including a 0-valued terminator. IOW, the string "hello" is represented as the sequence {'h', 'e', 'l', 'l', 'o', 0}. Strings are stored in arrays of char (or wchar_t for "wide" strings, which we won't talk about here). This includes string literals like "Bla" - they're stored in arrays of char such that they are available over the lifetime of the program.
Under most circumstances, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", so most of the time when we're dealing with strings we're actually dealing with expressions of type char *. However, this does not mean that an expression of type char * is a string - a char * may point to the first character of a string, or it may point to the first character in a sequence that isn't a string (no terminator), or it may point to a single character that isn't part of a larger sequence.
A char * may also point to the beginning of a dynamically allocated buffer that has been allocated by malloc, calloc, or realloc.
Another thing to note is that the [] subscript operator is defined in terms of pointer arithmetic - the expression a[i] is defined as *(a + i) - given an address value a (converted from an array type as described above), offset i elements (not bytes) from that address and dereference the result.
Another important thing to note is that the = is not defined to copy the contents of one array to another. In fact, an array expression cannot be the target of an = operator.
The CS50 string type is actually a typedef (alias) for the type char *. The get_string() function performs a lot of magic behind the scenes to dynamically allocate and manage the memory for the string contents, and makes string processing in C look much higher level than it really is. I and several other people consider this a bad way to teach C, at least with respect to strings. Don't get me wrong, it's an extremely useful utility, it's just that once you don't have cs50.h available and have to start doing your own string processing, you're going to be at sea for a while.
So, what does all that nonsense have to do with your code? Specifically, the line
s = "Bla";
What's happening is that instead of copying the contents of the string literal "Bla" to the memory that s points to, the address of the string literal is being written to s, overwriting the previous pointer value. You cannot use the = operator to copy the contents of one string to another; instead, you'll have to use a library function like strcpy:
strcpy( s, "Bla" );
The reason s[0] = A worked as you expected is because the subscript operator [] is defined in terms of pointer arithmetic. The expression a[i] is evaluated as *(a + i) - given an address a (either a pointer, or an array expression that has "decayed" to a pointer as described above), offset i elements (not bytes!) from that address and dereference the result. So s[0] is pointing to the first element of the string you read in.
This is difficult to answer correctly without a code example. I will make one but it might not match what you are doing.
Let's take this C function:
char* edit_string(char *s) {
if(s) {
size_t len = strlen(s);
if(len > 4) {
s[4] = 'X';
}
}
return s;
}
That function will accept a pointer to a character array and if the pointer is not NULL and the zero-terminated array is longer than 4 characters, it will replace the fifth character at index 4 with an 'X'. There are no references in C. They are always called pointers. They are the same thing, and you get access to a pointed-at value with the dereference operator *p, or with array syntax like p[0].
Now, this function:
char* edit_string(char *s) {
if(s) {
size_t len = strlen(s);
if(len > 4) {
char *new_s = malloc(len+1);
strcpy(new_s, s);
new_s[4] = 'X';
return new_s;
}
}
s = malloc(1);
s[0] = '\0';
return s;
}
That function returns a pointer to a newly allocated copy of the original character array, or a newly allocated empty string. (By doing that, the caller can always print it out and call free on the result.)
It does not change the original character array because new_s does not point to the original character array.
Now you could also do this:
const char* edit_string(char *s) {
if(s) {
size_t len = strlen(s);
if(len > 4) {
return "string was longer than 4";
}
}
s = "string was not longer than 4";
return s;
}
Notice that I changed the return type to const char* because a string literal like "string was longer than 4" is constant. Trying to modify it would crash the program.
Doing an assignment to s inside the function does not change the character array that s used to point to. The pointer s points to or references the original character array and then after s = "string" it points to the character array "string".

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.

Arguments passed to puts function in C

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

How does "while(*s++ = *t++)" copy a string?

My question is, what does this code do (from http://www.joelonsoftware.com/articles/CollegeAdvice.html):
while (*s++ = *t++);
the website says that the code above copies a string but I don't understand why...
does it have to do with pointers?
It is equivalent to this:
while (*t) {
*s = *t;
s++;
t++;
}
*s = *t;
When the char that t points to is '\0', the while loop will terminate. Until then, it will copy the char that t is pointing to to the char that s is pointing to, then increment s and t to point to the next char in their arrays.
This has so much going on under the covers:
while (*s++ = *t++);
The s and t variables are pointers (almost certainly characters), s being the destination. The following steps illustrate what's happening:
the contents of t (*t) are copied to s (*s), one character.
s and t are both incremented (++).
the assignment (copy) returns the character that was copied (to the while).
the while continues until that character is zero (end of string in C).
Effectively, it's:
while (*t != 0) {
*s = *t;
s++;
t++;
}
*s = *t;
s++;
t++;
but written out in a much more compact way.
Let's assume s and t are char *s that point to strings (and assume s is at least as large as t). In C, strings all end in 0 (ASCII "NUL"), correct? So what does this do:
*s++ = *t++;
First, it does *s = *t, copying the value at *t to *s. Then, it does s++, so s now points to the next character. And then it does t++, so t points to the next character. This has to do with operator precedence and prefix vs. postfix increment/decrement.
Operator precedence is the order in which operators are resolved. For a simple example, look:
4 + 2 * 3
Is this 4 + (2 * 3) or (4 + 2) * 3? Well, we know it is the first one because of precedence - the binary * (multiplication operator) has higher precedence than the binary + (addition operator), and is resolved first.
In *s++, we have unary * (pointer dereference operator) and unary ++ (postfix increment operator). In this case, ++ has higher precedence (also said to "bind tighter") than *. If we had said ++*s, we would increment the value at *s rather than the address pointed to by s because prefix increment has lower precedence* as dereference, but we used postfix increment, which has higher precedence. If we had wanted to use prefix increment, we could have done *(++s), since the parenthesis would have overridden all lower precedences and forced ++s to come first, but this would have the undesirable side effect of leaving an empty character at the beginning of the string.
Note that just because it has higher precedence doesn't mean it happens first. Postfix increment specifically happens after the value has been used, which his why *s = *t happens before s++.
So now you understand *s++ = *t++. But they put it in a loop:
while(*s++ = *t++);
This loop does nothing - the action is all in the condition. But check out that condition - it returns "false" if *s is ever 0, which means *t was 0, which means they were at the end of the string (yay for ASCII "NUL"). So this loop loops as long as there are characters in t, and copies them dutifully into s, incrementing s and t all the way. When this loop exits, s has been NUL-terminated, and is a proper string. The only problem is, s points to the end. Keep another pointer handy that points to the beginning of s (i.e. s before the while() loop) - that will be your copied string:
char *s, *string = s;
while(*s++ = *t++);
printf("%s", string); // prints the string that was in *t
Alternatively, check this out:
size_t i = strlen(t);
while(*s++ = *t++);
s -= i + 1;
printf("%s\n", s); // prints the string that was in *t
We started by getting the length, so when we ended, we did more pointer arithmetic to put s back at the beginning, where it started.
Of course, this code fragment (and all my code fragments) ignore buffer issues for simplicity. The better version is this:
size_t i = strlen(t);
char *c = malloc(i + 1);
while(*s++ = *t++);
s -= i + 1;
printf("%s\n", s); // prints the string that was in *t
free(c);
But you knew that already, or you'll soon ask a question on everyone's favorite website about it. ;)
* Actually, they have the same precedence, but that's resolved by different rules. They effectively have lower precedence in this situation.
while(*s++ = *t++);
Why do people think it is equivalent to:
while (*t) {
*s = *t;
s++;
t++;
}
*s = *t; /* if *t was 0 at the beginning s and t are not incremented */
when it obviously isn't.
char tmp = 0;
do {
tmp = *t;
*s = tmp;
s++;
t++;
} while(tmp);
is more like it
EDIT: Corrected a compilation error. The tmp variable must be declared outside of the loop.
The aspect that is mysterious about this is the order of operations. If you look up the C language spec, it states that in this context, the order of operations is as follows:
1. * operator
2. = (assignment) operator
3. ++ operator
So the while loop then becomes, in english:
while (some condition):
Take what is at address "t" and copy it over to location at address "s".
Increment "s" by one address location.
Increment "t" by one address location.
Now, what is "some condition"? The C lang specification also says that the value of an assignment expression is the assigned value itself, which in this case is *t.
So "some condition" is "t points to something that is non-zero", or in a simpler way, "while the data at location t is not NULL".
The C Programming Language (K&R) by Brian W. Kernighan and Dennis M. Ritchie gives a detailed explanation of this.
Second Edition, Page 104:
5.5 Character Pointers and Functions
A string constant, written as
"I am a string"
is an array of characters. In the internal representation, the array is terminated with the null character '\0' so that programs can find the end. The length in storage is thus one more than the number of characters between the double quotes.
Perhaps the most common occurrence of string constants is as arguments to functions, as in
printf("hello, world\n");
Where a character string like this appears in a program, access to it is through a character pointer; printf receives a pointer to the beginning of the character array. That is, a string constant is accessed by a pointer to its first element.
String constants need not be functions arguments. If pmessage is declared as
char *pmessage;
then the statement
pmessage = "now is the time";
assigns to pmessage a pointer to the character array. This is not a string copy; only pointers are involved. C does not provide any operators for processing an entire string of characters as a unit.
There is an important different between these definitions:
char amessage[] = "now is the time"; /* an array */
char *pmessage = "now is the time"; /* a pointer */
amessage is an array, just big enough to hold the sequence of characters and '\0' that initializes it. Individual characters within the array may be changed by amessage will always refer to the same storage. On the other hand, pmessage is a pointer, initialized to point to a string constant; the pointer may subsequently be modified to point elsewhere, but the result is undefined if you try to modify the string contents.
+---+ +--------------------+
pmessage: | o-------->| now is the time \0 |
+---+ +--------------------+
+--------------------+
amessage: | now is the time \0 |
+--------------------+
We will illustrate more aspects of pointers and arrays by studying versions of two useful functions adapted from the standard library. The first function is strcpy(s,t), which copies the string t to the string s. It would be nice just to say s = t but this copies the pointer, not the characters.To copy the characters, we need a loop. The array version is first:
/* strcpy: copy t to s; array subscript version */
void strcpy(char *s, char *t)
{
int i;
i = 0;
while((s[i] = t[i]) != '\0')
i ++;
}
For contrast, here is a version of strcpy with pointers:
/* strcpy: copy t to s; pointer version 1 */
void strcpy(char *s, char *t)
{
while((*s = *t) != '\0')
{
s ++;
t ++;
}
}
Because arguments are passed by value, strcpy can use the parameters s and t in any way it pleases. Here they are conveniently initialized pointers, which are marched along the arrays a character at a time, until the '\0' that terminates t has been copied to s.
In practice, strcpy would not be written as we showed it above. Experienced C programmers would prefer
/* strcpy: copy t to s; pointer version 2 */
void strcpy(char *s, char *t)
{
while((*s++ = *t++) != '\0')
;
}
This moves the increment of s and t into the test part of the loop. The value of *t++ is the character that t pointed to before t was incremented; the postfix ++ doesn't change t until after this character has been fetched. In the same way, the character is stored into the old s position before s is incremented. This character is also the value that is compared against '\0' to control the loop. The net effect is that characters are copied from t to s, up to and including the terminating '\0'.
As the final abbreviation, observe that a comparison against '\0' is redundant, since the question is merely whether the expression is zero. So the function would likely be written as
/* strcpy: cope t to s; pointer version 3 */
void strcpy(char *s, char *t)
{
while(*s++ = *t++);
}
Although this may seem cryptic as first sight, the notational convenience is considerable, and the idiom should be mastered, because you will see if frequently in C programs.
The strcpy in the standard library (<string.h>) returns the target string as its function value.
This is the end of the relevant parts of this section.
PS: If you enjoyed reading this, consider buying a copy of K&R - it is not expensive.
It works by copying characters from the string pointed to by 't' into the string pointed to by 's'. For each character copies, both pointers are incremented. The loop terminates when it finds a NUL character (equal to zero, hence the exit).
HINTS:
What does the operator '=' do?
What is the value of the expression "a = b"? Eg: if you do "c = a = b" what value does c get?
What terminates a C string? Does it evaluate true or false?
In "*s++", which operator has higher precedence?
ADVICE:
Use strncpy() instead.
it copies a string because arrays are always passed by reference, and string is just a char array. Basically what is happening is (if i remember the term correctly) pointer arithmetic. Here's a bit more information from wikipedia on c arrays.
You are storing the value that was dereferenced from t in s and then moving to the next index via the ++.
Say you have something like this:
char *someString = "Hello, World!";
someString points to the first character in the string - in this case 'H'.
Now, if you increment the pointer by one:
someString++
someString will now point to 'e'.
while ( *someString++ );
will loop until whatever someString points at becomes NULL, which is what signals the end of a string ("NULL Terminated").
And the code:
while (*s++ = *t++);
is equal to:
while ( *t != NULL ) { // While whatever t points to isn't NULL
*s = *t; // copy whatever t points to into s
s++;
t++;
}
Yes, it does have to do with pointers.
The way to read the code is this: "the value that is pointed to by the pointer "s" (which gets incremented after this operation) gets the value which is pointed to by the pointer "t" (which gets incremented after this operation; the entire value of this operation evaluates to the value of the character copied; iterate across this operation until that value equals zero". Since the value of the string null terminator is the character value of zero ('/0'), the loop will iterate until a string is copied from the location pointed to by t to the location pointed to by s.
Many adherents of С language are convinced that the "while (* s ++ = * t ++)"
is a genuine grace.
In the conditional expression of the loop "while",three side effects are inserted(shift of one pointer, shift of the second pointer, assignment).
The body of the loop as a result was empty, since all the functionality is placed in a conditional expression.
use for with int i:
char t[]="I am a programmer",s[20];
for(int i=0;*(t+i)!='\0';i++)
*(s+i)=*(t+i);
*(s+i)=*(t+i); //the last char in t '\0'
printf("t is:%s\n",t);
printf("s is:%s\n",s);
use for with pointer++:
char t[]="I am a programmer",s[20];
char *p1,*p2;
p1=t,p2=s;
for(;*p1!='\0';p1++,p2++)
*p2 = *p1;
*p2 = *p1;
printf("t is:%s\n",t);
printf("s is:%s\n",s);
use while with pointer++:
char t[]="I am a programmer",s[20];
char *p1,*p2;
p1=t,p2=s;
while(*p2++=*p1++);
printf("t is:%s\n",t);
printf("s is:%s\n",s);
printf("t is:%s\n",p1-18);
printf("s is:%s\n",p2-18);
use array to initialize pointers:
char a[20],*t="I am a programmer",*s;
s=a;
while(*s++=*t++);
printf("t is:%s\n",t-18);
printf("s is:%s\n",s-18);
printf("s is:%s\n",a);
starts a while loop....
*s = *t goes first, this assigns to what t points at to what s points at. ie, it copies a character from t string to s string.
what is being assigned is passed to the while condition... any non zero is "true" so it will continue, and 0 is false, it will stop.... and it just happens the end of a string is also zero.
s++ and t++ they increment the pointers
and it all starts again
so it keeps assigning looping, moving the pointers, until it hits a 0, which is the end of the string
Yes this uses pointers, and also does all the work while evaluating the while condition. C allows conditional expressions to have side-effects.
The "*" operator derefereces pointers s and t.
The increment operator ("++") increments pointers s and t after the assignment.
The loop terminates on condition of a null character, which evaluates as false in C.
One additional comment.... this is not safe code, as it does nothing to ensure s has enough memory allocated.
The question I provided the following answer on was closed as a duplicate of this question, so I am copying the relevant part of the answer here.
The actual semantic explanation of the while loop would be something like:
for (;;) {
char *olds = s; // original s in olds
char *oldt = t; // original t in oldt
char c = *oldt; // original *t in c
s += 1; // complete post increment of s
t += 1; // complete post increment of t
*olds = c; // copy character c into *olds
if (c) continue; // continue if c is not 0
break; // otherwise loop ends
}
The order that s and t are saved, and the order that s and t are incremented may be interchanged. The save of *oldt to c can occur any time after oldt is saved and before c is used. The assignment of c to *olds can occur any time after c and olds are saved. On the back of my envelop, this works out to at least 40 different interpretations.
Well this is true just in the case of the char if there is no \0 and the it is an integer array the the program will crash because there will be a address whose elements are not the part of the array or pointer, if the system has memory that was allocated using the malloc then the system will keep giving the memory

Resources