Today, I found out that you can write such code in C++ and compile it:
int* ptr = new int(5, 6);
What is the purpose of this? I know of course the dynamic new int(5) thing, but here i'm lost. Any clues?
You are using the comma operator, it evaluates to only one value (the rightmost).
The comma operator (,) is used to
separate two or more expressions that
are included where only one expression
is expected. When the set of
expressions has to be evaluated for a
value, only the rightmost expression
is considered.
Source
The memory address that the pointer is pointing to is initialized with a value of 6 above.
My compiler, g++, returns an error when attempting to do this.
What compiler or code did you see this in?
I believe it is bug which meant to allocate some sort of 2D array. You can't do that in C++ however. The snippet actually compiles because it's utilizing the comma operator, which returns the last expression and ignores the results of all the others. This means that the statement is equivalent to:
int* ptr = new int(6);
The 5 is ignored. this allocates an int on the heap and initializes it to (5,6).
the result of a set of statements separated by the comma operator is the value of the last statement, so the int is initialized to 6
Simply do this:
int* ptr = new int(6);
As far as comma operator is concerned, use it when you can't do the desired task without it. There is no use of applying tricks such as:
int* ptr = new int(5, 6);
Related
so in the picture, it says that the problem is with the starting address of the array as we cant change it. but why does this apply only for arrays. int x = 1; we could easily say int y = x; and it would work. doesnt this change the memory address of the variable too?
[tl;dr] The first and sole reason why newValues = oldValues; is illegal ("will not work") is that the C++ standard prohibits it. Array assignment is not defined, supported or allowed in C++, and therefore any such statement is invalid code. Any other attempts to "explain" it, using memory addresses or other speculations, only obfuscates the simple truth that it is the definition of the language that decides what is legal and what is not in that language.
The following are quoted from the posted "textbook" excerpt, which I find to be both wrong and misguided for what looks to be an introduction to C++ basics.
the name of an array without the brackets and subscript stands for the array's starting memory address
Wrong. The name stands for the variable that it denotes, which has array type. While it is true that an array can decay to a pointer ("starting memory address) in certain contexts, it is certainly not true that an array name is the same with its starting address. For example, both sizeof oldValues and typeid(oldValues) are valid expressions, which would mean something very different if replacing oldValues with its memory address.
the statement will not work because you cannot change the starting memory address of an array
The statement "will not work" is correct, but the given reason is still wrong. No assignment changes the address of its left-hand side, it only changes its value. Array assignment does not work because the language does not define it, and for no other reason. Consider for example the following.
int a[4], b[4];
a = b; // error, array assignment not allowed
struct { int n[4]; } c, d;
c = d; // ok, using default copy assignment
i have an array of object class, and i want to assign the last indexi to NULL
i have the following code, but it gives an error
DNA is a class
allRightSequences is a vector
DNA* newDNA = new DNA[allRightSequences.size()];
newDNA [allRightSequences.size()] = NULL; << this line gives an error
NULL is a macro that, in appropriate situations, will expand into something that can be treated as a null pointer constant. So you can use it to set a pointer value:
int *ip = NULL; // okay
However, newDNA does not contain pointers; it contains objects of type DNA. Forget the array for a moment. The problem is this:
DNA dna = NULL;
This won't work, unless DNA has a constructor that can be called with whatever NULL expands into.
If you really need to have a marker at the end of the array you need to create an array of pointers. But you really don't need this. Use std::vector<DNA>, which keeps track of the size for you.
allRightSequences.size() is not the last index of an array that has allRightSequences.size() elements. The last index is allRightSequences.size() - 1. The behaviour of accessing the array out of bounds is undefined.
Another potential problem: There must exist an appropriate assignment operator in order to be assign a pointer to a DNA object. Unless you have defined such operator, the assignment is ill-formed.
What you might want (though not sure from the question yet), is an array of pointers to DNA objects.
What you are declaring is "just" an array of DNA objects; and you can't set an object to null, as Pete Becker's answer explains very well.
The following code would work:
// notice how we use +1 here to have place for the NULL element at the end
DNA* newDNA[] = new DNA*[allRightSequences.size()+1];
newDNA [allRightSequences.size()] = NULL;
For each element of the array, you'd however also have to create a DNA object via new DNA... then...
Note that if you use a compiler supporting C++11, use nullptr instead of NULL.
And if you want to avoid the hassle with pointers completely, you could use a construct like std::optional in case you use C++17 or boost::optional for earlier versions, as described in this answer to another question, as mentioned by Baum mit Augen above.
Also, the good question is what you really need that zero pointer at the end - if it's just for determining the last element when iterating over the array, then you might be better off using an std::vector<DNS> or a similar collection type instead...
Use the following code:
newDNA [allRightSequences.size()-1] = NULL;
Because an array index in C++ goes from 0 to n-1, where allRightSequences.size() in your case returns n, where n is the size of the array.
Let's say I define a pointer structure called date_ptr of a structure already defined, the following way:
Date *date_ptr = new Date[10]
Essentially this is an array of structures containing objects of type Date. Now let's say I wanted to set the month of each structure in the array doing:
date_ptr[0].month = new int(10);
date_ptr[1].month = new int(3);
My question is as follows: am I allowed to set the month variable of each structure using the dot operator instead of the -> even though date_ptr is a pointer to the structure. If so, does this cause any problems? Or is it better (or mandatory) to use the -> operator?
In your case, data_ptr is a pointer, but data_ptr[0] is not a pointer, but a object of type Date. Thus you can only use dot (.) but not -> to access Date's fields.
date_ptr is a pointer to structure but date_ptr[0] is a reference to a structure. That's because date_ptr[0] is the same as *(date_ptr+0). So it's mandatory to use ..
Careful, that's an array containing 0s of type Date *. In particular, the following code will segfault without proper initialization.
Anyway to answer you, -> is just syntactic sugar for equivalent code with .. You don't need to use it, you can simply write date_ptr->month=0; and it will compile. Or (date_ptr+1)->month=0; for the second element.
Do you mean the following? This would work.
Date * end_ptr = date_ptr + 10;
for (Date * ptr = date_ptr; ptr != end_ptr; ++ptr)
ptr->month = 1;
Be warned not do do this if polymorphism is involved or you'll encounter a bad surprise.
#include<stdio.h>
int main(){
char *ptr="Helio";
ptr++;
printf("%s\n",ptr);
//*ptr++;
printf("%c\n",++*ptr);/*Segmentation fault on GCC*/
return 0;
}
Q1) This works fine in Turbo C++ but on GCC it gives segmentation fault. I am not getting the exact reason.
May be operator precedence is one of the reason.
Q2) Do each compiler has different operator precedence?
As I can see here ++ has higher precedence than dereference operator. May be GCC and Turbo C++ treats them differently.
No, the operator precedence is defined by the C standard, all the compiler follows the same one.
The reason of difference result of Turbo C++ and GCC in this case is because you modified the string literal, which is undefined behavior.
Change it to:
char arr[] = "Helio";
char *ptr = arr;
and you can modify the content of the string now. Note that arr itself is the array name and cannot be modified, so I added a new pointer variable ptr and initialize it to point to the first element of the array.
In your last printf() line, the expression ++*ptr is equivalent to ++ptr[0], which is, in turn, equivalent to ptr[0] = ptr[0]+1. Since ptr[0]=='H', you are trying to change the value of ptr[0] to 'I'.
That's the key problem there. Since &ptr[0] points to the first element of the constant "Helio", the attempt to change the first character, H, is giving trouble, because it is Undefined Behaviour.
char* p = "some literal";
This is only legal because of a smelly argument that C-people fought over during standard comitee negociations. You should consider it as an oddity that exists for backward compatibility.
This is the message you get with GCC:
warning: deprecated conversion from string constant to 'char*'
Please next time, write the following:
char const* p = "some literal";
And make it a reflex in your coding habits. Then you would not have been able to compile your faulty line.
which is:
++*ptr
Here you are taking the first character of the constant literal and try to increment it, to what comes after H, therefore I. But this memory zone happens to be in a write protected page, because this is a constant. This is very much undefined by standard and you should consider it illegal. Your segfault comes from here.
I suggest you run your program in valgrind next time to get more elaborate error messages.
In the answer that Yu Hao wrote for you, what is happenning is that all the characters gets copied one by one, from the constant string pool where the literal are stored, to a stack-allocated char array, by a code that the compiler writes at the initialization/declaration site, therefore you can dereference its content.
I was reading some code and came across this thing. I don't have the whole context now save this line.
cout<<(*--*++ptr+1)<< endl;
this compiles fine and works when we input values in it..
its declaration is like this.
char ***ptr ;
What is this operator and is it included in the standard?
It's not a single operator, it's a combination of several unary operators. It gets parsed like this:
*(--(*(++ptr))) + 1
So, ptr1 is first incremented, then dereferenced, then that value is decremented and dereferenced again.