C - passing an array by reference - only first element set - c++

I have a function which should modify an array (of floats) in the original parent function. I am using the following code:
void sortFunction(Word**words, int wordCount){ //to sure if two * are correct (pointer to an array..?)
int i = 0;
for(i=0;i<wordCount-1;i++){
Word first = *words[i]; //values fine
Word second = *words[i+1]; //weird values, causes segfault
if(first.data[0] > second.data[0]){
//do stuff
}
}
}
int main(int argc, char ** argv){
Word* words = NULL;
int wordsCount = ...
//filling the array in a loop and using realloc for memory allocation
//Here, the array is filled correctly (verified)
sortFunction(&words, wordsCount);
}
Where Word is a typedef struct and Word.data is the (dynamic) float array. When checking in the parent function, the array is allocated and the values set correctly.
I have tried with about 10 elements in the array, but always only the first ([0]) element is fine in the sortFunction(), second and all others are messed up. I also have an int propery in the struct, and when I try to print it for the second element, I get something over 1 billion.
I assume I am not passing the array correctly - I use the following code (just a sample) to pass regular variables, so I tried to modify it for an array, but apparently, not correctly. What is the right way to do this for an array?
void foo(int*var){
*var=8;
}
int main(){
int var = 5;
changeVar(&var);
}
Thanks in advance for any tips!

Postfix [] has higher precedence than unary *, so *words[i] is parsed as *(words[i]), which isn't what you want.
You need to dereference the words pointer before applying the subscript, so you need to explicitly group the * operator with words using parentheses:
Word first = (*words)[i];
Word second = (*words)[i + 1];

First, you do not need to pass **, just one is enough, because you will be passing the address of your array anyway:
void sortFunction(Word* words, int wordCount)
and call it as:
sortFunction(words, wordsCount);
Second, the Undefined behavior originates in the following statement:
Word first = *words[i]; Word second = *words[i+1];
It should have been (*words)[i] but still, you are copying structs, so your dynamic data array is not copied correctly. avoid this useless copy, and use this instead, AFTER changing the protoype of sortFunction:
Word* first = &words[i];
Word* second = &words[i+1];
if(first->data[0] > second->data[0])
p.s: This does not guarantee that the rest of your code is correct, just comments of the parts you showed of the code.

Related

Difference between int * array[60] and int * array = new int(60);

int * array[60]; //creates an array of 60 pointers to an int
int * array = new int(60); //same thing?
Do these both result in the same type of array? e.g an array of pointers to integers
I know that the first one uninitialized, and the second one is initialized, but I am unsure of what exactly the second one creates.
int * array = new int(60); //same thing?
No, they're not the same thing. array is just a pointer here, and then point to an int with initialized value 60.
If you meant int * array = new int[60];, array will point to an array of 60 ints, they're still not the same thing.
Note that just as the declaration, int* array means it is a pointer, while int* array[60] means it is an array (of 60 pointers). (Array might decay to pointer, i.e. int** for int* array[60], it's not same as int*.)
Perhaps you do not realize that the second case is not an array, the following program prints 60:
#include <iostream>
int main() {
int* foo = new int(60);
std::cout << *foo << '\n';
return 0;
}
Here are two pictures that illustrate the differences between
int * array[5];
and
int * array = new int(5);
To create a pointer int array use int * array = new int[5];
code,
debug view
One of them creates an array, the other doesn't.
int * array[60]; // Creates an array of 60 integer pointers
To help understand the difference, take into account that the first line creates a 60 pointers-block in memory (in the stack if you are inside main, for example), but the second one only a pointer block.
Both are completely different types. For example, try the following:
array++;
In the first line, it does not work. In the second one, it's ok. If you try:
array[0]++;
In the first line you change the first pointer, in the second one you add 1 to the integer (change to 61).

Function to modify array - Pointer as input

I want to make a function which takes an existing 9x9 empty array of integers, and inserts values taken from a file (so the function also gets the file name as input). But I cant really figure out how to do this properly, even though I've tried quite a few different methods. Basically, here is what I do:
int board = new int[9][9] //The empty array
int addToArray(int *board, string filename) {
/* Code to insert values in each field is tested and works so
I will just show a quick example. The below is NOT the full code */
int someValue = 5;
board[0][0] = someValue;
/* Return a value depending on whether or not it succeeds. The variable 'succes'
is defined in the full code */
if (succes) {
return 0;
} else {
return -1;
}
}
This is a very reduced example, compared to the actual code, but it is overall function of passing a pointer to a an array into some function, and have that function modifying the array, that I want. Can anyone tell me how to do this?
In case anyone ever ends reading the question, I used method number 3 from Johnny's link. I copy pasted the code and added some comments, for convenience...
// Make an empty, and un-sized, array
int **array;
// Make the arrays 9 long
array = new int *[9];
// For each of the 9 arrays, make a new array of length 9, resulting in a 9x9 array.
for(int i = 0; i < 9; i++)
array[i] = new int[9];
// The function to modify the array
void addToArray(int **a)
{
// Function code. Note that ** is not used when calling array[][] in here.
}
passFunc(array);
It should be simply
int **board
in the function arguments.
The simple rule is that *name = name[ ], so as many [ ] you have in the array, you need to have as many * in the parameters.

Returning two dimensional array of strings

string** flowFile() {
string line;
string word[8];
int i=0;
static string flow[23][2];
ifstream myfile ("test.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
strSplit(line,word);
flow[i][0]=word[1];
flow[i++][1]=word[2];
}
myfile.close();
}
else cout << "Unable to open file";
return flow;
}
int main()
{
string **fl=flowFile();
}
I'm getting this error:
error: cannot convert ‘std::string (*)[2] {aka std::basic_string<char> (*)[2]}’
to ‘std::string** {aka std::basic_string<char>**}’
in return
What is wrong with my code?
string flow[23][2] and string ** are two different incompatible types. One cannot convert to another implicitly. Thats all. The solution is to make them compatible, by making the later string [23][2], return reference and accept reference, but that would still be a bad solution, because you're still working with raw arrays.
A good solution is to use std::vector and std::string. Maybe, you need std::pair also, or std::array.
Here is one possible solution:
#include <vector>
#include <array>
#include <string>
//C++11 style typedef
using flow_data_t = std::vector<std::array<std::string,2>>;
//reimplementation of your function
flow_data_t flowFile()
{
std::string line;
std::string word[8];
int i=0;
flow_data_t flow;
std::ifstream myfile ("test.txt");
if ( !myfile )
cout << "Unable to open file";
while ( std::getline (myfile,line) )
{
strSplit(line,word);
flow.push_back({word[0], word[1]});
}
return flow;
}
int main()
{
flow_data_t data=flowFile();
for(auto const & row : data)
for(auto const & col : row)
//work!
}
Hope that helps.
You cannot return array from a function even though you can return a pointer and let your array decay to a pointer: Array Decay
However 2D array can decay to neither T* nor T** because of the memory layout of the array is different from "2D pointer array" (it is actually more like flattened), and you cannot return array from function. However in C++ you can return array reference Full Code:
//This does not work
//typedef string * string2d[2];
//typedef string *(&string2d)[2];
typedef string (&string2d)[23][2];
string2d flowFile() {
static string flow[23][2];
return flow;
}
Array reference would even preserve the information of how big each row and columns are and no array decaying happen.
Of course, a more suggested "C++ way" to do this is using std::vector (as always).
In C++, arrays have type std::vector. You should use these, not low-level builtin arrays declared with [].
In C++, string [23] is sometimes interchangeable with string*, but string[23][2] is never interchangeable with string**. That's one reason you should not use builtin arrays.
In C++, you cannot return a local builtin array variable. It will compile but then your program will probably crash. This is another reason you should not use builtin arrays. (Returning a static array should be OK though).
There are many more reasons.
There is nothing wrong with returning a pointer to a static variable. It's just that the return type must be declared properly. It kind of makes sense if you try to reproduce what the declarations mean, and what the compiler accordingly tries to do. Consider the declaration static string flow[23][2];. It declares 23 rows of strings, each with 2 elements. It helps if you look at it as a one-dimensional array. It just so happens that the array elements are arrays, but that's not so important right now (but we'll come back to it). From this perspective the array has just 23 elements, and each element has the size of 2 strings. Like with all arrays, the elements (here: arrys of 2 strings) are simply lined up in memory.
Like any array, flow will in most contexts decay to a pointer to its first element. Incrementing that pointer will point to the next element, i.e the second row. Numerically the compiler must add 2*sizeof(string) to the address of flow in order to compute the address of flow's next element, which would be flow[1]. (It comes directly behind flow[0]. No magic here.)
Now if you declare string **flowpp, flowpp is a pointer already, no need to decay. If we think it is pointing to the first element in an array, what type would the elements have? Sure enough: plain pointers. Incrementing flowpp would let it point to the next element. My pointers are 4 bytes large, so that numerically adding just 4 to flowpp would be enough to access flowpp's next element. Compared to what needs to be added to flow (remember, 2*sizeof(string)), that's completely different. The compiler computes the offsets of elements depending of what the pointers point to! Which is very different in the two cases.
So what can your function return? What does flow decay to when you return it? It decays to a pointer to its first element. The elements are arrays of two strings. It must be string xxx[2], with xxx being a pointer: hence string (*p)[2]. If the pointer is actually returned by a function, we have a function call instead of plain p, so it's (*f())[2].
Here is a complete example:
#include<iostream>
using namespace std;
const int numFlowElems = 3, numArrElems = 2;
/** #return a pointer to the first element of a static array
of string[numArrElems]s.
*/
string (*flowFile())[numArrElems]
{ // init so that we see something below.
static string flow[numFlowElems][numArrElems]
= {{"1","2"},
{"3","4"},
{"5","6"}
};
// your function code ...
return flow;
}
int main()
{
// array decays to ptr, like usual. Ptr elems are string[numArrElems].
// ptrToArr is a pointer to arrays of two strings.
string (*ptrToArr)[numArrElems] = flowFile();
for( int flowInd= 0; flowInd<numFlowElems; ++flowInd )
{
for(int strInd = 0; strInd<numArrElems; ++strInd)
{
cout << ptrToArr[flowInd][strInd] << ' ';
}
cout << endl;
}
return 0;
}
How do you parse string (*flowFile())[numArrElems]? I needed two attempts to get the declaration right, if that's any consolation. The key is that in C and C++ (not in C#, mind you!) a declaration has the shape of an expression.
You can do it from the inside to the outside: flowFile() is a function. The result is dereferenced because the function call has higher precedence than the star: *flowFile() is the dereferenced result. Apparently that result is an array of size numArrElems, with elements which are strings.
You can do it outside in: The result of (*flowFile())[numArrElems] is declared as a string. (*flowFile()) is an array of strings with numArrElems elements. Apparently flowFile() must be dereferenced to obtain that array so that flowfile is a function which returns a pointer to an array of numArrElems strings. That's true! It returns the first element of flow, which is exactly an array of strings.
Vectors of vectors might indeed be easier; if you want to retain the semantics you should pass references, as others mentioned: After all, all functions in your original program will operate on the same static array. If you pass vectors by value that will not be the case any longer. But then, that may actually be beneficial.

Get the length of an array which contains an element 0 while passing to a function

Is there any way to print length of an array which contains an element 0 and that array has been passed to a function which can have only one argument as the array?
Example:
int arrLen(int arr[])
{
//get size here;
}
int main()
{
int arr[]={0,1,2,3,4,5};
arrLen(arr);
}
There is a limitation in C++ that we can not compare the elements of an array with a NULL if it has a zero, but still asking if there is a way to do that. I can only pass array to function is my limitation.
In your very example, you can use function template to get what you want:
template <size_t N>
int arrLen(int (&arr)[N])
{
return N;
}
The only answer is that you can't get the size of the array once it's been passed as an argument. You have to remember that when passing an array as an argument, it decays to a pointer, and the compiler have no idea of what the pointer actually points to. You should also remember that sizeof is a compile-time operation, the result of a sizeof operation is done by the compiler, and not at runtime.
You either have to put a special end-of-array marker, like strings use the '\0' character to mark the end of a string, at the end of the array (note that this end-of-array marker can be anything that's not supposed to be in the array, be it a zero, -1 or something else). Or you have to pass the length as an argument to the function.
In C when pass an array as an argument to a function, you're passing a pointer to the first element. If you want to pass the size of the array, you should pass it as a separated argument.
You can store the length of the array in the first element of it:
int arr[] = {-1,0,1,2,3,4,5};
arr[0] = sizeof(arr) / sizeof(arr[0]) - 1;
After you do this, you'll get the array's size in arr[0].
There's two ways to achieve what you want:
Know the size of the array - you have to either hard-code it in the function, or pass it as parameter.
Use a sentinel value. When you find the sentinel value, you know you've reached the end of the data. For example, C strings work using \0 as a sentinel.
The latter one seems to be applicable here (e.g. using INT_MIN as sentinel), but unless you have very good reasons, don't do it. Simply pass the length.
Since you control the function that computes the array length, you could decide that a specific int value (or even sequence) such as -1 marks the end of your array. You can then implement your arrLen function like this (with additional improvements for e.g. int overflow):
int arrLen(int arr[])
{
int size = 0;
int* p = arr;
while (*p != -1) {
++size;
++p;
}
return size;
}
then, of course, you need to properly "close" your array on the calling site, or you'll run into trouble:
int arr[]={0,1,2,3,4,5, -1 };
Thanks for the help, but that is my limitation to pass only 1 argument into the function and that can only be an array.
anyways I just wrote that main function to make an understanding, but actually that main function is not available to me. So finally I end up with a function which can get an argument that can be an int array and return the size of array.
I tried with something that to convert my int array into an ascii array of those int values and since a NULL or '\0' can never be equal to a '0', so comparing them with NULL up to the end of an array is possible.
But again I got stuck when I'm going to convert the array, I required the length.

How do I find the length of "char *" array in C?

I declare the following array:
char* array [2] = { "One", "Two"};
I pass this array to a function. How can I find the length of this array in the function?
You can't find the length of an array after you pass it to a function without extra effort. You'll need to:
Use a container that stores the size, such as vector (recommended).
Pass the size along with it. This will probably require the least modification to your existing code and be the quickest fix.
Use a sentinel value, like C strings do1. This makes finding the length of the array a linear time operation and if you forget the sentinel value your program will likely crash. This is the worst way to do it for most situations.
Use templating to deduct the size of the array as you pass it. You can read about it here: How does this Array Size Template Work?
1 In case you were wondering, most people regret the fact that C strings work this way.
When you pass an array there is NOT an easy way to determine the size within the function.
You can either pass the array size as a parameter
or
use std::vector<std::string>
If you are feeling particularly adventurous you can use some advanced template techniques
In a nutshell it looks something like
template <typename T, size_t N>
void YourFunction( T (&array)[N] )
{
size_t myarraysize = N;
}
C is doing some trickery behind your back.
void foo(int array[]) {
/* ... */
}
void bar(int *array) {
/* ... */
}
Both of these are identical:
6.3.2.1.3: Except when it is the operand of the sizeof operator or the unary & operator,
or is a string literal used to initialize an array, an expression that has type
‘‘array of type’’ is converted to an expression with type ‘‘pointer to type’’
that points to the initial element of the array object and is not an lvalue. If
the array object has register storage class, the behavior is undefined.
As a result, you don't know, inside foo() or bar(), if you were
called with an array, a portion of an array, or a pointer to a single
integer:
int a[10];
int b[10];
int c;
foo(a);
foo(&b[1]);
foo(&c);
Some people like to write their functions like: void foo(int *array)
just to remind themselves that they weren't really passed an array,
but rather a pointer to an integer and there may or may not be more
integers elsewhere nearby. Some people like to write their functions
like: void foo(int array[]), to better remind themselves of what the
function expects to be passed to it.
Regardless of which way you like to do it, if you want to know how long
your array is, you've got a few options:
Pass along a length paramenter too. (Think int main(int argc, char
*argv)).
Design your array so every element is non-NULL, except the last
element. (Think char *s="almost a string"; or execve(2).)
Design your function so it takes some other descriptor of the
arguments. (Think printf("%s%i", "hello", 10); -- the string describes
the other arguments. printf(3) uses stdarg(3) argument handling, but
it could just as easily be an array.)
Getting the array-size from the pointer isn't possible. You could just terminate the array with a NULL-pointer. That way your function can search for the NULL-pointer to know the size, or simply just stop processing input once it hits the NULL...
If you mean how long are all the strings added togather.
int n=2;
int size=0;
char* array [n] = { "One", "Two"};
for (int i=0;i<n;++i)
size += strlen(array[i];
Added:
yes thats what im currently doing but i wanted to remove that extra
paramater. oh well –
Probably going to get a bad response for this, but you could always use the first pointer to store the size, as long as you don't deference it or mistake it for actually being a pointer.
char* array [] = { (char*)2,"One", "Two"};
long size=(long)array[0];
for(int i=1; i<= size;++i)
printf("%s",array[i]);
Or you could NULL terminate your array
char* array [] = { "One", "Two", (char*)0 };
for(int i=0;array[i]!=0;++i)
{
printf("%s",array[i]);
}
Use the new C++11 std::array
http://www.cplusplus.com/reference/stl/array/
the standard array has the size method your looking for