The same notation is used for pointing at a single character or the first character of a null-terminated string:
char c = 'Z';
char a[] = "Hello world";
char *ptr1 = &c;
char *ptr2 = a; // Points to the 'H' of "Hello world"
char *ptr3 = &a[0]; // Also points to the 'H' of "Hello world"
char *ptr4 = &a[6]; // Points to the 'w' of "world"
char *ptr5 = a + 6; // Also points to the 'w' of "world"
The values in ptr2 and ptr3 are the same; so are the values in ptr4 and ptr5. If you're going to treat some data as a string, it is important to make sure it is null terminated, and that you know how much space there is for you to use. Many problems are caused by not understanding what space is available and not knowing whether the string was properly null terminated.
Note that all the pointers above can be dereferenced as if they were an array:
*ptr1 == 'Z'
ptr1[0] == 'Z'
*ptr2 == 'H'
ptr2[0] == 'H'
ptr2[4] == 'o'
*ptr4 == 'w'
ptr4[0] == 'w'
ptr4[4] == 'd'
ptr5[0] == ptr3[6]
*(ptr5+0) == *(ptr3+6)
Late addition to question
What does
char (*ptr)[N];represent?
This is a more complex beastie altogether. It is a pointer to an array of N characters. The type is quite different; the way it is used is quite different; the size of the object pointed to is quite different.
char (*ptr)[12] = &a;
(*ptr)[0] == 'H'
(*ptr)[6] == 'w'
*(*ptr + 6) == 'w'
Note that ptr + 1 points to undefined territory, but points 'one array of 12 bytes' beyond the start of a. Given a slightly different scenario:
char b[3][12] = { "Hello world", "Farewell", "Au revoir" };
char (*pb)[12] = &b[0];
Now:
(*(pb+0))[0] == 'H'
(*(pb+1))[0] == 'F'
(*(pb+2))[5] == 'v'
You probably won't come across pointers to arrays except by accident for quite some time; I've used them a few times in the last 25 years, but so few that I can count the occasions on the fingers of one hand (and several of those have been answering questions on Stack Overflow). Beyond knowing that they exist, that they are the result of taking the address of an array, and that you probably didn't want it, you don't really need to know more about pointers to arrays.
Answer from Jonathan Leffler on Stack OverflowThe same notation is used for pointing at a single character or the first character of a null-terminated string:
char c = 'Z';
char a[] = "Hello world";
char *ptr1 = &c;
char *ptr2 = a; // Points to the 'H' of "Hello world"
char *ptr3 = &a[0]; // Also points to the 'H' of "Hello world"
char *ptr4 = &a[6]; // Points to the 'w' of "world"
char *ptr5 = a + 6; // Also points to the 'w' of "world"
The values in ptr2 and ptr3 are the same; so are the values in ptr4 and ptr5. If you're going to treat some data as a string, it is important to make sure it is null terminated, and that you know how much space there is for you to use. Many problems are caused by not understanding what space is available and not knowing whether the string was properly null terminated.
Note that all the pointers above can be dereferenced as if they were an array:
*ptr1 == 'Z'
ptr1[0] == 'Z'
*ptr2 == 'H'
ptr2[0] == 'H'
ptr2[4] == 'o'
*ptr4 == 'w'
ptr4[0] == 'w'
ptr4[4] == 'd'
ptr5[0] == ptr3[6]
*(ptr5+0) == *(ptr3+6)
Late addition to question
What does
char (*ptr)[N];represent?
This is a more complex beastie altogether. It is a pointer to an array of N characters. The type is quite different; the way it is used is quite different; the size of the object pointed to is quite different.
char (*ptr)[12] = &a;
(*ptr)[0] == 'H'
(*ptr)[6] == 'w'
*(*ptr + 6) == 'w'
Note that ptr + 1 points to undefined territory, but points 'one array of 12 bytes' beyond the start of a. Given a slightly different scenario:
char b[3][12] = { "Hello world", "Farewell", "Au revoir" };
char (*pb)[12] = &b[0];
Now:
(*(pb+0))[0] == 'H'
(*(pb+1))[0] == 'F'
(*(pb+2))[5] == 'v'
You probably won't come across pointers to arrays except by accident for quite some time; I've used them a few times in the last 25 years, but so few that I can count the occasions on the fingers of one hand (and several of those have been answering questions on Stack Overflow). Beyond knowing that they exist, that they are the result of taking the address of an array, and that you probably didn't want it, you don't really need to know more about pointers to arrays.
The very same. A C string is nothing but an array of characters, so a pointer to a string is a pointer to an array of characters. And a pointer to an array is the very same as a pointer to its first element.
HELP ME WITH POINTERS AND STRINGS!
String literal as pointers?
How to return a pointer to a string in C - Stack Overflow
Assigning strings to pointer in C - Software Engineering Stack Exchange
Can I use a string pointer in a struct?
Can I return a string pointer from a function?
Are string pointers faster than arrays for string manipulation?
Hi, i don't really understand something about strings and pointers So basically a string is an character array ( correct me if im wrong) and we all know that the name of an array is a constant pointer which means we cannot increment or decrement it Although that i found sometimes they do increment the pointer For exemple
Char*S="hello"; While((*S)!='/0') S++ Please someone explain to me the difference between a string and a character array along with pointers!!
I am still learning c, and I am really confused by this. Any help is appreciated.
There are multiple mistakes in the shared code, primarily -
s++;move the pointer till'\0'. It should be brought back 1 unit to point to actual string by puttings--. Other wise the copied one will start with '\0' that will make it empty string.- Magic numbers 20 and 13. where in
malloc()1 + length of s should be sufficient instead or 20. For 13 just move a unit ahead and put'\0'
However, using string.h library functions() this can be super easy. But I think you are doing it for learning purpose.
Therefore, Corrected code without using string.h lib function() should look like this:
char *reverseStr(char s[])
{
printf("Initial string is: %s\n", s);
int cCounter = 0;
while(*s != '\0')
{
cCounter++;
s++;
}
s--; //move pointer back to point actual string's last charecter
printf("String contains %d symbols\n", cCounter);
char *result = (char *) malloc(sizeof(char) * ( cCounter + 1 ));
if( result == NULL ) /*Check for failure. */
{
puts( "Can't allocate memory!" );
exit( 0 );
}
char *tempResult = result;
for (int begin = 0; begin < cCounter; begin++)
{
*tempResult = *s;
s--; tempResult++;
}
*tempResult = '\0';
//result[cCounter+1] = '\0';
return result;
}
Calling from main
int main()
{
char testStr[] = "Hello world!";
char *pTestStr;
puts("----------------------------------");
puts("Input a string:");
pTestStr = reverseStr(testStr);
printf("%s\n", pTestStr);
free(pTestStr);
}
Output
----------------------------------
Input a string:
Initial string is: Hello world!
String contains 12 symbols
!dlrow olleH
As per WhozCraig suggestion just by using pointer arithmetic only -
char *reverseStr(const char s[])
{
const char *end = s;
while (*end)
++end;
char *result = malloc((end - s) + 1), *beg = result;
if (result == NULL)
{
perror("Failed to allocate string buffer");
exit(EXIT_FAILURE);
}
while (end != s)
*beg++ = *--end;
*beg = 0;
return result;
}
Your code can be simplified using a string library function found in string.h
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *reverseStr(char s[])
{
printf("Initial string is: %s\n", s);
int cCounter = strlen(s);
char *result = malloc(cCounter + 1);
printf("String contains %d symbols\n", cCounter);
int begin = cCounter;
for(; cCounter > 0; cCounter--)
{
result[begin - cCounter] = s[cCounter - 1];
}
result[begin] = '\0';
return result;
}
int main()
{
char testStr[] = "Hello world!";
char *pTestStr;
puts("----------------------------------");
puts("Input a string:");
pTestStr = reverseStr(testStr);
printf("%s\n", pTestStr);
free(pTestStr);
return 0;
}
Output:
----------------------------------
Input a string:
Initial string is: Hello world!
String contains 12 symbols
!dlrow olleH
This is just the way string literals work in C. String literals like "name" are arrays of characters, it is equivalent to the five element array {'n', 'a', 'm', 'e', '\0'}. For the code
char *c;
c="name";
the environment reserves memory for the above array already at initialization time, when the program is loaded from disk into memory. At run time, the adress of the beginning of that array is assigned to c.
Note the first piece of code of yours is not equivalent to the second, because in the first piece you assign a string literal (and not a character like 'n') to a char* variable. In the second, you try to assign an int (and not an int array) to an int*.
Here is a tutorial on strings and pointers in C with a more detailed explanation.
String literals like "name" are stored as arrays of char (const char in C++) such that they are allocated when the program starts and held until the program terminates.
The type of the expression "name" is "5-element array of char" (5th element for the 0 terminator). Except when it is the operand of the sizeof or unary * operators, or is a string literal being used to initialize an array in a declaration, an expression of type "N-element array of T" will be converted ("decay") to an expression of type "pointer to T", and the value of the expression will be the address of the first element of the array.
So, when you write
c="name";
"name" is not the operand of the sizeof or unary * operators, and it isn't being used to initialize an array in a declaration, so the address of the first element of the string is being assigned to the pointer variable c. Essentially, what you have in memory is something like the following:
+-----+
"name"[0] : | 'n' | <-------+
+-----+ |
"name"[1] : | 'a' | |
+-----+ |
"name"[2] : | 'm' | |
+-----+ |
"name"[3] : | 'e' | |
+-----+ |
"name"[4] : | 0 | |
+-----+ |
... |
+-----+ |
c : | | ---------+
+-----+
char *pointer = &string;
should be
char *pointer = string;
string is a pointer variable that contains the address of your string literal. You want the address of the string literal, so you should simply copy the value in string - not take the address of the local pointer variable - your current code gives you a pointer to a pointer to a string.
Additionally, pointer = (char *)pointer + sizeof(char); doesn't require a cast, and it should not use sizeof(char). When incrementing a variable of type pointer to X, incrementing it by one will increment it by sizeof(X) bytes - increment by one to point at the next X. Use pointer += 1; or ++pointer instead.
If you want to print (or otherwise process) the whole string one char at a time, you may use the following idiom:
char *p = /* ... */;
while (p && *p) {
printf("next char: %c\n", *p++);
}
The condition first tests whether p is NULL, i.e. if it is wise to dereference p at all. If p is not NULL, *p tests whether you already reached the end of the string, denoted by the '\0' character, which happens to be 0.