C style char arrays - How many bytes do we store? - c++

char firstName[32];
I understand that each char occupies 1 byte in memory. So does the above occupy 32 bytes of memory?
Am I missing a pointer that takes up memory too or is this just 32 bytes?

No, that takes up exactly 32 bytes of memory.
There is no pointer.
This is often an area of confusion, since an array name silently "decays" to a "char*"
char* fname = firstName;
So, firstName may be of type const char*, but it is not itself a char* variable. It is exactly like:
int x = 5;
x is int variable and takes up space. 5 on the other hand, is just a constant value of int type. It takes of no space; it's just a value.

It occupies exactly 32 bytes of memory.Internally everything an address.Variables are only for our understanding.

This is just 32 bytes. The name of the array sometimes acts like a pointer to the first element, but it is not a pointer.

That takes up 32 bytes. It will hold a 31-character string (the other byte is for the null string terminator).

The statement char firstName[32] creates an array of 32 characters, or 32 bytes, on the stack. Because it's on the stack, the compiler knows exactly where it is in relation to the stack pointer. The compiler will hardcode the address of the array into any operations that use it; there's no need for storing a pointer to it.
It's important to note that if you attempt to pass this array as a function argument, it will degrade into a pointer to the array, because C++ doesn't allow passing primitive arrays by value. Most people who are new to C++ would expect it to pass a copy of the array.

There are two ways to go when you need, e.g. 32 bytes, to store your data. The difference in these two versions:
// version 1
char *firstName = new char[32];
// version 2
char firstName[32];
is that for version 1 the space your data allocated on the heap and you have to free before the program ends, whereas in version 2 the space is on the stack. Both will give you a variable that points to the first byte of your available space and this space is 32 bytes in both cases. People will argue that there are reasons why you might want to choose one over the other, but that is a different story.
sizeof( firstName )
The interesting point is what sizeof would return and this is the size of a char pointer (depends on your system and compiler) for version 1 and 32 for version 2. Keep in mind what another user mentioned, passing firstName to a function degrades it into a pointer.

Complementing the answers above:
A pointer to char occupies 4 bytes in the 32-bit architecture, whereas in the 64-bit architecture it occupies 8. In the example, it occupies 4.
#include <stdio.h>
#include <stdlib.h>
#define SIZE 32
int main()
{
char array[SIZE];
char *ptr = (char*)array;
printf("\nsize of array: %i bytes", sizeof(array));
printf("\nsize of pointer: %i bytes", sizeof(ptr));
printf("\naddress array on the stack: %p", &array);
printf("\naddress reference: %p", ptr);
printf("\naddress pointer to array on the stack: %p", &ptr);
/*
1 char ----- 1 byte
32 characters ---- 32 bytes
*/
return 0;
}
We can also allocate space in the heap for the 32-byte array:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 32
int main()
{
char array[SIZE];
char *malloc_pointer = (char*)malloc(sizeof(array)); // a pointer on stack pointing out 32 bytes on heap
printf("\naddress malloc_pointer on the stack: %p", &malloc_pointer);
printf("\nsize of pointer to heap: %i bytes", sizeof(malloc_pointer));
free(malloc_pointer); // clean
return 0;
}

In the debug version there are also bytes stored beyond the array (on some compilers) to check for writing after the array. In the release version it should be 32 bytes plus one int on the stack (probably) to store the address.

Related

C++ calculate size of array of strings from file [duplicate]

#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

C++ pointer to char

#include<iostream>
namespace std;
void main(){
char *ch;
char nch;
cout<<"\n"<<sizeof(ch);
cout<<\n"<<sizeof(nch);
cout<<"\n";
return 0;
}
This program would print the output as:
8
1
Why does the size of char type change when it is a pointer?
Pointers are not the data they're pointing to and char * is not the same type as char.
Most pointers have the same size and it's generally machine architecture dependent, in your case it happend to be 8 bytes, so you pretty much can expect something among the lines:
int* pInt;
char* pChar;
std::cout << (sizeof(pInt) == sizeof(pChar)); // prints 1 for true
On the other hand sizeof(char) is guaranteed to return 1. But this still doesn't guarantee the ammount of actual memory used to store it, funny enough.
If you want to get the size of actual data pointed to by the pointer you, of course, can dereference it:
std::cout << sizeof(*ch); // prints 8
Pointer to char is not a char, it is a pointer. Size of a pointer does not depend on the size of the object it points to. Because pointer is basically an address of the first byte of the object.
sizeof *ch
The catch is that ch is a pointer to char, so ch is not a char. It just stores an address. For storing an address, it needs some space and in many systems, that happen to be 8 bytes
sizeof(nch)
prints the size of char type in a system and it is 1 byte.
It doesn't, but the size of a pointer may be different than the size of a character. If you change your code from sizeof(ch) to sizeof(*ch), then you'll get 1 1.

Char * Array Memory Allocation in C++

Lets say below is my char pointer array:
char *names[4] = {"abc", "def", "ghi", "jkl"};
for(int i = 0; i < 4; i++){
cout << &names[i] << endl;
}
This will print 4 memory allocations:
0x7fff591c9b90
0x7fff591c9b98
0x7fff591c9ba0
0x7fff591c9ba8
My Question is why is it allocating 8 bytes for each element in the array? Can you help me in understanding how memory is allocated for each data type in C++? like for Char *, char, in, int *, string, etc., or quote any reference.
TIA
My Question is why is it allocating 8 bytes for each element in the
array?
Well probably because size of pointer on your machine is 8 bytes. It is common that size of pointer is 8 bytes on 64 bit systems. But again there is no hard rule for this and size of pointers may vary per machine. And since each element of your array is a pointer, hence the result.
Memory allocation say for int is different from int* in that in the former you need to allocate space which will hold all values of integer, while in the latter, you need as much space to contain value of a pointer.
A string literal is an array of read-only char elements, terminated by the special character'\0'. When you use a string literal it decays to a pointer to the first element in that array. So making an array of four pointers to char will always have the element size be the size of a pointer, even if that pointer is to a string literal.
On 64 bit systems the usual size of a pointer is 64 bits, i.e. 8 bytes. That's why each element in the array is 8 bytes. On a 32 bit system, the size of pointers are of course 32 bits, 4 bytes.
The length of the string literals doesn't matter, for example take
char const* string_array[] = { "a", "bc", "def", "ghij" };
In the above array the element size will still be the size of the pointer, i.e. 8 bytes on a 64 bit system.

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

Difference between using character pointers and character arrays

Basic question.
char new_str[]="";
char * newstr;
If I have to concatenate some data into it or use string functions like strcat/substr/strcpy, what's the difference between the two?
I understand I have to allocate memory to the char * approach (Line #2). I'm not really sure how though.
And const char * and string literals are the same?
I need to know more on this. Can someone point to some nice exhaustive content/material?
The excellent source to clear up the confusion is Peter Van der Linden, Expert C Programming, Deep C secrets - that arrays and pointers are not the same is how they are addressed in memory.
With an array, char new_str[]; the compiler has given the new_str a memory address that is known at both compilation and runtime, e.g. 0x1234, hence the indexing of the new_str is simple by using []. For example new_str[4], at runtime, the code picks the address of where new_str resides in, e.g. 0x1234 (that is the address in physical memory). by adding the index specifier [4] to it, 0x1234 + 0x4, the value can then be retrieved.
Whereas, with a pointer, the compiler gives the symbol char *newstr an address e.g. 0x9876, but at runtime, that address used, is an indirect addressing scheme. Supposing that newstr was malloc'd newstr = malloc(10);, what is happening is that, everytime a reference in the code is made to use newstr, since the address of newstr is known by the compiler i.e. 0x9876, but what is newstr pointing to is variable. At runtime, the code fetches data from physical memory 0x9876 (i.e. newstr), but at that address is, another memory address (since we malloc'd it), e.g 0x8765 it is here, the code fetches the data from that memory address that malloc assigned to newstr, i.e. 0x8765.
The char new_str[] and char *newstr are used interchangeably, since an zeroth element index of the array decays into a pointer and that explains why you could newstr[5] or *(newstr + 5) Notice how the pointer expression is used even though we have declared char *newstr, hence *(new_str + 1) = *newstr; OR *(new_str + 1) = newstr[1];
In summary, the real difference between the two is how they are accessed in memory.
Get the book and read it and live it and breathe it. Its a brilliant book! :)
Please go through this article below:
Also see in case of array of char like in your case, char new_str[] then the new_str will always point to the base of the array. The pointer in itself can't be incremented. Yes you can use subscripts to access the next char in array eg: new_str[3];
But in case of pointer to char, the pointer can be incremented new_str++ to fetch you the next character in the array.
Also I would suggest this article for more clarity.
This is a character array:
char buf [1000];
So, for example, this makes no sense:
buf = &some_other_buf;
This is because buf, though it has characteristics of type pointer, it is already pointing to the only place that makes sense for it.
char *ptr;
On the other hand, ptr is only a pointer, and may point somewhere. Most often, it's something like this:
ptr = buf; // #1: point to the beginning of buf, same as &buf[0]
or maybe this:
ptr = malloc (1000); // #2: allocate heap and point to it
or:
ptr = "abcdefghijklmn"; // #3: string constant
For all of these, *ptr can be written to—except the third case where some compiling environment define string constants to be unwritable.
*ptr++ = 'h'; // writes into #1: buf[0], #2: first byte of heap, or
// #3 overwrites "a"
strcpy (ptr, "ello"); // finishes writing hello and adds a NUL
The difference is that one is a pointer, the other is an array. You can, for instance, sizeof() array. You may be interested in peeking here
If you're using C++ as your tags indicate, you really should be using the C++ strings, not the C char arrays.
The string type makes manipulating strings a lot easier.
If you're stuck with char arrays for some reason, the line:
char new_str[] = "";
allocates 1 byte of space and puts a null terminator character into it. It's subtly different from:
char *new_str = "";
since that may give you a reference to non-writable memory. The statement:
char *new_str;
on its own gives you a pointer but nothing that it points to. It can also have a random value if it's local to a function.
What people tend to do (in C rather than C++) is to do something like:
char *new_str = malloc (100); // (remember that this has to be freed) or
char new_str[100];
to get enough space.
If you use the str... functions, you're basically responsible for ensuring that you have enough space in the char array, lest you get all sorts of weird and wonderful practice at debugging code. If you use real C++ strings, a lot of the grunt work is done for you.
The type of the first is char[1], the second is char *. Different types.
Allocate memory for the latter with malloc in C, or new in C++.
char foo[] = "Bar"; // Allocates 4 bytes and fills them with
// 'B', 'a', 'r', '\0'.
The size here is implied from the initializer string.
The contents of foo are mutable. You can change foo[i] for example where i = 0..3.
OTOH if you do:
char *foo = "Bar";
The compiler now allocates a static string "Bar" in readonly memory and cannot be modified.
foo[i] = 'X'; // is now undefined.
char new_str[]="abcd";
This specifies an array of characters (a string) of size 5 bytes (one byte for each character plus one for the null terminator). So it stores the string 'abcd' in memory and we can access this string using the variable new_str.
char *new_str="abcd";
This specifies a string 'abcd' is stored somewhere in the memory and the pointer new_str points to the first character of that string.
To differentiate them in the memory allocation side:
// With char array, "hello" is allocated on stack
char s[] = "hello";
// With char pointer, "hello" is stored in the read-only data segment in C++'s memory layout.
char *s = "hello";
// To allocate a string on heap, malloc 6 bytes, due to a NUL byte in the end
char *s = malloc(6);
s = "hello";
If you're in c++ why not use std::string for all your string needs? Especially anything dealing with concatenation. This will save you from a lot of problems.