Difference between char* and char[] (2) [duplicate] - c++

This question already has answers here:
Struggling to get number of chars in char* [duplicate]
(2 answers)
What does sizeof(&array) return?
(4 answers)
Closed 9 years ago.
I tried to calculate the length of a character array in the following ways:
char *s="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;
n comes out to be constant value 4, no matter how long the string is. Whereas had i declared the array as
char s[]="abc";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;
The output still remains 4. I understand that in the second case, it includes the concluding character '\0', hence the output.
The only thing i didn't understand is why i get a constant output in first case.

With char *s you make a pointer s that points to some other memory. With char s[] = ... you make a an array of N characters.
Maybe it's easier if you look at it like this:
For the pointer version, char *s = "abcde", it will be something like
+---+ +-----------+
| s | ---> | "abcde\n" |
+---+ +-----------+
While for the case with the array, char s[] = "abc" it will be like
+---------+
| "abc\0" |
+---------+
This should make it easy to see why you can't use sizeof on the pointer, as it returns the size of the pointer and not what it points to. I have also added the string terminator that exists for all string literals, and this is why you get the size 4 for the array, it actually is four characters.

char *s is a pointer to either a char, or a sequence of char. On a 32bit architecture it will be 4 bytes wide, so sizeof(s) will be 4. A single character is (usually) 1 byte, so sizeof(s[0]) will be 1. Therefore, n will be 0.
When you use a char[] type the compiler treats it a a fixed length sequence, it's just working out how long the sequence will be for you, in your case it's 4 characters long. However, if you had:
char s[]="Hello, world";
int n=sizeof(s)/sizeof(s[0]);
Then n would be 13, as there the 12 character you entered, plus the null terminator at the end.

In this code snippet
char *s="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;
s is a pointer. So sizeof( s ) is equal to the size of pointers in the system. In your system the size of a pointer is equal to 4. As the type of s[0] is char then its size equal to 1 and you get value 4.
In the second code snippet
char s[]="abc";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;
s is an array. Its size is determined by the size of the initializer. As string literal "abc" has size equal to 4 because the terminating zero is also counted then the size of array s is 4. If you for example would write
char s[]="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;
then the size of the string literal is equal to 6 and correspondingly the size of the array will be also equal to 6.
You could the same code rewrite the following way
char s[6]="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;
If you write this code as
char s[10]="abcde";
int n=sizeof(s)/sizeof(s[0]);
cout<<n;
then the size of the array will be equal to 10 though the size of the string literal is equal to 6. All other elements of the array that have no initializer will be zero-initialized. That is the array would look as
[a][b][c][d][e]['\0']['\0']['\0']['\0']['\0']

In the first case, s is an object of type char*. sizeof(s) evaluates to the size of this "pointer to char" object, which is 4 (in your execution environment), not the length of the string that s points to (which strlen(s) evaluates to).

Related

size of pointer to array vs string in C++

string a= "Stack Overflow";
char b[]= "Stack Overflow";
cout<<sizeof(a)<<","<<sizeof(b)<<endl;
Output of above code is 4,15
Since 'a' points to the string, it has size 4 that of a string on my machine.
'b' is also pointer to string, but why it has size of 15 (i.e. of sizeof("Stack Overflow")) ?
Since 'a' points to the string, it has size 4 that of a string on my machine.
Not exactly.
a IS A string. It is not a pointer and, hence, does not point to a string. The implementation of string on your setup is such that sizeof(string) is 4.
'b' is also pointer to string, but why it has size of 15 (i.e. of sizeof("Stack Overflow")) ?
Not true.
b is not a pointer to a string. It is an array of char. The line
char b[]= "Stack Overflow";
is equivalent to:
char b[15]= "Stack Overflow";
The compiler deduces the size of the array and creates an array of the right size.

Understanding char array[] and string

I am new to programming. I am learning C as my first programming language. I found something strange to understand.
I have learnt that in C we can represent a String as a sequence of characters like this (using a char array):
char status[10] = "Married";
I have learnt that the problem of this approach is that we have to tell the size of the status array during compilation.
But now I have learned we can use a char pointer to denote an string like -
char status[10] = "Married";
char *strPtr;
strPtr = status;
I don't understand it properly. My questions are -
How can I get char at index 4 (that is i in Married) using the strPtr?
In status there is a null character (\0) at the end of the string represented by the char array - M-a-r-r-i-e-d-\0. So by using the null character (\0) we can understand the end of the string. When we use strPtr, how can we understand the end of the string?
char *strPtr;
strPtr = status;
Now your pointer strPtr is pointing to the first character in the array and you can do
int i =0;
while( strPtr[i] != '\0')
{
printf("%c ",strPtr[i]);
i++;
}
*strPtr is called dereferencing the pointer to get the value stored in the location the pointer is pointing to.
Make a note that
strPtr[4] = *(strPtr +4);
Both will get you the value stored at the index 4 of the array.
Note the difference between a pointer and a array name:
----------------------------------
| s | t | r | i | n | g | \0 |
----------------------------------
|
strPtr
status
strPtr ++ will make your pointer point to the next element in the array.
| s | t | r | i | n | g | \0 |
----------------------------------
|
strPtr
Whereas you can't do this for the array name
status++ is not allowed because an array is not a modifiable lvalue.
Good to know:
char status[10] = "Married";
is just syntax sugar for the equivalent:
char status[10]; // allocate 10 Bytes on stack
status[0] = 'M';
status[1] = 'a';
...
status[6]= 'd';
status[7] = '\0'; // same as 0
Nothing more, nothing less.
Also:
char c = status[3];
is exactly the same as
char c = *(status+3);
The expression status[10] is mere syntactic sugar for *(status+10).
The \0 termination is used under the hood to check for the end, if you were implementing some string-handler yourself you could do this too, or you could ignore it and use some other parameter size given with the string, or you could (don't!) choose anything else as the termination symbol.
This isn't just true of char arrays, or 'strings', a C array is just a pointer to a contiguous block of like-typed stuff with a compile-time check that your 'array' subscripts don't go beyond the 'end' specified at time of declaration. With the *(array+offset) notation, you need to check this for yourself.
To get character at index 4 strPtr, you just use strPtr[4] (this also work for status).
To get the end of the string when using strPtr, you need to go through the characters and look for the terminating \0. This is what printf("%s", strPtr) does when it prints the string (and also when it parses the "%s" expression, which is just another string). To find a number of valid characters in the string in C, you use strlen() function. Oh, and make sure you dont do something like this:
char a[3];
strcpy(a, "Hello!");
As this will write 7 bytes into a three-byte memory space, and hence overwrite something you don't want overwritten.
I'm going to make a provocative statement: the way to think of this is that C doesn't have strings. C only has arrays of char. And despite its name, char is actually a numeric type ('A', for example, is just a funny way to write a number, usually 65).
An array of char is not really different from an array of int or any other array of numeric type; it's just that the language offers some extra ways to write objects of type char and arrays of them, and there is a general convention (systematized with functions like strlen) for how to interpret data stored in char arrays as being representations of strings.
char status[10]; // declares an array of `char` of length 10.
char *strPtr; // declare a pointer to `char`
strPtr = status; // make `strPtr` point to the first element of `status`
// Declare an array of 6 `char`, and initialize it.
char hello[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
// Shorthand notation for initializing an array of 6 `char` as above
char world[6] = "World";
// I want to store numeric data in this one!
char other[6] = {0, 1, 2, 3, 4, 5};
// "World" is shorthand for a constant array of 6 `char`. This is
// shorthand for telling the compiler to actually put that array in
// memory someplace, and initialize worldPtr to point to that memory.
const char *worldPtr = "World";
// This does the same thing as above. But it's still a *constant* array.
// You should *never* do this; it should be syntactically illegal to
// make a nonconstant `char*` to point to it. This is only allowed for
// historical reasons.
char *helloPtr = "Hello";
The '\0' at the end of the string is a useless add-on designed for easy or safety. You can tell string last character by using 'sizeof' like this:
char status[] = "Married";
size_t szLastCharstatus = sizeof(status) / sizeof(status[0]) - 2;
char chLastChar = status[szLastCharstatus];
Detailed explanation:
sizeof(status)
Returns the number of bytes array occpuies.
sizeof(status[0])
Returns the number of bytes first element occupies (and so the rest).
The division between those 2 values gives us the number of elements in the array. To access the last element now we need to subtract one 2 times because elements in array count from zero and because the last character in the string is '\0'.
Also note that arrays are not pointers and vice-versa. Arrays have an implicit conversion to pointer of their first element, constant size and their own type. They can be passed around by pointers or by value (using structure hack is required for the second).
Note that I'm using 'size_t' which is a type-def of a variable storing some size of data.

Behaviour of sizeof() operator

For the following piece of code:
char a[] = "Apple";
char *s[] = {"Apple"};
printf("%d %d\n", sizeof(a), sizeof(s[0]));
The output is:
6 4
Can someone tell me why sizeof() is giving different outputs?
EDIT: I did intend to type sizeof() originally, but typed strlen() instead. I apologize for the same. I have edited the statement now.
sizeof(a) is the size of the array, which contains the terminator as well as the 5 printable characters.
strlen(s[0]) gives the length of the string, excluding the terminator, since that is what strlen is specified to do.
UPDATE: sizeof(s[0]) is the size of a pointer. There's no way to determine the size of an array given just a pointer to it.
sizeof gives you the number of chars allocated to a while strlen gives you the length of useable string in a.
the \0 counts as part of the size in memory of the string, but the length of the string itself, given by strlen(), is only given by the characters before the \0 is encountered.
A character array declared like this:
char a[] = "Apple";
has, according to the language specification, a null-terminator. Therefore, the length of the array is 6. There are 5 characters, and then the null terminator.
On the other hand, strlen() returns the number of characters that precede the null terminator. Which is 5.
The sizeof operator yields the size (in bytes) of its operand.
In this statement
char a[] = "Apple";
array a is initialized by characters of string literal "Apple" that includes the terminating zero.
In fact this record is equivalent to
char a[] = { 'A', 'p', 'p', 'l', 'e', '\0'; };
So the size in bytes of a is equal to 6.
Standard C function strlen counts symbols in a string until it encounters the terminating zero. So
strlen( a )
will return 5 that is the number of characters in the array that are before the terminating zero.
Take into account that you could write for example
char a[100] = "Apple";
In this case sizeof( a ) will yield 100 because you explicitly specified the number of bytes that the array will occupy. However it was initialized only with 6 characters of the string literal. So how to find how many actual data are in the character array? For this purpose function strlen was introduced that to distinguish the size of a character array and the number of actual data in the character array.
Because in C there is no string type. String is a character array which is NULL terminated. strlen() counts the characters until the NULL character, whereas sizeof() actually returns the amount of memory used up by the charater array.
a is an array of chars, which contains 6 elements, hence sizeof returns 6 (the length of the string including zero termination).
s is an array of pointers to char. The pointer size is 4 bytes. sizeof(s[0]) returns the size of the first element, which is pointer, i.e. its size is 4.
When you define:
char a[] = "Apple";
It means an array of characters, which equals to the following definition:
char a[] = {'A', 'p', 'p', 'l', 'e', '\0'}; // '\0' is the string termination character which equals to 0
Since char type size is 1, the sizeof(a) returns 6 which is the size of the whole array.
Nevertheless, when you define:
char *s[] = {"Apple"};
It means an array of char pointer. Hence sizeof(s[0]) return the size of its first element which
equals to sizeof(char*).
For a 32-bit platform, sizeof(char*) = 4. If you do it on an 64-bit platform, 8 is the expected value.

int arrays in C/C++

i wonder about int array in c affect to memory.
for example we opened char array char array[10];
it wont open 10 it'll open 11 because of '\0'
is there same situation on int array?
when we declare int abc[10]; will it open array that is 10 int size or 11 like char?
Thanks...
You are wrong with regards to char array[10]. This will not declare an array of 11 elements, only 10, including the terminating '\0'. This means that if you put a string of ten characters in the array, it will overflow.
some_type name[10] will always declare an array of 10 elements, never more, never less.
Any array declaration will have x number of elements
type array[x]
not x+1.
not even the char one.
read here more about arrays:
http://www.cplusplus.com/doc/tutorial/arrays/
I think declaring char array[10] allocates exactly 10 bytes of space, it is your job to manage memory with '\0' if you see fit.
int abc[10] creates an array of 10 ints, with subscripts 0 through 9. Changing the type (e.g., to char abc[10] doesn't change the number of items in the array.
With an array of char, the NUL terminator is considered part of the string, so if you provide an initializer and specify a size, the size must be at least as large as the size of the string including the NUL terminator. If you don't specify the size, the size will be the length of the string including the NUL terminator.
char a[] = "A string"; // sizeof(a)==9
Note, however, that C is slightly different in this respect -- in C you can specify an initializer and a size that does not include space for the NUL terminator, and it'll still compile.
char a[9] = "A string"; // allowed in either C or C++
char a[8] = "A string"; // allowed in C, but not C++.
I'm not sure what you mean by "opened" an array. If you declare:
char array[10];
you define an array of ten char. If you declare:
int array[10];
you define an array of ten int. Both uninitialized unless defined
with static lifetime.
The appended '\0' only affects string literals and initialization
strings.
for example we opened char array char array[10]; it wont open 10 it ll open 11 because of '\0'
Wrong. In C, you are expected to take care of your terminating \0's in strings - the compiler won't do any favour for you. If you declare a char[10], you get exactly 10 chars, and the same is true for ints and all other types.
A char array[10] will create an array of 10 elements. I think you are a bit confused because in c typically you have to create an array of size 11 to store a word of size 10, because you need to have one extra element for the '\0' char in the end. But still you have to declare the array to be of size 11, not 10. The compiler will not do that for you.
I think you are somewhat confused about initializing an array of char in C++. char array[10] will have size 10, not size 11, however, char array[] = "1234567890"; will have size 11 because the initialization knows that your char array needs to end with a newline character.

c++ sizeof( string )

#include <cstdlib>
#include <iostream>
int main(int argc, char *argv[])
{
cout << "size of String " << sizeof( string );
system("PAUSE");
return EXIT_SUCCESS;
}
Output:
size of String = 4
Does that mean that, since sizeof(char) = 1 Byte (0 to 255), string can only hold 4 characters?
It isn't clear from your example what 'string' is. If you have:
#include <string>
using namespace std;
then string is std::string, and sizeof(std::string) gives you the size of the class instance and its data members, not the length of the string. To get that, use:
string s;
cout << s.size();
When string is defined as:
char *string;
sizeof(string) tells you the size of the pointer. 4 bytes (You're on a 32-bit machine.) You've allocated no memory yet to hold text. You want a 10-char string? string = malloc(10); Now string points to a 10-byte buffer you can put characters in.
sizeof(*string) will be 1. The size of what string is pointing to, a char.
If you instead did
char string[10];
sizeof(string) would be 10. It's a 10-char array.
sizeof(*string) would be 1 still.
It'd be worth looking up and understanding the __countof macro.
Update: oh, yeah, NOW include the headers :) 'string' is a class whose instances take up 4 bytes, that's all that means. Those 4 bytes could point to something far more useful, such as a memory area holding more than 4 characters.
You can do things like:
string s = "12345";
cout << "length of String " << s.length();
sizeof(char) is always 1 byte. A byte which we think is 8-bits need not be the case. There are architectures where a BYTE is 32-bits, 24-bits and so on. The sizeof applied to any other type is in multiples of sizeof(char) which is by definition 1.
The next important thing to note is that C++ has three character types: plain char, signed char and unsigned char. A plain char is either signed or unsigned. So it is wrong to assume that char can have only values from 0 to 255. This is true only when a char is 8-bits, and plain char is unsigned.
Having said, that assuming that 'string' is 'std::namespace', sizeof(string) == 4 means that the sizeof the 'std::string' class is 4 bytes. It occupies 4 times the number of bytes that a 'char' on that machine takes. Note that signed T, unsigned T always have the same size. It does not mean that the actual buffer of characters (which is called string in common parlance) is only 4 bytes. Inside the 'std::string' class, there is a non static member pointer which is allocated dynamically to hold the input buffer. This can have as many elements as the system allows (C++ places no restriction on this length). But since the 'std::string' class only holds the pointer to this potentially infite length buffer, the sizeof(std::string) always remains the same as sizeof pointer on the given architecture which on your system is 4.
I know a lot of people had answered your question, but here are some points:
It's not the size of the string or the capacity of the string, this value represents the structural size of the class string, which you can see by its implementation (and it can change from implementation to implementation) that is a simple pointer;
As the sizeof(string) is the size of the class structure, you'll get the size of the only internal pointer, that in your case is 4 bytes (because you are in a 32-bit machine, this can change from platform to platform too);
This pointer inside the string class, points to a memory buffer where the class will hold the real string data, this memory buffer is reallocated as needed, it can increase/decrease as you append/delete/create more string text;
If you want to get the real size of the string, you need to call the size() method from the class which will check the memory buffer string size (which isn't the same as the memory buffer size).
I think your problem is your conception of sizeof, see more information here and here is some explanation on how it works.
Not at all. It means that the class's structure is that, it doesn't include the dynamic memory it can control. std::string will expand dynamically to meet any required size.
s.max_size() // will give the true maximum size
s.capacity() // will tell you how much it can hold before resizing again
s.size() // tells you how much it currently holds
The 4 you get from sizeof is likely a pointer of some kind to the larger structure. Although some optimizations on some platforms will use it as the actual string data until it grows larger than can fit.
No, it means that the sizeof the class string is 4.
It does not mean that a string can be contained in 4 bytes of memory. Not at all. But you have to difference between dynamic memory, used to contain the size characters a string can be made of, and the memory occupied by the address of the first of those characters
Try to see it like this:
contents --------> |h|e|l|l|o| |w|o|r|ld|\0|
sizeof 4 refers to the memory occupied by contents. What it contents? Just a pointer to (the address of ) the first character in the char array.
How many characters does a string can contain ? Ideally, a character per byte available in memory.
How many characters does a string actually have? Well, theres a member function called size() that will tell you just that
size_type size() const
See more on the SGI page !
A string object contains a pointer to a buffer on the heap that contains the actual string data. (It can also contain other implementation-specific meta-information, but yours apparently doesn't.) So you're getting the size of that pointer, not the size of the array it points to.
you can also use strings and can find out its length by string.length() function. look at the below code:
// Finding length of a string in C++
#include<iostream>
#include<string>
using namespace std;
int count(string);
int main()
{
string str;
cout << "Enter a string: ";
getline(cin,str);
cout << "\nString: " << str << endl;
cout << count(str) << endl;
return 0;
}
int count(string s){
if(s == "")
return 0;
if(s.length() == 1)
return 1;
else
return (s.length());
}
you can get the details from :
http://www.programmingtunes.com/finding-length-of-a-string-in-c/
size() of string gives the number of elements in the string whereas sizeof() function on a string gives three extra bits. strlen() of a character array gives the number of elements + 1 (because of null char delimiter) and keep in mind size of char is 1 byte. sizeof() on a char array gives the size assigned to the array
string str="hello";
char arr[x]="hello";
cout<<str.size()<<endl<<sizeof(str)<<endl;
cout<<strlen(arr)<<endl<<sizeof(arr)<<endl;
output is 5 8 5 x