My question is simple:
Say you have this:
char *chrptr = "junk";
Imagine at the time, *chrptr would point at j. Is there a way to increment the current character j to the next character which, in this case would be k? I don't want to go to the next character, I want to increment the current-pointed to character.
I'm new to C, and what I tried: (*chrptr)++ doesn't work.
Based on your edit, it seems like you want to modify the string, you can't do that with a constant string, actually you can but that behaviour is undefined. So you need to change the definition to a non-constant array of characters:
//This initializes a 5 element array including the null byte at the end
char chrptr[] = "junk";
//now you can modify that
chrptr[0]++;
//or equivalently
chrptr[0] +=1;
chrptr[0] = chrptr[0]+1;
char *chrptr = "junk";
This code isn't really good. String literals like "junk" are pointers to read-only memory. You're not supposed to ever modify them. So either say:
const char* chrptr = "junk"; // pointer to a const; no modifications
or (in your case):
char chrArray[] = "junk";
This creates a 5-element array of characters on the stack, initializes it with "junk" (plus the null terminator). Now you're free to modify it:
chrArray[0] ++;
(*chrArray) ++;
(Some leftover remarks)
I'm new to c, but things such as (*chrptr)++ don't work.
They do work, but differently. Let me sum this up:
chrptr is a value of type pointer-to-char.
*chrptr is a value of type char, because the pointer has been dereferenced.
Both of these happen to be "l-values" (= actual objects), so you can modify them:
++ chrptr increments the pointer by one (= advances the pointer one object forward)
++ *chrptr increments the char by one (= changes 'a' into 'b').
(Before, ++*chrptr didn't work for you because the string was in read-only section of memory. If you had pointed to it using const char* not char*, you'd get a helpful compile error instead of unexpected runtime behaviour.)
Also note:
In case of a simple statement, ++*chrptr; is equivalent to (*chrptr)++;. The operator order is important (dereference, then increment).
OTOH, *chrptr++ is increment-then-dereference because of the operator precedence. If not sure about precedence, add parentheses.
You do not need to dereference the pointer again using the dereference operator *.
You simply need to do chrptr++ to advance the character pointer in memory.
Update
You can wrap a while loop around to search for the character.
char *chrptr = "junk";
char search = 'k';
while (*chrptr) {
if (*chrptr == search)
printf("%c\n", *chrptr);
chtptr++;
}
See this (*chrptr)++; works fine but this will increment the first character of the array pointed by chrptr.
In your case you are using the statement like
char *chrptr = "junk";
Here chrptr is pointing to a const char array so on using (*chrptr)++; it will increment not reflect the changes in the string.
But if you use the code like this way (http://codepad.org/FJMB1ryv) :--
#include<iostream>
using namespace std;
int main()
{
char a[]="yogendra";
char *y=a;//(char*)"junk";
(*y)++;
cout<<y<<endl;
return 0;
}
you (*y)++ will work.Hoping this will help you. Good luck:)
Related
I have a question regarding the operation on character array.
I was inspired by This answer here that discusses char* vs char[]. In this answer, it says considering a case where we want to cut off the first character of a word,
char* p = "hello";
p++;
is a much faster operation, than if we declared using character array, and therefore had to index into every element.
char s[] = "hello";
s[0] = 'e';
s[1] = 'l';
s[2] = 'l';
s[3] = 'o';
s[4] = '/0';
But my question is, in the second case, cannot I just use another pointer that points to the start of s, i.e.
char* ptr = s;
and then treat it the same as char* p? Would it be as fast?
You mean something like this?
char s[] = "Hello";
char *ptr = s+1;
Yes, you can do that, and it results in ptr pointing to the string "ello". It is just as fast; like the other example, it should be simple arithmetic and not require any copying of data.
I think it is a misconception to think of this as a "pointer versus array" issue. Pointers and arrays in C are inseparable. Both examples involve an array, and two different pointers into that array. In the first example, the array is created by the string literal "Hello" and doesn't have a name; the values of p before and after p++ both point into that array. In the second example, the array is named s, and the expression s decays into a pointer to the zeroth element of that array; s+1 is a pointer to the first element.
The main difference is that in the second example, the array can be modified, and may have a finite lifetime. So your program now has to manage issues of aliasing and ownership. Suppose one part of the code accesses the string through s, and another part accesses it through ptr. Are you prepared for the fact that if the first code modifies the string, the second code will see it change? Does your code correctly keep track of when the lifetime of s ends (e.g. the end of the block where it's defined), and does it make sure not to use ptr beyond that point?
By contrast, the string literal in the first example has static lifetime, and survives until the end of the program; so ptr = p+1 remains valid indefinitely. It also must not be modified at all, or undefined behavior results. So if your program is otherwise bug free, you don't have to worry about some other part of your code changing the string behind your back.
The way I understand these things:
char *p = "hello";
Six bytes (including terminating '\0') are put in READ ONLY memory, and the address of the first byte is put into the variable p that has the datatype char *. Yes, the code can increment/decrement p to point further into the string.
char s[] = "hello";
Six bytes (including terminating '\0') are put in READ/WRITE memory, and referring to s means referring to the initial byte of the string. Yes, another pointer can be declared: char *p = s; And, yes, the code can manipulate the data stored in those six bytes.
char *p = &s[1]; // don't need to increment.
If you want to really play with things:
printf( "%.3s\n", &"Hi there"[3] );
will print "the". There is no name and no pointer, but there is an unnamed READONLY array that can be (carefully!) accessed.
Consider the following example that 'decorates' up to the 31 day of a month with the correct 'ordinal' suffix:
for( int DoM = 1; DoM <= 31; DoM++ ) {
int i = DoM;
if( i > 20 ) i %= 10; // Change 21-99 to 1-10. Don't wanna think about 100+
if( i > 3 ) i = 0; // Every other one ends with "th"
// 0 1 2 3
printf( "%d%s\n", DoM, &"th\0st\0nd\0rd"[ i * 3 ] );
}
I am trying to understand a bit more about incrementing arrays vs pointers. For example, the following works:
char string[] = "Hi";
char * pstring = string;
while(*pstring)
printf("%c", *pstring++);
But if I remove the pointer, it will not:
char string[] = "Hi";
while(*string)
printf("%c", *string++);
Why does the first one work? What's the main difference between iteration through a pointer and array?
There's really quite a lot of rationales for why the second one doesn't work. I'm sure you know this, but I'll just reiterate: an array is not a pointer. Arrays are only converted to pointers. This is automatic, and it happens "very often", but arrays and pointers are still different types. In terms of the language, you simply cannot assign to an array (lvalues of array type are not "modifiable lvalues"), and, specifically, the "hidden" string = string + 1 assignment in string++ does not work. You can, of course, assign to a pointer variable. For this reason, in the C standard, ++ is defined to work only on numeric ("real") and pointer types, and this means you aren't allowed to give it an array.
In terms of why the rules are like this, one train of thought starts by noticing that an array type is only "complete" when it has a size—i.e. if you have a variable of array type, its size is a part of its type. Trying to mutate string with arithmetic, as you do here, would require changing the type of string, because the size would change, but this is not allowed in C. (Note that char string[]; is an invalid declaration because it doesn't specify a size; when you added the initializer you told C to infer the size (3) from it.) In the pointer version, pstring is a char*, and so is pstring + 1, so there's no issue. In the array version, you'd need to have char string[3] before the loop and char string[1] afterwards. Worse, the final size of string would depend on the data in it, so there'd be no way to predict it from the language's point of view. Best not open that can of worms, no?
The idea of incrementing string also breaks down because, in C, an "array object" is more than "a bunch of contiguous elements". When you declare string, yes, you create a bunch of char objects that are contiguous in memory, but you also "bless" (this is not a technical term, unless you're using Perl :)) that memory into being a char[3] object. Probably, in terms of the actual machine, this "blessing" doesn't actually do or mean anything, but, in terms of the abstract machine that C programs run on, there is a difference. Specifically, there is neither an char[2] object located at memory address string + 1 nor an char[1] at string + 2. Thus, were you to increment string, there would be no array for string to refer to anymore.
I suppose you can boil all this down to the intuition that an array is really just "a bunch of variables". That is, when you declared char string[3];, that should feel like you did char string_0, string_1, string_2;. This is just like if you had struct { int x; char y; } test;—this feels like writing int test_x; char test_y;. "Incrementing a group of variables" is quite meaningless, so of course string++ and test++ are disallowed. With string, you have the option to create a char *pstring, such that pstring = &string_0, pstring + 1 = &string_1, pstring + 2 = &string_2, but that doesn't change the fact that doing arithmetic on string itself (especially destructively incrementing it) doesn't make sense.
Here's my two bits....
Why does the first one work?
The pointer "pstring" is a 'variable'. This means that the pointer "pstring" can be re-assigned a new value.
pstring++ is "pstring = pstring + 1" (allowed).
Other valid pointer operations are:
Assignment of pointers of the same type.
Adding or Subtracting a pointer and an integer.
Subtracting or Comparing two pointers to members of the same array.
Assigning or Comparing a pointer to zero(NULL).
What's the main difference between iteration through a pointer and array?
The name of the array(synonymous with the location of the first element) is not a "variable" and will always refer to the same storage.
Though an integer can be added to or subtracted from an array name, re-assigning a new value to an array name is illegal.
string++ is "string = string + 1" (not allowed).
The difference in coding is extrapolated further in the following:
char string[] = "Hi";
int i = 0;
while(*(string+i)){ // or string[i]
printf("%c", *(string+i));// or string[i]
i++;
}
This is probably a really easy question but I can not seem to find an explicit answer online. Say a had a pointer to an array declared as:
static char newMessage[400];
char *p = &newMessage;
(I don't know if this is right) How would I go about manipulation the newMessage array using only the pointer. I am doing this because a C cannot return an array but can return a pointer to an array. please be gentle, I'm new
Your code is almost right; the only problem is that you have mismatched pointer types. You want:
char *p = newMessage;
Not:
char *p = &newMessage;
The latter tries to initialize p, a char * variable, with a value of type char (*)[400], which isn't valid C.
After you've created and initialized p, you can just use it however you'd like:
p[6] = 12;
Or something like that.
Just point the pointer to the array
char* p = newMessage ;
And return it from a function.
You use it the same as you would use the array it points to.
newMessage[2] = '\0'
p[2] = '\0'
When you declare an array like static char newMessage[400], the identifier newMessage is substituted by the address of the first element of the array, and it behaves like a pointer.
char* p= newMessage;
char* q= "Hi, world";
newMessage[4]= 'x';
p[4]= 'x';
*(newMessage + 2)= 0;
*(p+2)= 0;
strlen(newMessage);
strlen(q);
strcmp(newMessage, "Hi world");
strcmp(p, q);
are all valid expressions.
Note that in the last four function calls, you are not passing arrays, but pointers to the first character of the string. And by convention, the functions scan the memory until they find a null byte terminator.
Actually, it should be char *p = newMessage; .The char[] behaves similar to char*.
You'll later modify it by how you usually modify any pointer.
BTW, this is very basic so it's better you read a tutorial.
Also, since you asked this, if you're planning to return a pointer to the array, the array better not be allocated on the stack. It should be heap-allocated (it's in your case since static)
You cannot actually manipulate the array, as arrays are no first class type in c.
Almost anything you care to do with the array name, will make it degenerate to a pointer. The exception being sizeof, so you can get the element count using sizeof array/sizeof *array.
What you can do, is change the values of the array elements. Use pointer arithmetic and dereferencing *. The index operator a[b] is syntactic sugar for *(a+b).
Also, you can use library functions (or your own), which accept pointers.
#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.
I have this code:
char *name[] = { "a1", "b2", "c3", "d4" };
printf("%s\n", *name); //the critical line
Related to critical line:
In this form, the output is simple: a1.
If I replace the critical line with:
printf("%s\n", ++*name);
then the output is 1. I think until now everything is good.
Taking in account that name is a pointer to the first string of characters, respectively "a1", I replace the critical line with:
printf("%s\n", ++name);
in the hope that I'll get "b2" result as output. But I get this error:
../src/test.c:32: error: lvalue required as increment operand.
Question: I can't understand why ++*name is legal - name is a pointer to first string of characters - and ++name isn't. In my opinion, the ++name should move the name to the next string of characters. Can anybody explain me where is the lack in my understing?
When you write ++name, the array name is converted to a pointer to the first element of the array. The result of this conversion is not an lvalue, and it can't be modified with ++ or otherwise. You could instead write name+1, which would print the right thing. When name is an array, there is no way to modify it to refer to anything other than that array[*].
Consider also:
char **p = name; // OK, `name' converts to pointer
++p; // OK, `p' is an lvalue
++(p+1); // not OK, `p+1' is not an lvalue
++((char**)p); // not OK, `(char**)p' is not an lvalue
++*name; // OK, `*name' is an lvalue
Roughly speaking, an "lvalue" is an expression that refers to an object, whereas a "not an lvalue" is an expression that has a value. The difference between an object and a value, is that an object is a place for storing values (well, one value at a time). Values can never be modified, objects sometimes can.
Whenever you have a subexpression which is an lvalue but whose current value is needed, the object is read/loaded/whatever you want to call it. In C++ this is called an "lvalue to rvalue conversion", I can't remember whether it's called anything in C other than "evaluating the subexpression".
[*] you can shadow it with another variable name in an inner scope, that refers to something else. But that's still not modifying the outer name, just temporarily hiding it.
name is an array, so, except when you use it as operand of the sizeof or & operators, it is evaluated as a pointer to the initial member of the array objet and is not an lvalue.
Accordingly, you can't modify name directly, with an operator such as ++ (remember that the postfix increment operator need a modifiable lvalue as operand). Otherwise, you can use a temporary pointer (p in the following example).
#include <stdio.h>
const char *name[] = { "a1", "b2", "c3", "d4" };
const char **p = name;
printf("%s\n", *p); /* Output: a1 */
*++p; /* or *p++ */
printf("%s\n", *p); /* Output: b2 */
While name points to the address of the first element, name is not of type char *, but char *[4]. therefore, sizof(name) == sizeof(char *)*4
Incrementing a pointer always means to add the size of the data it points to. So, after incrementing, it points behind the whole array. Just like if you have
int i, a;
int *p = &i;
p++;
p will now point behind i. It will point to a, if the compiler decided to put a behind i.
Also note that your array only contains 4 pointers, not 4 strings. Like above, it is the compilers choice where those strings actually are. So, the end of the first string is not necessarily next to the beginning of the second string. Especially if you assign other values (string adresses) to name[1] later. Therefore, you may cast name to char **, but should not cast to char *. Incrementing the former will point to the second element (second char* pointer).
First off, make sure you're totally happy and confident with the following fact: An arrays is not a pointer.
Second, what's in a name? The array decays into a pointer to the first element. After decay, the expression name has type char ** (pointer to first element of an array of char*. However, the decayed expression is an rvalue. You cannot modify it! And naturally so, since it makes no sense to modify a pointer that's a pointer to a fixed array.
Therefore, you cannot directly increment the pointer which is the result of decaying name, no more than you can say ++5 or ++foo() (where foo returns a primitive type by value)[whoops, that was a concession meant for C++].
What you can say is this:
char ** np = name;
++np;
printf("%s", *np);
This has the same effect as printing name[1], but now you also have a variable that holds a pointer to the second array element.