I am new to C/C++ and trying to test my understanding of pointers. For this I created the following simple program to create an integer array to store 10 numbers and print it out.
#include<iostream>
#include <cstdlib>
// #include <cstdint>
int main(){
int numberOfItems = 10;
int *array;
// int *array = malloc((int*)numberOfItems*sizeof(int));
array = malloc((int*)numberOfItems*sizeof(int));
for(int i=0;i<numberOfItems;i++){
*array = i;
array++;
i++;
}
std::cout<<"The size of the array is : "<<sizeof(array)<<std::endl;
for(int i=0;i<numberOfItems;i++){
std::cout<<*array<<std::endl;
array++;
i++;
}
return 0;
}
I ran the program using the command g++ main.cpp.
But it gives me the following error:
main.cpp:8:47: error: invalid operands of types ‘int*’ and ‘long unsigned int’ to binary ‘operator*’
array = malloc((int*)numberOfItems*sizeof(int));
Tried and Failed
I tried to change the int to uint64_t but still it gave me similar kind of error.
I do not understand what I am doing wrong.
The error is due to the fact that your syntax is incorrect in the following line.
array = malloc((int*)numberOfItems*sizeof(int));
The right syntax would be as follows:
array = (int*) malloc(numberOfItems*sizeof(int));
You need to typecast the return value of malloc as it returns a (void *) pointer. So, you need to specify what type of data you would be pointing when you access the memory.
Let's go through your code step by step:
int *array;
array = malloc((int*)numberOfItems*sizeof(int));
Here you have two problems:
malloc is C, not C++. Yes, malloc is supported in C++, but for backwawrds compatibility with legacy code. Do not use it.
You cast numberOfItems to a pointer, then multiply the pointer with an integer. That's undefined behavior. Your compiler might even do the right thing here, but you cannot know and you cannot trust any result you're getting.
Let's continue:
for(int i=0;i<numberOfItems;i++){
*array = i;
array++;
i++;
}
The for declaration looks fine. You initialize an integer i to 0, and you increment it using the ++ operator as long as it is smaller than numberOfItems, that's good. But:
You increment i again inside your loop. That means you actually increment i by 2, so i goes 0, 2, 4, 6, 8, 10, and your loop is only executed 5 times.
You increment your array pointer. While technically perfectly valid code, this will bite you further down.
So you write the values 0, 2, 4, 6 and 8 into memory at the initial location of your array pointer, and 1*sizeof(int), 2*sizeof(int), 3*sizeof(int), 4*sizeof(int) bytes further down each.
Next problem:
std::cout<<"The size of the array is : "<<sizeof(array)<<std::endl;
This will not print what you meant it to print. array is a pointer type, so sizeof(array) will return the size of a pointer, which is probably either 4 or 8 bytes depending on the bitnes of your application/OS.
And last but not least your last loop:
for(int i=0;i<numberOfItems;i++){
std::cout<<*array<<std::endl;
array++;
i++;
}
You do the same thing with i as in your first loop. This time, this saves your neck, because...
...since you incremented the pointer array already in your first loop, you're now continuing at 5*sizeof(int) bytes further down in the memory. You're therefore not printing the values you set in the first loop (which was probably your intention), but uninitialized values that reside in the second half of the memory originally allocated at array.
Related
I get Segmentary fault with this code:
#include <iostream>
using namespace std;
int* arrayCreate(int length){
int *ew[length];
for (int i=0; i<length; i++)
{
*(ew[i])=i;
}
return ew[0];
}
int main(){
int *ptr=arrayCreate(7);
cout << *ptr << endl;
}
And when I tried to change this line
int *ew[length];
into
int *ew = new int[length];
I have error < indirection requires pointer operand ('int' invalid) >
Any one please explain the difference between these two declaration, why I get segmentary fault and how to fix it?
In the first version, you allocate array of pointers on the stack and return an element of that array - which is dead once the function finishes. Accessing this return value means undefined behaviour.
In the second version, you create array of ints (not pointers) on the heap. Thus the syntax error.
What you want is
int* arrayCreate(int length){
int* ew = new int[length];
for (int i=0; i<length; i++)
{
ew[i]=i;
}
return ew;
}
Or better yet, don't use new[], use std::vector, which manages memory for you:
#include <vector>
#include <numeric> //for std::iota
std::vector<int> arrayCreate(int length){
std::vector<int> v (length);
std::iota(v.begin(), v.end(), 0); //you can use your loop as well
return v;
}
int *ew[length];
Problem 1: The size of an array variable must be compile time constant. length is not a compile time constant. Thus, the program is ill-formed.
how to fix it?
If you need an array with dynamic size, you need to allocate dynamically. Simplest solution is to use std::vector.
why I get segmentary fault
Observation: The pointers in ew have indeterminate values. They don't point to any valid object.
*(ew[i])=i;
Problem 2: You indirect through a pointer stored in the array. Since you're indirecting through an invalid pointer, the behaviour of the program is undefined.
Ask yourself: What int object was ew[i] supposed to be pointing to?
how to fix it?
Don't read indeterminate values, and don't indirect through invalid pointers.
int *ew = new int[length];
Here, you create a dynamic array of integers. Array of integers is not an array of pointers. ew is a pointer to an integer. ew is not a pointer to a pointer.
*(ew[i])=i;
Here, you indirect through ew to access ith successor sibling, and then indirect through that sibling. But the first indirection results in an int object and you cannot indirect through an int.
how to fix it?
Don't try to indirect through an int.
Any one please explain the difference between these two declaration
int *ew[length] is an ill-formed and uninitialised array of pointers to int. int* ew is a single pointer to an int, in this case initialised with the address of a first element of a dynamic array of int.
To get memory for your array in C++ you should write:
int *ew = new int[length];
To return the pointer you should write:
return ew;
This means you return pointer to the beginning of array. It should be mentioned that a[i] <=> *(a + i). You can't write *(ew[i]) = i; to assign, but ew[i] = i; will work.
It should also be said that usage of raw pointers is deprecated in modern c++.
I have to find the exact number of elements in an int array leaving the '\0's which are effectuated during declaration. I know that the value '\0' is equivalent to 0 .i.e ('\0' == 0) = true.
#include<iostream.h>
int getsize(int arr[])
{
int i = 0,p=1;// initialized to 1 as, if left un-initialised it suffers from undefined behaviour
while(p!=NULL)
{
i++;p=arrr[i]'
}
return i;
}
The code works fine when it is called in the main as:
void main()
{
int testarr[10]={0,5};
cout<<"\nThe size is : "<<getsize(testarr);
}
But when the testarr[] is modified to int testarr[10]={5,0}
The output becomes
The size is : 1
The problem is that the pre-historic turbo c++ compiler,which I'm unfortunately restricted to reads int 0 and '\0' the same.I have used NULL instead but, the code doesn't seem to work. Is there something I'm missing?
How to find the number of user-defined elements in an int array?
There is no way to distinguish a zero that was specified by the programmer, from a zero that was generated by the compiler.
The problem is that the pre-historic turbo c++ compiler,which I'm unfortunately restricted to reads int 0 and '\0' the same.
That behaviour is not specific to your ancient compiler. It is true for all C++ compilers. The value of 0 is exactly the same as '\0'. However, there is no '\0' involved in your program.
while(p!=NULL)
Don't compare an integer with NULL. That is going to confuse anyone reading your code (which since C++11 may be ill-formed depending on how the standard library has chosen to define NULL). Since it is equivalent to comparing with zero, just use while(p).
What your function does, is it counts the number of non-zero elements in the array and until a zero is reached, except the first value is ignored and always counted as 1. If the array does not end in a zero (in other position than first), then the array is accessed over bounds, and there will be UB.
Essentially, it works just like strlen, but for integers, and the first element is treated differently.
So the expected output would be:
{0,0,1,2} -> 1
{0,1,0,0} -> 2
{1,0,0,0} -> 1
{0,0,0,0} -> 1
{0,1,2,0} -> 2
{0,1,2,3} -> Any or no output is expected, because UB
can't I check for null pointers
No. Your array does not contain pointers. It contains integers.
testrarr[10]={5,0} as, by default ,during initialization it fills all the values in the array as \0 a.k.a null character not nullpionter –
No. The array contains integers, so it is not filled with null character. Zero initialization fills the array with zero integers (which has the same value of null character, so the distinction is subtle).
C misuses the term "array" slightly. An array is an organisation of data, a buffer is a place to put data. So when we declare a buffer in C
int testarr[10];
we are declaring a buffer which can hold ten integers, not an array of ten integers. In fact the values may be "illegal integer" trap representations.
When you do
int testarr[10] = {0,5};
you've got a buffer of ten integers, and array of only two. But, partly because the array / buffer confusion is ingrained, C won't tell you. It's normally necessary to keep a separate value, N.
int testarr[10] = {0, 5};
int N = 2;
Now when we pass the array to a subroutine, we pass the address, plus N.
int sum(int *x, int N)
{
int answer = 0;
int i = 0;
for(i=0;i<N;i++)
answer += x[i];
return answer;
}
int testarr[10] = {0, 5}:
int N = 2;
total = sum(testarr, N);
Note that we can also call sum on array slices, or on dynamically allocated arrays. The function is completely unaware of any unused integer slots after the data, or if data is static, on the stack, or on the heap.
Consider the following code:
int main()
{
int* p = new int(3);
p+=4;
std::cout<<*p<<std::endl;
}
My compiler (Visual Studio 2012) prints: -7514522142 int this case.
So can we somehow deduce the output and is this code legal?
You are accessing memory (allocated for a single int object) out of bounds. The behaviour is undefined, i.e. not deducible. The program should not be considered legal, despite being syntactically valid.
So can we somehow deduce the output and is this code legal?
Pointers are incremented in multiples of the size of the type they point to. When you add 4 to p, you're adding 4 * sizeof(int), not just 4 bytes.
If you're trying to make p point to the "next" integer, increment it by 1, not 4. Otherwise, p will point to memory beyond the end of what you allocated.
In fact, if I'm not mistaken your allocation only creates a single int with the value 3, not three separate ints:
int* p = new int(3);
Try commenting out the p += 4; line and you should get '3' as the output. Considering that, juanchopanza's answer above is spot on.
I'm a novice programmer trying to get a head start on some classes before the summer semester starts, and I've run into this problem while trying to create a Quick Union algorithm in C++.
I've been trying to figure out why my program creates two identical arrays, despite having two separate for loops designed to create two different arrays. Whenever my program runs to completion and prints id[] and sz[], it always outputs 1 as the element at every index in both arrays.
class quickUnionUF{
private:
int id[];
int sz[];
int root(int);
public:
quickUnionUF(int, int);
bool connected(int, int);
void unionPoint(int, int);
void print();
};
quickUnionUF::quickUnionUF(int n, int b){
id[n];
sz[b];
for(int i=0;i<n;i++){
id[i] = i;
}
for(int j=0;j<b;j++){
sz[j] = 1;
}
}
For example, if I create quickUnionUF(5, 5);
id[] should now contains elements:
0, 1, 2, 3, 4
And sz[] contains elements:
1, 1, 1, 1, 1
However, the program creates an array sz[] AND array id[] with elements:
1, 1, 1, 1, 1
Any thoughts as to why this is happening?
Standard C++ does not have sizeless array members.
Use std::vector<int> as dynamically sized arrays in C++.
#include <vector>
class quickUnionUF{
private:
std::vector<int> id;
std::vector<int> sz;
int root(int);
public:
quickUnionUF(int, int);
bool connected(int, int);
void unionPoint(int, int);
void print();
};
quickUnionUF::quickUnionUF(int n, int b)
: id(n)
, sz(b)
{
for(int i=0;i<n;i++){
id[i] = i;
}
for(int j=0;j<b;j++){
sz[j] = 1;
}
}
Your code hints at a two very important mistakes:
C++ does not work like Java. int id[] is not an reference to an array of arbitrary size on the garbage collected heap. It is instead a member array of undefined size used to implement dynamic arrays (and similar features) in C99. You should never use this syntax unless you know exactly what you are doing, because it is almost guaranteed to be wrong otherwise.
id[n] does not allocate an array at all. Instead it just indexes id and discards the result.
Listen to your compiler!
First, your code should not compile due to the fact, that only the last member of a struct may be a flexible array type. In fact clang howls:
main.cpp:53:9: error: field has incomplete type 'int []'
int id[];
MSVC howls:
1>main.cpp(54): error C2229: class 'quickUnionUF' has an illegal zero-sized array
And g++ only warns (well, g++ is strange in what it accepts sometimes):
main.cpp:53:12: warning: ISO C++ forbids zero-size array ‘id’ [-Werror=pedantic]
int id[];
Note: g++ is wrong in compiling this, even if one allows flexible array members. This is defined in C99 6.7.2.1§16 and C11 6.7.2.1§18 both of which begin with (emphasis is mine):
As a special case, the last element of a structure with more than one named member may
have an incomplete array type; this is called a flexible array member. [...]
What is happening?
Well, assuming you got your code to compile anyway, it basically means the following:
Create an object with the alignment of integers, but NO elements at all. Take a peek at the following test program:
quickUnionUF q;
::std::cout << sizeof(quickUnionUF) << "\n";
::std::cout << &q << "\n" << &q.id[0] << "\n" << &q.sz[0] << "\n";
The only compiler that managed to compile this at all (gcc 4.9.0) gave the following result:
0
0x7fff1bf6274c
0x7fff1bf6274c
0x7fff1bf6274c
So, this is a zero byte object (yes, this is illegal C++, since every C++ object has a size > 0) and the first element of each array is at the same position (OUTSIDE YOUR OBJECT!). Remember, you declared id and sz to have zero elements!
Therefore, you are writing to the same arbitrary position. You can consider this the extreme case of a buffer overflow: By writing 5 integers to a zero size buffer, you are overflowing from the first zero size buffer through the second zero size buffer into memory totally not under your control.
This also explains your observed result: The second loop simply overwrites what the first did (and it still does it by corrupting your stack).
How do I fix this?
Just use a vector. You can tell it how big you want it and you can ask it to tell you when you are indexing to some position that is not yours.
I was trying to do something using sizeof operator in c++.
Please refer to the following code snippet.
http://ideone.com//HgGYB
#include <iostream>
using namespace std;
int main()
{
int *pint = new int[5];
int temp = sizeof(*pint);
cout << "Size of the int array is " << temp << endl;
return 0;
}
I was expecting the output as 5*4 = 20. Surprisingly it comes to 4. Any ideas ?
Here is pint is an int*. So,
sizeof(*pint) == sizeof(int)
Compiler doesn't know about new int[5], when it does sizeof(*pint) (because sizeof() is a compile time operator).
[Note: Try the same test with statically declared array, int pint[5]; and will see the expected result.
Additionally, sizeof() returns size_t (which is an unsigned value), so it should be:
size_t temp = sizeof(...);
]
Dynamically sized arrays lose their size information- the size is only the size of one integer, as pint is a pointer to int, and *pint is an integer, not an array type of any size.
There is no way for C++ to know the size of the array.
In your case,
*pint
returns an int, and sizeof(int) is 4 on your machine.
All fine. You ask for the size of an int which will be 4 bytes.
pint is a pointer to int that just happens to point to the beginning of an array. It contains no information about this array.
It is giving you the size of what the pointer points to - the first location in the array.
In the current case sizeof(*pint) is giving the sizeof(int), so its returning 4 . But, even if you will try sizeof(pint), it will return you the size of a pointer. Which will most probably be 4 if yours is a 32 bit machine else it will be 8, if 64 bit machine.
Now you have asked, why it is not returning 4*5 = 20. Since pint points to an integer array. Yes, pint points to an integer array, but its not an array. The difference is :
Array have a fixed size. you can redectare it at all. While pointers can point to any object of any size.
Since sizeof operator is evaluated at compile time, so compiler dont have any way to know at which size of array this pointer is pointing and so cant tell the size of that object and so it always return only the size of pointer. now you can understand, why in case of pointers compiler gives size of the pointer (ie space occupied by pointer in memory), but in case of array it gives full size.