0

In the following code, im trying to build 2 arrays. The first one is an array given by the user, the second one is an array which has been sorted among other things, although kept short since the actual implementation is not nescessary :

int main()
{
    int size = 0;
    cout << "Please enter size: ";
    cin >> size;
    int array[size];
    int newArray[size] = doSomething(array,&size);
    return 0;
}
int* doSomething(int array[],int *size)
{
    *size+=1;
    int newArray[size];
    //do something with the array and store it in the newArray
    return newArray;
}

So my question is this:

My teacher told me that most compilers work differently, and the order of some operations might differ among them.

At the line int newArray[size] = doSomething(array,&size); I am expecting the size variable to be changed inside doSomething before it is used to initialize newArray. Once the doSomething method is finished running, it should return an array (WHICH I ASSUME It IS JUST RETURNING THE ADRESS OF THE FIRST ELEMENT OF THE ARRAY, PLEASE CORRECT ME IF THIS IS WRONG). Once it returns I want to store that address into my newly array, where the variable size is used to initalize the array's size. This variable should be according to my logic, equal to the original size entered by the user +1. So if the user enters a size of 4, the size of newArray should be 5. Is this a good way of going about it, or would it produce unreliable results for different compilers?

For the purpose of this exercise, I can only use built in array and pointers. So I cannot use vectors. Furthermore, in this example, the newArray is one element larger, but the actual code has a size which is dynamic, and therefore might be different each time. I can therefore not hard code the +1 inside the declaration.

If this is wrong, can someone point me in the right direction and help me to find a way where I can pass a built in array (no vectors or array<>), modify the contents and size of it and then return that array and store it in a variable in the caller method?

Thank you very much

rici
  • 234,347
  • 28
  • 237
  • 341
  • Your code is wrong in various ways, but 1st of all read: http://stackoverflow.com/questions/6441218/can-a-local-variables-memory-be-accessed-outside-its-scope – πάντα ῥεῖ Nov 30 '16 at 05:08
  • What exactly is there wrong with it? Am I not using pass by reference correctly by passing the size value using & and getting back the array through the return statement? The main program doesn't get terminated, so the memory holding size should still be in use and therefore no danger in it being overwritten. Could you point out what;s wrong with it? –  Nov 30 '16 at 05:19
  • Did you read the linked Q&A? – πάντα ῥεῖ Nov 30 '16 at 05:25
  • return automatic variable by pointer/reference is undefined behavior, `int newArray[size];` is not a C++ code, it's an extension. multiple read/write to same variable is undefined behavior – Danh Nov 30 '16 at 05:26
  • 2
    @John, if you use `gcc`, use the compiler flag `-Wall`. Then pay attention to the warnings issued by the compiler. – R Sahu Nov 30 '16 at 05:27

2 Answers2

1

First, standard C++ does not allow so-called variable-length arrays (VLAs); the size of the array in the declaration must be a compile-time constant. Standard C does allow them and both gcc and clang implement them as an extension. So technically, your code is ill-formed C++.

Let's accept the extension, for argument's sake. Now we have another problem, which is that arrays cannot be used as initializers for arrays. (An array could be used to initialize a pointer because the array will decay to a pointer in that context, but the pointer doesn't have a size at all. If you did tgat, though, you would introduce a different problem: the returned array has automatic storage duration which means that it is destructed and deallocated immediately. It is, therefore, a "dangling pointer" and using it is undefined behaviour.) You could work around that restriction a bit awkwardly by wrapping the array in a struct.

None of that touches the order of evaluation issue you are curious about. The answer is that the order is unspecified; the compiler might evaluate the function call before or after allocating space for the array. So even if your compiler allows VLAs, the size of this one is unspecified.

rici
  • 234,347
  • 28
  • 237
  • 341
  • We haven't learned about structs yet. The assignment asks to prompt the user for a size and threshold value. Once we have the size, we have to build the the dynamic array using built-in arrays to build an array of the size given. We then prompt the user for the elements inside the array. We then have to pass that array along the threshold value to another method, which will go through the array, remove any value that is above the threshold, sort the array in ascending order then add to it in descending order the same values. before returning it. no vectors allowed. How should i do it? –  Nov 30 '16 at 05:53
  • @John: if you are using standard C++, there is no way to allocate an array from a non `const` expression. – rici Nov 30 '16 at 06:07
0

You have a problem here:

 cin >> size; 
 int array[size];

Unless you use new you can't do that. The compiler creates the array container before the program runs, so you can't give it a custom size once it is running.

You must allocate your array as a new object on the heap:

cin >> size;
int* array = new int[size];

Maybe this will point you in the right direction, but I have no idea exactly what classes you are trying to call as you haven't included all of your source code.

I edited my previous answer, because I believe you are trying to simply call an array of ints, not a class called "array". If you just want a C-style array of integers, the above example is how you do it properly.

Keep in mind once you are done using the data you should call

delete[] array;
  • Doing int array[size] seems to work just fine when it's compiled under g++. But i will give your way a try. Just a couple of questions though. int*object is a pointer, what is array[size]? shouldnt it be int*array = new [size]? Also if I were to delete it at the end, should I just write delete[] array or delete[size] array? –  Nov 30 '16 at 06:03
  • @John... No need to specify size in delete. `delete[] array` will work fine. `new` always return object. for more info refer some good text. – someone Nov 30 '16 at 06:14
  • @John The reason gcc accepts your VLA is that by default it enables various non-standard extentions (-std=gnu... mode). If you tell it to work in strict C++ standard compliant mode with `-std=c++14` or `-std=c++11` you'll see that it rejects it. – Jesper Juhl Nov 30 '16 at 07:23
  • Yes @John you are absolutely correct in saying that it should be int* array = new int[size] and I have updated my answer to reflect this. – Dustin Nieffenegger Nov 30 '16 at 09:22
  • @Dustin Goodson, Thanks, I did it your way after all, worked nicely. Thank you so much –  Nov 30 '16 at 10:16