473,395 Members | 1,574 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,395 software developers and data experts.

Is there a difference between char* and char [], where/how are they created in memory

In the following code snippet, I created a class samp which has two private variables /char[80]/ and /char*/ which are initialized in the constructor. I create a function /samp input()/ that returns an object of this class and see that the object is deleted after returning from the function. However, I note that unless I write my own destructor, the object is not being deleted even it is out of scope. I also have a global variable samp* GlobSampObj; which I use to look at the contents of the temporary object created in /samp input()/ function outside the function in main. Finally, only /char* / variable alone is destroyed. So where and how are these both variables created in the memory, char s[80]; char* p; and how are they destroyed in the memory?

Expand|Select|Wrap|Line Numbers
  1. #include<iostream>
  2. using namespace std;
  3.  
  4. class samp
  5. {
  6.      char s[80];
  7.      char* p;
  8. public:
  9.      void show(){cout << "s:" << s << " p:" << p << endl;}
  10.      void set(char *str)
  11.      {
  12.           strcpy(s,str);
  13.           cout << "address location of s:" << (int *)s << endl;
  14.           p = new char[strlen(str)+1];
  15.           strcpy(p,str);
  16.      }
  17.      // if you write your own destructor it will be called the moment the obj
  18.      // goes out of scope
  19.      ~samp() // unless you write a destructor the memory wont be erased 
  20.      {
  21.           cout << "Destructor called " << endl;
  22.           delete(s); // does not get deleted? how can I delete this
  23.           delete(p);
  24.      }
  25. };
  26.  
  27. samp* GlobSampObj;
  28.  
  29. void show(samp obj)
  30. {
  31.  obj.show();
  32.  cout << endl;
  33. }
  34.  
  35. // returns an obj of type class samp
  36. samp input()
  37. {
  38.      char p[80];
  39.      // char pointer to a const location
  40.  
  41.      samp str;
  42.      cout << "Enter a string" << endl;
  43.      cin >> p;
  44.      str.set(p);
  45.  
  46.      //addStore = (reinterpret_cast<int *>(&str));
  47.      //cout << "addStore: " << addStore << " *addStore: " << *addStore << endl;
  48.  
  49.      GlobSampObj = &str;
  50.      cout << "GlobSampObj: " << GlobSampObj << " GlobSampObj->show(): " << endl;
  51.      GlobSampObj->show();
  52.      cout << endl;
  53.  
  54.      cout << "object str will be deleted after returning the value" 
  55.           << "as a destructor is written" << endl;
  56.      return str;
  57.      // object destructor will be called now
  58. }
  59.  
  60. int main()
  61. {
  62.      samp s;
  63.      s = input();
  64.      // works fine although the object is deleted once the value has been returned 
  65.      s.show(); // shows correct value
  66.  
  67.      // show(s);
  68.      // even a function like this which makes a copy of the str obj 
  69.      // can delete the object after exiting the show()
  70.      // that is why you need to write a copy constructor
  71.  
  72.  
  73.      // cout << "addStore: " << addStore << " *addStore: " << *addStore << endl;
  74.      cout << "GlobSampObj: " << GlobSampObj << " GlobSampObj->show(): " << endl;
  75.      GlobSampObj->show();
  76.      cout << endl;
  77.  
  78.      //cout << "after calling show() the obj must be deleted" << endl;
  79.      //s.show();
  80.  
  81.      system("pause");
  82.      return 0;
  83. }
Expand|Select|Wrap|Line Numbers
  1. Output:
  2. Enter a string
  3. hellothere
  4. address location of s:0x22feb8
  5. GlobSampObj: 0x22feb8 GlobSampObj->show():
  6. s:hellothere p:hellothere
  7.  
  8. object str will be deleted after returning the valueas a destructor is written
  9. Destructor called
  10. s:hellothere p:
  11. s:hellothere p:
  12.  
  13. Destructor called
  14. GlobSampObj: 0x22feb8 GlobSampObj->show():
  15. s:hellothere p:╚$=
Press any key to continue . . .
Oct 6 '07 #1
7 2660
weaknessforcats
9,208 Expert Mod 8TB
The rules for deleting are simple: If you allocated it, then you have to delete it.

In your case the member variable p is allocated in samp::set() using the new operator.
Bug 1: p may already be in use. You need to delete it before you
overstore the contents with a new address
Bug 2: samp has no constructors. That means p is indeterminate. That
means if you delete it samp::set() you will crash.

Rule: Make sure all of your member variables have correct
contents before the constructor is completed.

Deleteing p in samp::~samp() is correct.
Bug 3: deleting samp::s will crash the program. samp::s was not
allocated using the new operator

Any variables allocated by the compiler will be deleted by the compiler, and that includes samp::s. You don't see it deleted since that's none of your business.

Rule: Destructors do not destory objects.

The compiler destroyes the object and as a courtesy will call your destructor if there is one. After that call, the destructor on all of your data members will be called and after that the object is deleted from memory.

Rule: Constructors do not create objects.

The compiler creates objects and as a courtesy calls the constructor on each of your data members and then calls your constructor for any last-minute initializations.

Not shown is assigning one samp object to another. Here a copy constructor is used, but there is none, so the compiler uses its own which calls the copy constructor on each data member. char and char* have no copy constructors so they are just copied. Now your original samp object has the same pointer as the as the copy.

Bug 4: samp::p for the target was not deleted before the assignment.
Memory leak.
Bug 5: samp::p was for the target does not contain a copy of samp::p
of the original. This a bug for HAS-A classes.

Bug 6: If samp implements an ASSOCIATES-A relationship with other
samp objects, the samp::p can be deleted only iof this is the
last samp object in existence.

You need:
1) to write constructors
2) to write an assignment operator
3) resolve the data model for Bug 5 and Bug 6. If it's ASSOCIATES-A, then you need to use a handle rather than a pointer.
Oct 6 '07 #2
Thank you for your comments, unfortunately I am just a beginner and still hooked at finding the difference between char* and char [].

I am confused about how they can be initialized and copied. I cannot understand how to find the size occupied either and where and how they are created in the memory like the types of heap, stack, what are these anyways? Please shed some light on the following before we discuss your comments??

char str[20];
char* strPtr = new char[20];

sizeof(str) gives 20
sizeof(stPtr) gives 4, makes sense as it is giving the size of the address probably stored in an int, but how can we find its size before copying or concatenating or assigning a new string to strPtr????

char str[20];
str = "Hello"; // fails ???

How are the char[] and char * defined in the memory and could anyone please shed some light on this please!!!
Oct 7 '07 #3
weaknessforcats
9,208 Expert Mod 8TB
Thank you for your comments, unfortunately I am just a beginner and still hooked at finding the difference between char* and char [].
A char* is a pointer to a character. char[] won't compile. The brackets are used to indicate an array an you put the number of elements between the brackets:
Expand|Select|Wrap|Line Numbers
  1. char array[6];      //array of 6 char
  2.  
You are allowed to let the compiler determine the number of elements based on how you initialize the array:
Expand|Select|Wrap|Line Numbers
  1. char array[] = "Hello";      //array of 6 char containing Hello+null terminator
  2.  
But:
Expand|Select|Wrap|Line Numbers
  1. char array[];
  2.  
won't compile because the number of elements can't be determined.

Now you can do this:
Expand|Select|Wrap|Line Numbers
  1. void fx(char arg[])
  2. {
  3.  
  4. }
  5.  
Here arg is an argument that is an array of char. To understand how this works you need to burn into your skull: The name of the array is the address of element 0.

That means in the above examples array is the address of array[0]. Since array[0] is a char, that makes array the address of a char. That is a char*.

You can use array anywhere as a char*.

In the case of the function call above, char arg[] is identical to coding char* arg. You call the function by passing in the address of element 0:
Expand|Select|Wrap|Line Numbers
  1. fx(array);
  2.  
char str[20];
char* strPtr = new char[20];

sizeof(str) gives 20
sizeof(stPtr) gives 4, makes sense as it is giving the size of the address probably stored in an int, but how can we find its size before copying or concatenating or assigning a new string to strPtr????
sizeof(stPtr) is the size of the pointer. When you pass the str[20] array to that function:
Expand|Select|Wrap|Line Numbers
  1. fx(str);
  2.  
and do the sizeof(arg) inside the function you will get 4 again. The sisof the address. In general, you cannot use sizeof to determine the size of an array. Customaril, you keep the number of elements in another variable and pass it along with the array address to your function:
Expand|Select|Wrap|Line Numbers
  1. void fx(char arg[], int numelements)
  2. {
  3.  
  4. }
  5.  
char str[20];
str = "Hello"; // fails ???
Remember, str is the address of str[0]. By assigning "Hello" to str you are assigning the address of the H as the arddress of str[0]. That is, you are attempting to chnage the address of the local variable. That you cannot do.

What you want to do is copy Hello into the array. You use a function for that:
Expand|Select|Wrap|Line Numbers
  1. strcpy(str, "Hello");
  2.  
In C++ you do not use char arrays for strings. Instead you use string objects:
Expand|Select|Wrap|Line Numbers
  1. string str;
  2. str = "Hello"; //OK
  3.  
The assgnment operator for the string object has been programmed to do the work of strcpy in C.
Oct 7 '07 #4
Thank you,

I also noticed that when I create ch[] = "Hello" or ch[20] = "Hi;
sizeof actually gives me the size occupied in the memory correctly and strlen gives me the length of the string until I reach the '\0' character. When I create char * I am unable to get the sizeof, I learnt that we can get the address location, atleast print it by using (int *)ch where ch is char[] or char*. Is there a way

1) to get the sizeof the character array by doing (int*)(&ch[strlen(ch)]) - (int*)(&ch[0]) or any other way. How else can we justify if the user has input more characters than is assigned for the char[20] or char* ch = new char[20] ???

What is buffer overflow and memory leakage in strings or arrays and how can we test or stop them from happening??
Oct 7 '07 #5
jthep
34
A stack is a storage space (data structure) that stores data like variables. When you make a variable, it goes into a stack like below.

-------------------
|5|'c'| | | | | | | |
-------------------
int a | char c| ....... etc

Each slot has an address of where it is on the stack....lets pick a number and say 10002 is the address for int a that stores 5. The size of a data type matters because it determines the address of the next slot. So lets say an integer is 4 bytes, so the next available slot is 10006 which is the address for char c that stores 'c' and so on and so on.

Think of a pile of dirty cafeteria plates, you start cleaning at the very top of the pile, then as more dirty plates become available, they are place at the top of the stack and you keep taking one plate at a time from the top to wash. A stack is like a stack of dirty cafeteria plates. Everytime to store a data, it is put on top of the stack and when a data is deleted the data at the top is deleted first.

My professor is constantly drilling us on how pointers and arrays are stored in a stack. If you define an array of chars with size 4 and a char is 1 byte, then think of it as making a one big box on the stack with 4 slots in it. The value stored in the one big box as a whole is the address of the array (equivalent to the address of the first element in the array[0]) The value that's stored in that box is unchangable:
0123
--------
| | | | |
------------------
|8100| | | | | |
------------------
array

In the above, the address of array/array[0] is lets say an arbitrary address 8100 and it is stored in a box on the stack. It might be confusing but think of that big box like it is detached from the stack. It's on the stack but because the value in that box is unchangable, think of it floating somewhere in outter space where it is unreachable. You can have access/change the values inside the address of the array, but not the address of the array.

A pointer is a little different, see below for pa:
0123
--------
| | | | |
-----------------------
|8100|8100| | | | |
-----------------------
array | pa

So you define a pointer pa right after you make an array. The address of the pointer is going to be 8104 since the array takes up 4 bytes. A pointer stores an address (type of address depends on the data type defined with the pointer - in your case a char *pa) just like the space that was allocated for the array does. The only difference, the address is changable. Just remember three things...

1. when declaring a variable, the ' * ' before the variable name specifies a pointer.

Then after declaring it, if I remember correct (someone correct me if im wrong),

2. pa = go to the address whose value is in pa
3. *pa = the value in the address whose value is in pa.

If you pass an array as an argument into a function, it is considered as a pointer because you are passing the value of the array which is an address. Thats why, when you do sizeof on an array that's passed into a function, you don't get the number of index/size of the array.

The variables are automatically taken out of the stack when you exit the function where it is declared in. As explained in the begining that the stack is like a pile of dirty cafeteria plates, pa will be deleted first then array. Below array and pa are removed, the next variable will start at location 8100.

0123
--------
| | | | |
-----------------------
|8100|8100| | | | |
-----------------------

However, even though array and pa are removed from the stack, the values that are still stored in the stack, it's just that you dont have access to it unless you have the address of where it is stored in the stack to access it (which you're not supposed to)...that is one flaw in C.

Stack overflow is like your index array out of bounds in java. The only thing is that C ignores the error and keeps storing pass the size of the buffer. For example, you declare an array of char with 3 slots and another array right after also of char with 4 slots. if you do a while loop to add characters say 'a', 'r', 'r', 'a', 'y', arr will be stored in the first array, but since you are looping to put all the characters of 'array' in, you will write the remaining characters into the next array. So first array will have 'a', 'r', 'r' and second array will have 'a', 'y', '\0'

Sorry couldnt make the slots any bigger. =(
Oct 7 '07 #6
thanks a lot jthep,

from what I understand from yours, all of the const variables (such as char a[] = "Hello" and int a[] = {1,2,3,4} ) and non-const variables (such as char* p = a) are created in the stack. whereas all the variables created using new and global are created in the heap.

while int a[] = {1,2,3,4} are stored contiguously meaning a or &a[0] followed by the rest of the elements such that the address pointed by \a\ can no longer be changed, in int* aPtr the address pointed by aPtr can be changed.

What about when we move from one function to the other, I faintly remember they are pushed from somewhere to somewhere and so on.

How can we find the size of a char* a = new char[20]; that we pass to another function so that we make sure we do not go beyond 19 characters leaving 20th for '\0'

You also said that in C++ (also??) when you create two char arrays (not dynamic) char a[3] and b[3] then do strcpy(a,"Hello"); the a[3] contains H , e, l and b[3] contains l, o, '\0' I believe..

what are stack overflows and buffer overflows and how to set array out of index and so on when creating and assigning static and dynamic arrays???

please correct me if I am wrong anywhere ...
Oct 8 '07 #7
jthep
34
thanks a lot jthep,

from what I understand from yours, all of the const variables (such as char a[] = "Hello" and int a[] = {1,2,3,4} ) and non-const variables (such as char* p = a) are created in the stack. whereas all the variables created using new and global are created in the heap.

while int a[] = {1,2,3,4} are stored contiguously meaning a or &a[0] followed by the rest of the elements such that the address pointed by \a\ can no longer be changed, in int* aPtr the address pointed by aPtr can be changed.

What about when we move from one function to the other, I faintly remember they are pushed from somewhere to somewhere and so on.

How can we find the size of a char* a = new char[20]; that we pass to another function so that we make sure we do not go beyond 19 characters leaving 20th for '\0'

You also said that in C++ (also??) when you create two char arrays (not dynamic) char a[3] and b[3] then do strcpy(a,"Hello"); the a[3] contains H , e, l and b[3] contains l, o, '\0' I believe..

what are stack overflows and buffer overflows and how to set array out of index and so on when creating and assigning static and dynamic arrays???

please correct me if I am wrong anywhere ...
As far as I know, as soon as you pass an array into a function, it will automatically become a pointer within that function. So if you try to do a sizeof after it has been passed through the function, it will not give you the number of elements in the array but the size of the pointer. Why not just keep track of the size of the array outside the function? You do a sizeof to get the size of the array before you pass the array in a function. Then just pass in the size of the array along with it.

Not sure with C++, but in C, the sizeof operater is implemented as sizeof(array)/sizeof(*array) to find the number of elements in an array.
Oct 8 '07 #8

Sign in to post your reply or Sign up for a free account.

Similar topics

7
by: wwj | last post by:
Hi ,all I want to know the difference between char a and char *p=new char and the difference between the heap and the stack ,and if the char a is corresponding to the stack in MEMORY,and char...
7
by: Paul | last post by:
Say I have: char foo; char** bar; In my understanding, these two have the same meaning in memory. Could someone elucidate upon these two types and their meanings? Thanks, Paul
24
by: wwj | last post by:
Hi ,all I want to know the difference between char a and char *p=new char and the difference between the heap and the stack ,and if the char a is corresponding to the stack in MEMORY,and char...
11
by: J Wang | last post by:
dear, I debug the program recently as follows. #include <sys/stat.h> int main(int argc, char *argv) { struct stat buf;
5
by: jab3 | last post by:
(again :)) Hello everyone. I'll ask this even at risk of being accused of not researching adequately. My question (before longer reasoning) is: How does declaring (or defining, whatever) a...
4
by: ravinderthakur | last post by:
hi all experts, can anybody explain me the difference between the unsigned char and char in c/c++ langugage. specifically how does this affects the c library fucntion such as strcat,strtok...
14
by: Imran | last post by:
hello all I am bit confused with int and long data type. I read in some book that, int cal hold 2^16 values where in long can hold 2^32. and both data types are 4 bytes long. My doubt...
6
by: mthread | last post by:
Hi, I am learning C++ and I have been told that an object can be created either by using calloc or new. If it is true, can some one tell me what is the difference b/w using these two function...
13
by: manish sahu | last post by:
difference between calloc() and malloc()
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.