I am using C++ on Mac OSX Lion and I have created the following code:
float* floatArray = new float[10];
for(int i = 0; i < 10; i++)
{
floatArray[i] = 0.0 ;
}
std::cout<< "Test size of a float " << sizeof(floatArray[0]) << std::endl;
// The value is 4 byte which is what I would expect.
std::cout<< "Test the size of the whole array" << sizeof(floatArray) <<std::endl;
// the value is 8. I would have expected the value to be 40 bytes.
What am I not understanding?
Thanks in Advance
The expression sizeof(floatArray) returns the size of the pointer, not what it points to.
In your system, size of the pointer in memory is 8 bytes.
Sizeof() operator just looks at the size of that variable in memory. So it prints the size of the float pointer.
You can find more detail here.
How to find the 'sizeof' (a pointer pointing to an array)?
Compare it with this (which actually is an array):
float floatArray[10] = {0.0};
std::cout<< "sizeof a float " << sizeof(floatArray[0]) << std::endl;
std::cout<< "sizeof the whole array " << sizeof(floatArray) << std::endl;
and then, if you need to use dynamically-sized or allocated arrays, consider using std::vector instead.
Your second sizeof(floatArray) is actually returning the size of the pointer, not the size of the array.
See here
The sizeof operator has no knowledge what and how many elements a pointer points to (except when you feed it an array, but that's not a pointer, again). So it returns sizeof (float *) - and as you're probably on 64-bit, the size of a pointer is 8 bytes long.
Related
after ptr++ pointer does not increment
1 #include<iostream>
2
3 int main() {
4
5 char *ptr;
6 char ch = 'A';
7 ptr = &ch;
8
9 std::cout << "pointer :" << &ptr << "\n";
10 ptr++;
11 std::cout << "pointer after ++ :" << &ptr << "\n";
12 return 0;
13 }
ikar$ g++ pointer_arth.cpp
ikar$ ./a.out
pointer :0x7ffeed9f19a0
pointer after ++ :0x7ffeed9f19a0
ikar$
You're incrementing the pointer, but outputting the address of the variable that holds the pointer itself (&ptr). You should output just ptr (and format it accordingly - see edit below).
Example:
#include <iostream>
int main() {
char data;
char *ptr = &data;
std::cout << "pointer:" << (unsigned long long)ptr << std::endl;
ptr++;
std::cout << "pointer incremented: " << (unsigned long long)ptr << std::endl;
}
Output:
pointer:140732831185615
pointer incremented: 140732831185616
Yes, printing just ptr will output garbage, so I converted the pointer to an integer (since pointers are memory addresses anyway).
As suggested in the comments, you can cast the pointer to void * when printing, which gives nicer formatting:
pointer:0x7ffee5467acf
pointer incremented: 0x7ffee5467ad0
Note how 0x7ffee5467acf == 140732745022159 != 140732831185615 - you'll get different outputs on each run because the kernel will load the executable into different places in memory.
EDIT: yes, the first version of this answer, about simply outputting ptr with std::cout << ptr, was incorrect, because the << operator is overloaded in such a way that it treats pointers to char as C-strings. Thus, that version would access potentially invalid memory and output garbage.
But the concept remains the same. Pointers to int, for example, don't have this "problem" and are printed as hexadecimal numbers, even without casting them to void *: Try it online!. The output shows that pointers are still incremented correctly by sizeof(int), which equals 4 on that machine.
Pointer is incremented successfully in your code.
You print the address of location which hold the pointer variable.
Actually, it is garbage after character -'A' if print 'ptr', you can understand and pointing to such un-handled memory location is not good.
How come when I increment a pointer and then dereference it I get a random number?
Here is my code:
#include <iostream>
using namespace std;
int main(){
int reference = 10;
int *health = &reference;
int *health1 = health;
cout << "Health Address: " << health <<
"\nHealth1 Address: " << health1 <<
"\nReference Address: " << &reference << endl;
health1++;
cout << "Health1 value after being incremented then dereferenced: " << *health1 << endl;
}
My output is:
Health Address: 0x7fff5e930a9c
Health1 Address: 0x7fff5e930a9c
Reference Address: 0x7fff5e930a9c.
Health1 value after being incremented then dereferenced: 197262882
I was expecting to get a 0 since the next value of the next memory address would be null, but that is not the case in this situation.
I was expecting to get a 0 since the next spot in memory would be null, but that is not the case in this situation.
Your expectation is wrong. After you have incremented your pointer, it is no longer pointing to the valid memory buffer. Dereferencing it invokes an undefined behavior.
After you increase the pointer, it points to the memory not allocated and initialized by your program, so it's not null as you expected.
Each time you run your program, you may get a random integer.
I think your misunderstanding comes from the fact that you expect the pointer to point at the address of the next element of an array:
int myarray[] = { 1, 2, 3, 4, 5 };
int* parray = myarray;
std::cout << *parray << std::endl;
parray++; // increment the pointer, now points at the address of number 2
std::cout << *parray << std::endl;
But since there is no array in your example the incremented pointer points at the next memory block. The size in bytes of the type it points to is added to the pointer. What value lies there is anyone's guess:
int myvalue = 10;
int* mypointer = &myvalue;
mypointer++;
Dereferencing such pointer is undefined behavior. When you exceed the memory allocated to your process you will not get a pointer null value or a dereferenced value of 0.
Suppose X is the value of a pointer T *p;.
If p is incremented then, p will point to address X + sizeof(T)
*p will then give you the value stored at address X + sizeof(T). Now depending upon the validity of address X + sizeof(T), you will get the result which can be Undefined Behavior in case X + sizeof(T) is invalid.
(*health1)++;
you need to dereference the pointer as this would increment the address itself and not the value it is pointing at.
I'm trying to output the number of element-objects in my array, but the syntax for that is not the same as it is for Java:
// print list of all messages to the console
void viewSent()
{
cout << "You have " << sent.size() << " new messages.\n";//Error: left of '.size' must have class/struct,union
std::cout << "Index Subject" << '\n';
for (size_t i = 0; i < sent.size(); ++i)
{
std::cout << i << " : " << sent[i].getSubject() << '\n';
}
}
if the .size doesn't work in C++ syntax, what does?
The C++ equivalent of a Java array is std::vector. sent.size() is the correct way to get the size.
You didn't post your definition of sent but it should be std::vector<YourObject> sent;, perhaps with initial size and/or values also specified.
I'm guessing you tried to use a C-style array -- don't do that, C-style arrays have strange syntax and behaviour for historical reasons and there is really no need to use them ever in C++.
If your array is a C-Array, you can loop through it like this:
for (size_t i = 0; i < (sizeof(sent) / sizeof(TYPE)); ++i)
... where TYPE is the underlying type of the array.
For example, if sent is defined as:
int sent[];
... then TYPE would be int, like this:
for (size_t i = 0; i < (sizeof(sent) / sizeof(int)); ++i)
A C-Array is not an object. So it has no members or methods and you cannot use the member operator with it. The sizeof operator is used to find the size of a fundamental type, in bytes. sizeof returns an integer value of type size_t.
So given the following code:
#include <iostream>
#include <vector>
int main(int argc, char* argv[]) {
int i = 42;
int* p = &i;
std::cout << "*p: " << *p << std::endl;
std::cout << "&p: " << &p << std::endl;
std::cout << "p: " << p << std::endl;
std::cout << "p + 1: " << (p + 1) << std::endl;
std::cout << "p + 1: " << ((p + 1) == (int*)(&p)) << std::endl;
std::cout << "*(p + 1): " << *(p + 1) << std::endl;
return 0;
}
It might produce the following output:
*p: 42
&p: 0x7fff38d8a888
p: 0x7fff38d8a884
p + 1: 0x7fff38d8a888
p + 1: 1
*(p + 1): 953723012
Is (p + 1) a pointer to the memory location p is stored in? Is it possible to get the value pointed by p by this way?
p is the pointer to an int object.
&p is the address of p.
The stack from your example looks like:
Address Type Name Value
0x7fff38d8a884 int i 42
0x7fff38d8a888 int* p 0x7fff38d8a884
The way that the stack has been setup, the address of p is right after the address of i. In this particular case, when you added 1 to p, it moved 4 bytes down and found the value there, which happens to be the address to i.
What is happening in the line
std::cout << "p + 1: " << ((p + 1) == (int*)(&p)) << std::endl;
is p+1 --> compiler gets address for the "second element" of array p
(int*)(&p) --> &p is an int**, but is being cast to an int*, int this particular instance, that happens to be the same as the value stored in p + 4 bytes
What is happening in the line
std::cout << "*(p + 1): " << *(p + 1) << std::endl;
is *(p+1) --> compiler accesses the "second element" of array p, because you are likely using an x86_64 system, which is little endian, the hex value stored there is 0x38D8A884, the lower half of the pointer stored in p (which converts to 953723012 in decimal),.
In your example (p + 1) does not point to any storage you have allocated, so dereferencing it produces undefined behavior and should be avoided.
EDIT: Also, your second output for (p + 1) itself is unreliable, since pointer arithmetic should be used only if the pointer is a pointer to an array. Consequently, the expression evaluates to false on my machine.
If you remember that pointers and arrays can be used interchangeably, you might figure out that e.g.
p[1]
is the same as
*(p + 1)
That means that the expression (p + 1) is a pointer to the int value after p. As p doesn't point to an array, it means that (p + n) for a positive n is a pointer to something you haven't allocated (it's out of bounds), and reading that value leads to undefined behavior. Assigning to it is also undefined behavior, and can even overwrite other variables data.
To get the address of where p is stored, you use the address-of operator: &p. That returns a pointer to the pointer (i.e. of type int **).
While the standard gives you no guarantee that ((p + 1) == (int*)(&p)) you seem to be lucky here.
Yet since you are on a 64-bitmachine when dereferencing (p+1) you get only the lower 32 bits of p.
0x38D8A884 == 953723012
The right hand side of the equation is the output that you received. The left hand side is the lower 32 bits of p as witnessed by the output of your program.
No.
Pointer arithmetic, although unchecked, is very limited by the Standard. In general, it should only be used within an array, and you may use it to point to either an array element or one past the end of the array. Furthermore, although pointing one past the end of an array is allowed, the so-obtained pointer is a sentinel value which should not be dereferenced.
So, what is it that you observe ? Simply put, &p, p + 1, etc... are temporary expressions whose result have to be materialized somewhere. With optimizations on, said results would probably be materialized in CPU registers, but without they are materialized on the stack within the function frame (in general).
Of course, this location is not prescribed by the Standard, so trying to obtain it produces undefined behavior; and even though it appears to work on your compiler with this set of compiling options means nothing for any other compiler or even this very same compiler with any other set of options.
That is the true meaning of undefined behavior: it does not mean the program crashes, it just means anything may happen and this encompasses the seems to work situations.
It is a random case that p + 1 is equal to &p. It takes place only in such code as yours where pointer p follows the object it points to. That is the address of p itself is sizeof( int ) greater than the address of the object it points to. If you for example will insert one more definition between i and p then the equation p + 1 == &p will not be valid. For example
int i = 42;
int j = 62;
int* p = &i;
p just so happened to get allocated on the stack at the address right after (well 4 bytes after) the address of the integer i. some_ptr+1 (which is really some_ptr+1*sizeof(int)) is not a consistent way to get the address of some_ptr, it is just a coincidence in this case.
so to answer your question some_ptr+1 != &some_ptr
I get a segmentation fault when my function reads floats from a string and places them in a void array. The segfault occurs after about 200 iterations of the for loop in the following code:
// Allocate memory
void** data;
data = (void**)malloc(num_vals * sizeof(float));
// Convert text to floats
(*(float**)data)[0] = atof(strtok(text, " "));
for(int index=1; index<num_vals; index++) {
(*(float**)data)[index] = atof(strtok(NULL, " "));
std::cout << (*(float**)data)[index] << std::endl;
}
The void array is necessary because the size and type of data in the string are determined at run-time. I've tried increasing the malloc size, but it doesn't change anything. Any thoughts?
Seriously??
std::vector<float> data;
std::istringstream str(text);
float fv;
while (str >> fv)
{
data.push_back(fv);
}
Now that's c++
As much as it pains me to do so, here is a version of your code that probably does what you want.
// Allocate memory
void* data;
data = malloc(num_vals * sizeof(float));
// Convert text to floats
((float*)data)[0] = atof(strtok(text, " "));
for(int index=1; index<num_vals; index++) {
((float*)data)[index] = atof(strtok(NULL, " "));
std::cout << ((float*)data)[index] << '\n';
}
Note, however, that if you worked for me and tried to check in that code, we would have a serious discussion about your choice of career.
I'd rather see something like this:
std::vector<float> v;
std::copy(std::istream_iterator<float>(std::istringstream(text)),
std::istream_iterator<float>(),
std::back_inserter(v));
P.s. Rob's rule #47: Never say std::endl when you mean '\n'.
Why do you convert to void ** ??? You code contains couple errors on indexing, so let me show some reasonable changes
float* data;
data = (float*)malloc(num_vals * sizeof(float));
// Convert text to floats
data[0] = atof(strtok(text, " "));
for(int index=1; index<num_vals; index++) {
data[index] = atof(strtok(NULL, " "));
std::cout << data[index] << std::endl;
}
You got your types mixed up in your inexplicable attempt to create this monster under the pretence of writing "C++". Anyway. what you're mallocing is nothing but a float*, so you need to cast data back to float*:
((float*)data)[0] = myfloat;
I think, since you are defining a pointer of void pointer and allocating/casting it to pointer of void pointer, it allocates 4 byte memory for each element because in C/C++, regardles of the type of the pointer, pointers are always 4 bytes which are not big enough floats.
There're several issues. One is - data should be void *, you have redundant *. Other might be alignment, i'm not sure you are able to place a float in any location in the memory.