Reputation: 10137
Normally, if you do the following:
int * i = &someint;
It's just a pointer to a variable.
But, when you do
char * str = "somestring";
it automatically turns it into an array. Is it the pointer which is doing this, or is it just syntactic sugar for initialization syntax?
Upvotes: 12
Views: 655
Reputation: 22596
As people said str
is not an array but only a pointer to a char (The first of "something", so s). However there are 2 syntaxics sugar
1- "something"
initialize a block of memory with all the characters, **and add \0
at the end.
So
char *str = "something";
is syntaxic sugar for
char *str = {'s', 'o', 'm', 'e', 't', 'h', 'i', 'n', 'g', '\0'};
^ ^^^^^
|
+- str
So technically str
, is 10 characters long not 9. (Note that str
only point to the
2 -
str[5]
is syntaxic sugar for
*(str + 5)
Then, there is a convention that most (not all) C-function dealing with strings, expect the last character to \0
(to know where it ends). Some other (see strncpy
, need the length as an extra argument and can add or not '\0'.
Upvotes: 0
Reputation: 881223
No, the string literal "somestring"
is already a character array, almost certainly created by your compiler.
What that statement is doing is setting str
to point to the first character. If you were to look at the underlying assembler code, it would probably look like:
str314159: db "somestring", 0 ; all string literals here.
: : : :
load r0, str314159 ; get address of string
stor r0, -24[sp] ; store it into local var str.
In a large number of cases, an array will decay to a pointer to the first element of that array (with some limited exceptions such as when doing sizeof
).
By way of example, the following C code:
#include <stdio.h>
int main (void) {
char *somestr = "Hello";
puts (somestr);
return 0;
}
when compiled with gcc -S
to generate x86 assembly, gives us (with irrelevant cruft removed):
.LC0:
.string "Hello"
.text
.globl main
.type main, @function
main:
pushl %ebp ; Standard set up of stack frame,
movl %esp, %ebp ; aligning and making
andl $-16, %esp ; room for
subl $32, %esp ; local variables.
movl $.LC0, 28(%esp) ; Load address of string in to somestr.
movl 28(%esp), %eax ; Call puts with that variable.
movl %eax, (%esp)
call puts
movl $0, %eax ; Set return code.
leave ; Tear down stack frame and return.
ret
You can see that the address of the first character, .LC0
, is indeed loaded into the somestr
variable. And, while it may not be immediately obvious .string
does create an array of characters terminated by the NUL character.
Upvotes: 14
Reputation: 1501
The word you use "normally" is a big part of issue here.
I think part of what may make this confusing is many functions that that take char *
are looking for a c style string (ie null terminated character array). Thats what they want. You could write a function that just looked at the character.
Similarly you could write a function that took a int* and treated it as a null terminated array as well, it is just not common. And for good reason because what if you wanted the value 0? in c style strings (meant for display not binary data) you would never want 0.
#include <iostream>
const int b_in_data[]={50,60,70,80,0};
int Display (const int * a)
{
while ( *a != 0){
std::cout << *a; ++a;
}
}
int main()
{
int a[]={20,30,40,0};
// or more like char* = something because compiler is making string literal for you
// probably somewhere in data section and replacing it with its address
const int *b = b_in_data;
Display(a);
Display(b);
return 0;
}
C style strings just chose to terminate instead of passing size, B style strings passed size instead. arrays of ints are generally not null terminated but could be. Comes down to "normally".
Upvotes: 0
Reputation: 14408
int * i = &someint;
In addition to others comments, Generally, we can say it is pointer to location of size (int). So, When we access value inside 'i'. ie *i, the sizeof(int) memory location is retrieved. Also, the arithmetic calculation is done in the same way. Ie., incrementing the pointer i+1 , increments + sizeof (int). Hence the size of the retrieved data depends on 'data type' of the variable.
Upvotes: 0
Reputation: 1719
char * str
is a pointer to a character. When you assign a string to a character pointer, it is pointing to the first character of the string, not the entire string. If the pointer is incremented you can see that it points to the second character in the string. When you print the character pointer, the cout object prints the character and continues printing character until a null character (\0) is seen.
#include <iostream>
using namespace std;
int main()
{
char *s = "something";
cout << "before :" << s << endl;
s++;
cout << "after :" << s << endl;
}
This program prints:
~/cpp: ./stringarray
before :something
after :omething
Upvotes: 2
Reputation: 17307
It is not a pointer to a variable. It is a pointer to a place in memory. You are creating a variable and storing it in some memory location, then pointing the pointer at that location. The reason it works for arrays is because the elements of the array are stored back to back in memory. The pointer points at the start of the array.
Upvotes: 3