I have the following pointer.
char **x = NULL;
x is will point to an array of pointers. So is the following code correct?
x = new (nothrow) (*char)[20];
and we will dealocate it using
delete[] x;
Is
x = (char **) malloc(sizeof(char **) * 20);
and
x = new (nothrow) (*char)[20];
equivalent?
Apart from the pointer-syntax mentioned by unwind, it is equivalent: an array of 20 char* will be allocated and deleted in both cases.
C++-adept warning: use std::vector< std::string > instead :) No memory management needed.
No, that code has syntax errors. The asterisk goes after the type name, to form a pointer to that type. So it's:
char*
not:
*char
It's weird that you have this right in the "C-style" example using malloc(), but not in C++.
As many commenters have kindly enough pointed out, there are other issues with the malloc() and its use of sizeof, though. But at least it got the type name right. Personally I'm against repeating type names in malloc() calls if at all possible, so I would write that version like this, to allocate a dynamic array of 20 character pointers:
char **x;
x = malloc(20 * sizeof *x);
This way:
Should be read as "20 times the size of whatever x points at", i.e. 20 times the size of a single char * pointer.
Contains the magical constant 20 in one place only.
Doesn't repeat any part of the type, if you were to change to wchar_t **x this would still work, and not by chance.
Is written in C, since I felt that is more natural when discussing malloc(). In C++, you need to cast the return value. In C, you should never do that.
New was introduced in C++. Malloc is C.
You shouldnt mix and match them... i.e. dont use delete on something you have used malloc on. Check this article.
I'd question why you are allocating such a thing in the first place. In C++, a std::vector of std::string is much more likely to be what you need.
Related
I am new to C++ and trying to convert string into integer. I was using atoi but there are some restrictions so I start using strtol which works perfectly. However, I would like to learn more on *temp and &temp (I have google and learn that it is a temporary space for storage) but would like to learn the difference and when to use which.
char *temp;
int m = strtol (argv[1],&temp,10);
if (*temp != '\0')
*temp is a pointer to a variable named temp and &temp takes the address of that variable
First of all jessycaaaa welcome to Stackoverflow.
I am new to C++ and trying to convert string into integer.
For me this looks like plain C-code. You can compile this with a C++ compiler though.
I was using atoi but there are some restrictions so I start using strtol which works perfectly.
Since you get an undefined behavior using atoi when argv[1] contains something different than a number, strtol is an approach to go for. If you share us a bit more code, we would help you better on your questions.
However, I would like to learn more on *temp and &temp (I have google and learn that it is a temporary space for storage) but would like to learn the difference and when to use which.
First of all you have to distinguish between use and declaration
char *temp;
Here you declare (*-symbol in declaration) a pointer named temp of type char. A pointer is a variable which stores the memory address (where it is pointing to). Here you did not define an address so it most likely will point a random space, but then
int m = strtol (argv[1],&temp,10);
you pass the address of the pointer (&-symbol, use-case, address-of operator) to strtol, so you get an address pointing to the part of the argv[1] where the number literals end, that is all fine. The function also returns the numerical value of the read string as long and is converted to an int.
if (*temp != '\0')
Here you access the value of what the address is pointing to (*-symbol, use-case, dereference operator). \0 is normally set as indication for a null-terminated string. So you are asking if the previously read end part has the null-termination character.
You know what: in C++ there are more elegant ways to accomplish that using stringstreams:
std::stringstream
Just an idea if you don't want to handle too much string manipulation in C and annoyances with pointers.
Also I would read a good book about C (not C++). C++ has also the references don't get confused by those. If you dominate the pointer-concept of C, I'm pretty sure everything else will be very clear for you.
Best regards
* and & are one of the first hurdles that programmers new to C and C++ have to take.
To really understand these concepts, it helps to know a bit more about how memory works in these languages.
First of all: C++ is just C but with classes and many other additional features. Almost all C programs are valid C++ programs. C++ even started out as a language that was compiled to C first.
Memory is, roughly speaking, divided in two parts, a 'stack' and a 'heap'. There are also other places for the code itself and compile-time constants (and maybe a few more) et cetera but that doesn't matter for now. Variables declared within a function always live on the stack. Let's see this in action with a simple example and analyse how memory is organized to build a mental model.
#include <iostream>
void MyFunction() {
int intOnStack = 5;
int* intPtrOnStack = new int(6); // This int pointer points to an int on the heap
std::cout << intOnStack << *intPtrOnStack;
delete intPtrOnStack;
}
int main() { MyFunction(); }
This program prints 56 when executed. So what happens when MyFunction() gets called? First, a part of the stack is reserved for this function to work with. When the variable intOnStack is declared within the function, it is placed in this part of the stack and it is initialized with (filled with) the int value 5.
Next, the variable intPtrOnStack is declared. intPtrOnStack is of type int*. int*'s point to int's by containing their memory-address. So an int* is placed on the stack and it is initialized with the value that results from the expression new int(6). This expression creates a new int on the heap and returns the memory-address of this int (an int*) to it. So that means that intPtrOnStack now points to the int on the heap. Though the pointer itself lives on the stack.
The heap is a part of memory that is 'shared' by all functions and objects within the program. The stack isn't. Every function has its own part of the stack and when the function ends, its part of the stack is deallocated.
So int*'s are just memory-addresses of int's. It doesn't matter where the int lives. int*'s can also point to int's on the stack:
#include <iostream>
void MyFunction() {
int intOnStack = 5;
int* intPtrOnStack = &intOnStack; // This int pointer points to intOnStack
std::cout << intOnStack << *intPtrOnStack;
}
int main() { MyFunction(); }
This prints 55. In this example we also see the &-operator in action (there are several uses of & like the bit-wise-and, I'm not going into them).
& simply returns the memory-address (a pointer!) of its operand. In this case its operand is intOnStack so it returns its memory-address and assigns it to intPtrOnStack.
So far, we've seen only int* as types of pointers but there exist pointer-types for each type of object that has a memory-address, including pointers. That means that a thing like int** exists and simply means 'pointer to a pointer to an int'. How would you get one? Like this: &intPtrOnStack.
Can pointers only live on the stack? No: new int*(&intPtrOnStack). Or new int*(new int(5)).
consider this code:
double *pi;
double j;
pi = &j;
pi[3] = 5;
I don't understand how is that possible that I can perform the last line here.
I set pi to the reference of j, which is a double variable, and not a double [] variable. so how is this possible that I can perform an array commands on it?
consider this code:
char *c = "abcdefg";
std::cout << &(c[3]) << endl;
the output is "defg". I expected that I will get a reference output because I used &, but instead I got the value of the char * from the cell position to the end. why is that?
You have two separate questions here.
A pointer is sometimes used to point to an array or buffer in memory. Therefore it supports the [] syntax. In this case, using pi[x] where x is not 0 is invalid as you are not pointing to an array or buffer.
Streams have an overload for char pointers to treat them as a C-style string, and not output their address. That is what is happening in your second case. Try std::cout << static_cast<const void *>(&(c[3])) << endl;
Pointers and arrays go hand in hand in C (sort of...)
pi[3] is the same as *(pi + 3). In your code however this leads to Undefined Behavior as you create a pointer outside an object bounds.
Also be careful as * and & are different operators depending on in which kind of expression the appear.
That is undefined behavior. C++ allows you to do things you ought not to.
There are special rules for char*, because it is often used as the beginning of a string. If pass a char* to cout, it will print whatever that points to as characters, and stop when it reaches a '\0'.
Ok, so a few main things here:
A pointer is what it is, it points to a location in the memory. So therefore, a pointer can be an array if you whish.
If you are working with pointers (dangerous at times), this complicates things. You are writing on p, which is a pointer to a memory location. So, even though you have not allocated the memory, you can access the memory as an array and write it. But this gives us the question you are asking. How can this be? well, the simple answer is that you are accessing a zone of memory where the variable you have created has absolutely no control, so you could possibly be stepping on another variable (if you have others) or simply just writting on memory that has not been used yet.
I dont't understand what you are asking in the second question, maybe you could explain a little more? Thanks.
The last line of this code...
double *pi;
double j;
pi = &j;
pi[3] = 5;
... is the syntactic equivalent to (pi + 3) = 5. There is no difference in how a compiler views a double[] variable and a double variable.
Although the above code will compile, it will cause a memory error. Here is safe code that illustrates the same concepts...
double *pi = new double[5]; // allocate 5 places of int in heap
double j;
pi[3] = 5; // give 4th place a value of 5
delete pi; // erase allocated memory
pi = &j; // now get pi to point to a different memory location
I don't understand how is that possible that I can perform the last
line here. I set pi to the reference of j
Actually, you're setting your pointer pi, to point to the memory address of j.
When you do pi[3], you're using a non-array variable as an array. While valid c++, it is inherently dangerous. You run the risk of overwriting the memory of other variables, or even access memory outside your process, which will result in the operating system killing your program.
When that's said, pi[3] means you're saying "give me the slot third down from the memory location of pi". So you're not touching pi itself, but an offset.
If you want to use arrays, declare them as such:
double pi[5]; //This means 5 doubles arrayed aside each other, hence the term "array".
Appropos arrays, in c++ it's usually better to not use raw arrays, instead use vectors(there are other types of containers):
vector<double> container;
container.push(5.25); //"push" means you add a variable to the vector.
Unlike raw arrays, a container such as a vector, will keep it's size internally, so if you've put 5 doubles in it, you can call container.size(), which will return 5. Useful in for loops and the like.
About your second question, you're effectively returning a reference to a substring of your "abcdefg" string.
&([3]) means "give me a string, starting from the d". Since c-style strings(which is what char* is called) add an extra NULL at the end, any piece of code that takes these as arguments(such as cout) will keep reading memory until they stumble upon the NULL(aka a 0). The NULL terminates the string, meaning it marks the end of the data.
Appropos, c-style strings are the only datatype that behaves like an array, without actually being one. This also means they are dangerous. Personally I've never had any need to use one. I recommend using modern strings instead. These newer, c++ specific variables are both safe to use, as well as easier to use. Like vectors, they are containers, they keep track of their size, and they resize automatically. Observe:
string test = "abcdefg";
cout<<test.size()<<endl;//prints 7, the number of characters in the array.
test.append("hijklmno");//appends the string, AND updates the size, so subsequent calls will now return 15.
I have an array allocated with malloc:
char *aStr1 = (char* ) malloc (10);
And then I filled this memory:
strcpy(aStr1, "ABCDEFGHI");
After that I created a new pointer aStr2:
char *aStr2 = aStr1 + 5;
And i set fourth element of memory to '\0':
*(aStr1 + 4) = '\0';
And finally, using these two pointers in a simple function:
int checkMem(char *aStr1, char *aStr2);
This function returns true (some none zero value) if aStr1 and aStr2 pointed to one memory block, and returns zero in another case.
How i can implement this function? (I read many linux mans about allocs function and haven't found any information about such problem).
//Added
I need this to do something like that:
char *aStr1 = (char *) malloc (10);
char *aStr2 = aStr1 + 5;
strcpy(aStr1, "ABCDEFGHI");
*(aStr1 + 4) = '\0';
and than:
my_strcat(aStr1, aStr2);
I do not ask for help to implement my_strcat, but maybe, get some hint how i can resolve its problem
//Updated
thanx, for all. I solved it.
Without any low level functions you cannot correctly know, how many memory allocate (maybe on some platform or realization you can do this:
size_t ptr_size = *((size_t *)ptr - 1);
but maybe not for all it will be correct).
And solving is simple: i create local copy of aSrc2, then realloc aSrc1 and copy aSrc2 to new aSrc1.
Unfortunately you cannot tell if two pointers point to memory that belonged to the same initial allocation.
You can create classes/structures that, for instance, save the initial allocation and then you could compare them.
But without added information, you simply cannot tell.
There is no provided standard mechanism for doing this, its up to you to track the memory you received and how big those allocations are, so you'd probably want to provide your own malloc wrapper that tracks what's allocd. Store the pointers in a map so you can use lower_bound to find the nearest allocate to the first string and then check if the second string is in the same allocation.
i am stuck and unable to figure out why this is the following piece of code is not running .I am fairly new to c/c++.
#include <iostream>
int main(){
const char *arr="Hello";
const char * arr1="World";
char **arr2=NULL;
arr2[0]=arr;
arr2[1]=arr1;
for (int i=0;i<=1;i++){
std::cout<<arr2[i]<<std::endl;
}
return 0;
}
where as this is running perfectly fine
#include <iostream>
int main(){
const char *arr="Hello";
const char * arr1="World";
char *arr2[1];
arr2[0]=arr;
arr2[1]=arr1;
for (int i=0;i<=1;i++){
std::cout<<arr2[i]<<std::endl;
}
return 0;
}
Why is this? and generally how to iterate over a char **?
Thank You
char *arr2[1]; is an array with one element (allocated on the stack) of type "pointer to char". arr2[0] is the first element in that array. arr2[1] is undefined.
char **arr2=NULL; is a pointer to "pointer to char". Note that no memory is allocated on the stack. arr2[0] is undefined.
Bottom line, neither of your versions is correct. That the second variant is "running perfectly fine" is just a reminder that buggy code can appear to run correctly, until negligent programming really bites you later on and makes you waste hours and days in debugging because you trashed the stack.
Edit: Further "offenses" in the code:
String literals are of type char const *, and don't you forget the const.
It is common (and recommended) practice to indent the code of a function.
It is (IMHO) good practice to add spaces in various places to increase readability (e.g. post (, pre ), pre and post binary operators, post ; in the for statement etc.). Tastes differ, and there is a vocal faction that actually encourages leaving out spaces wherever possible, but you didn't even do that consistently - and consistency is universially recommended. Try code reformatters like astyle and see what they can do for readability.
This is not correct because arr2 does not point to anything:
char **arr2=NULL;
arr2[0]=arr;
arr2[1]=arr1;
correct way:
char *arr2[2] = { NULL };
arr2[0]=arr;
arr2[1]=arr1;
This is also wrong, arr2 has size 1:
char *arr2[1];
arr2[0]=arr;
arr2[1]=arr1;
correct way is the same:
char *arr2[2] = { NULL };
arr2[0]=arr;
arr2[1]=arr1;
char **arr2=NULL;
Is a pointer to a pointer that points to NULL while
char *arr2[1];
is an array of pointers with already allocated space for two items.
In the second case of the pointer to a pointer you are are trying to write data in a memory location that does not exist while in the first place the compiler has already allocated two slots of memory for the array so you can assign values to the two elements.
If you think of it very simplistically, a C pointer is nothing but an integer variable, whose value is actually a memory address. So by defining char *x = NULL you are actually defining a integer variable with value NULL (i.e zero). Now suppose you write something like *x = 5; This means go to the memory address that is stored inside x (NULL) and write 5 in it. Since there is no memory slot with address 0, the the entire statement fails.
To be honest it;s been ages since I last had to deal with such stuff however this little tutorial here, might clear the motions of array and pointers in C++.
Put simply the declaration of a pointer does NOT reserve any memory, where as the declration of a array doesn't.
In your first example
Your line char **arr2=NULL declares a pointer to a pointer of characters but does not set it to any value - thus it is initiated pointing to the zero byte (NULL==0). When you say arr2[0]=something you are attempting to place a valuei nthis zero location which does not belong to you - thus the crash.
In your second example:
The declaration *arr2[2] does reserve space for two pointers and thus it works.
there is no problem here:
int *x;
x = (int *) malloc(0 * sizeof(int));
int value = 5;
x = (int *) realloc(x,(value)*sizeof(int));
But I cant do that for strings :\
I wanna do that for a y[] array, like this:
y[0]="hello"
y[1]="how are you"
how can I do that?
std::vector<std::string> y;
y.push_back("hello");
y.push_back("how are you");
Don't use malloc, or realloc, or free in C++. Don't use char* for purposes other than interop. Stay away from pointers until you actually need them (same for arrays).
You cannot use realloc on an array of std::string objects because realloc moves things around by bit copying and this is not allowed on general objects.
The standard class std::vector is a generic container for objects that moves and copies things around correctly (using copy constructors, assignments and similar methods) and that can change its size for example with the resize method. All the needed memory is allocated and freed automatically as needed.
With std::vector for example you can write code like...
std::vector<std::string> v; // An empty vector
v.resize(10); // Now size is 10 elements (all empty strings "")
v[0] = "Hello"; // First element is now the string "Hello"
v[1] = "world."; // Second element is now the string "world."
v.resize(2); // Now v.size() is 2
v.push_back("How's going"); // Now the size is 3 and third element is filled.
Do yourself a favor and pick up a good C++ book, reading it cover to cover. C++ is a powerful but complex language and if you try to learn it by experimenting with a compiler you're making a terrible mistake for many reasons.
What you're doing right now is not C++ ... you can do what you want with C-style strings, but you would need an array of pointers to type char that allow you to access the allocated memory for each string in the array. This can be done like so:
char* y[2];
y[0] = strdup("hello");
y[1] = strdup("how are you");
You also need to keep in mind that your y array now "owns" the pointers, so you must call free() on each pointer in the array in order to avoid any memory leaks should you decide to change the strings each pointer is pointing to.
If you want to go with an idiomatic C++ solution though, and not revert to C-style strings, then you should be using std::string and std::vector ... doing so avoids the issues with memory leaks as well as allocating and deallocating the memory associated with dynamically allocated C-strings.
You can actually do exactly what you need exactly like with integers:
typedef const char *c_string;
c_string *y;
y = (c_string *) malloc(0 * sizeof(c_string));
int value = 5;
y = (c_string *) realloc(y,(value)*sizeof(c_string));
y[0]="hello";
y[1]="how are you";
This won't work with non-const char * though, so this example is of limited usability.