I can't find a description of the difference between:
char *myVar
and
char myVar[ ]
Can someone please fill me in?
I can't find a description of the difference between:
char *myVar
and
char myVar[ ]
Can someone please fill me in?
char *charPointer; //declares a pointer to a memory address
char charArray[12]; //declares an array of 12 chars in memory
//this means that charArray is a pointer to an address in memory that is guaranteed to have space allocated for it and the next 11 locations
Using arrays the compiler can do some checks, using pointers the compiler will trust you.
If the OP means in a parameter list, then the difference between them is simpler; there isn't one.
Both answers are right, but there is a little more to it. A char * is a pointer to a character or character array, but the declaration of a pointer does not reserve any space to store any characters. The declaration of an array does.
If you do this:
char myArray[20];
myArray[0] = 'A';
myArray[1] = '\0';
it's legal and valid.
If you do this:
char *myPtr;
myPtr[0] = 'A';
myPtr[1] = '\0';
it's invalid, since myPtr does not point to any space.
Typically, pointers are used for dynamic array allocation (such as malloc) and processing (such as strtok).
Not to be an ass PaulS, but you say that there are more to it, but never say what.
And "A char * is a pointer to a character or character array" is not correct. A char pointer always points to a char. If that char happens to be a part of a defined array that's just lucky;)
Pointers are used when you need to reserve the possibility to point at nowhere. An array identifier always points to somewhere.
Steve S try this:
const int size = 10;
void test(int arr[][size])
{
cout << arr[0] << endl;
}
void setup() {
int **tester; //because array is the same as pointer, logic dictates [][] is the same as **
//you can even try int tester[10][2]; //compile error
test(tester);
}
void loop() {
}
You see that the array/pointer definition in parameter lists can matter.
/me is now done being an ass
Not being an ass at all, AlphaBeta - try doing "sizeof"1 on "char* myChar" and on "char myChar [SOME_CONSTANT]".
1Not to be confused with "strlen".
Also,
char *myPtr;
myPtr = myOtherArray; // works fine
But,
char myArray[];
myArray = myOtherArray; // won't compile
-Mike
True, you cannot re-assign an array (regardless of type, not just char) in that way.
I also accept the criticism where you're using multiple dimensions. However, as a C programmer of long standing, and even longer sitting1, in my defence I was trying to keep things simple for the original poster.
From following the developer mailing list, I recognise that not everyone came to the Arduino platform via the same route as me, as we keep being told
But yes, I was a little lax in my reply - I promise I'll try and do better next time
1I started professionally around 1981. Is it any wonder I can't see properly to solder even through-hole these days...
I can now understand the technical difference between the two but am still a bit hazy on when it is best to use char *str1 and when to use char str2[ ] in the following circumstances:
Use char *str1 = "Test123" or char str2[ ] = "Test123" when initialising a string variable for use as a constant in the current function?
Use char *str1 = "Test123" or char str2[ ] = "Test123" when initialising a string variable for use in the current function which will substitute another value in the variable?
Use char *str1 = "Test123" or char str2[ ] = "Test123" when initialising a string variable to pass as a parameter to another function?
(Will str1 automatically have a \0 appended to the end when it is initialised?)
To keep it simple for now, let's just look at declaring global variables, outside of any function.
If you say:char mystr[] = "Hello";
It will create a character array. The compiler figures out that the array needs to be 6 characters long, to hold H, e, l, l, o, and '\0', the NUL terminator.
You can treat 'mystr' like a read-only (const) character pointer. You can call functions with 'mystr' as a parameter. You can reference 'mystr[1]' to access the second character ('e') in the array. You can de-reference 'mystr' as a pointer -- '*mystr' is a character ('H').
You can also change the contents of the 'mystr' array. For example, if you say: mystr[0] = 'J';
The string will now say "Jello".
How much space have you used up in RAM? Six characters. When you use 'mystr' as a pointer, the compiler fills in the value for it, just as it fills in the value for 6 or 298.
What you CANNOT do is change the value of 'mystr' as a pointer. You cannot make it point to another place in memory. It will always point to the beginning of the six-character array, no matter what the contents of that array may be set to. In fact, if you try to change it, you will get an error when you try to compile your program:
char mystr[] = "Hello";
void myfun(void)
{
mystr = "Oops!"; // will not compile
}
Now, if you make a global declaration like so:char *mystr = "Hello";
you've actually done something different. For one thing, you've got a pointer, which is a variable, just like an 'int'. If I recall correctly, pointers on the Arduino take up two bytes. Also, somewhere else in RAM, the compiler has stashed six characters: H, e, l, l, o, and '\0'. So in this case, you've used up 8 bytes of RAM, rather than six for a simple array.
Also, this case is just the opposite of the array case -- you can change the pointer, but you shouldn't change the thing pointed to.
If you want to change the string the 'mystr' points to, you can do it with a simple statement (note that this is a program statement, not a declaration)mystr = "Goodbye";
What's happening here is that the compiler has yet another string stashed away in memory, containing 8 characters: G, o, o, d, b, y, e, and '\0'. When the statement executes, the value of the pointer 'mystr' is changed to the address of the "Goodbye" string.
Now, it would not be a good thing to change the value of the string by using 'mystr'. The compiler might let you say this:*mystr = 'N';
but this could cause trouble down the road. The compiler may have optimized the code by sharing a string constant. For example, with this code:
char *mystr = "Hello";
char *otherstr = "Hello";
The two pointers might point to the same place in memory, or they might not. If you change a character in the string, it might also be changed in the string pointed to by the other pointer. Or it might not. It might work the way you expect on one version of the compiler, or on one chip, but not on another. On some more sophisticated systems, it might cause the program to crash, since it might be writing to a block of memory that has been set to be read-only.
In other words, just don't do it. What you are in essence doing is changing a string constant, and changing constants within your program is always a bad idea.
Now, if the pointer is not pointing to a string constant (e.g., "Hello"), it's perfectly all right to change the thing pointed to.
I hope this clears up the confusion a little bit. Pointers to strings and arrays containing strings are really two different things, even though the language lets us use them interchangeably in some cases.
Regards,
-Mike
All strings constants are automatically terminated with a NUL.
Now, the difference between:
char *str1 = "Hello";
and
char str2[] = "Hello";
is that str1
is a direct pointer to the location where the string constant is stored, whereas str2
points to a copy of the string constant that can be manipulated.
According to Kernighan and Ritchie, it is legal to modify str2
, but it is undefined what will happen if you modify str1
. Furthermore, you can change where str1
points to, but you can not change where str2
points to.
To boil it down:
You can modify the contents of str2
, but it is not recommended that you modify the contents of str1
.
Technical mumbo-jumbo:
The way AVR-GCC/G++ works is that the string constants are stored in program memory/flash, then are copied to RAM at the beginning of your program.
str1
will point to the existing copy of that string constant, whereas str2
is a new array variable with enough space to contain the string constant - which is copied just before use - i.e. in the function it's declared, or at the program start for globals.
You get a compiler warning (hidden by Arduino IDE): "deprecated conversion from string constant to 'char *'" when you compile using str1
.
str1
SHOULD be declared as:
const char *str1 = "Hello";
This means you can not change the contents of str1
(it is a constant, after all).
b
FWIW: I recommend reading KnR's "The C Programming Language".
Thanks guys.
(I have a copy of K&R on order.)
As an exercise for the reader, what does this mean: char * const word = "try it";
AlphaBeta,
Thanks for posting that. I was trying to figure out the syntax for that.
It means that the pointer itself is a constant and can't be changed. For example:
char * const str = "Hello";
void myfun(void)
{
*str = 'J'; // this will compile, but may cause problems in your program
str = "Goodbye"; // this will not compile because 'str' is a const
}
Regards,
-Mike