Click here to Skip to main content
15,895,709 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
See more:
// for union of two arrays
C++
int* uni(int len1, int len2, int set1[], int set2[])
{
	int set3[20], i, j, k, flag;

	k = 0; 
	
	// Copies the elements of the first set to  new set
	for (i = 0; i < len1;i++)
	{
		set3[k] = set1[i];
		k++;
	}
	
	for (i = 0; i < len2; i++)
	{
		flag=1;

		//Combines the sets 1 and 2
		for (j = 0;j < len1; j++)
			if(set2[i]==set1[j])
			{
				flag=0;
				break;
			}
		
			if(flag==1)
			{
				set3[k]=set2[i];
				k++;
			}
	}	
	
	return set3;
}


What I have tried:

i tried doing it as return set3[20] then it says that [warning] return makes integer from pointer without a cast
Posted
Updated 11-Apr-20 8:11am
v2

There are various ways to fix this:

1. Make int3 a global variable. This is usually the least appealing solution.
2. Make int3 a variable in the function that calls uni, and pass it to uni as an argument. This is OK if int3 is only needed within the calling function.
3. Make int3 a member variable of the class that calls uni, and pass it to uni as an argument. This would be done if the class needs to use uni later.
4. Allocate int3 from the heap, using new. This could be done by uni or by the functions that call it. When int3 is no longer required, free it using delete. If you're using C++11 or later, it's better to put int3 in a unique_ptr using make_unique, after which it can be freed using unique_ptr::reset. In most cases, uni (even if wrapped by a unique_ptr) would still be a member of some class, in which case int3 will automatically be freed when the class is deleted. Or if the unique_ptr is local to a function, int3 will automatically be freed when the function returns.
 
Share this answer
 
v4
Comments
Member 14798802 11-Apr-20 6:33am    
i see thankyou
Greg Utas 11-Apr-20 6:50am    
I forgot to mention making int3 a member of a class, which is another way to fix this. I also added some notes about when to use each approach.
Just to add to Greg's answer - which is correct - I'll just briefly explain why it's a problem.

There are two types of memory available to you app: Heap and Stack.
Heap is big - potentially the size of your RAM plus your HDD free space, and is created using either malloc or new (preferably the latter). This is used for most of your data.
Stack is small - typically around 1MB - and it's allocated "behind the scenes" when you call a function. When you do that, teh address the program needs to return to is pushed on the stack, and space is allocated for every local variable in your function. When you return from the function, that stack space is reclaimed, and the return address popped off, then the program continues from the instruction after the call. Each time you call the function, you get a new set of local variables and a new return address. .If you think about it, that's the only way iot can work, because otherwise recursive functions calls wouldn't work at all!

The problem is that iot means all local variables are temporary: they "cease to exist" when the function stops executing. And that's fine ... unless you return a pointer to one of them ...
Then the pointer is fine, your code will work, but as soon as you call another function, the memory it is pointing to will get reused and your values will get overwritten. This pointer is called a "hanging reference" and the compiler is thankfully bright enough to spot them and warn you so you don't get some really-hard-to-track-down bugs creeping in later!

You should only return a pointer to heap memory, never to a local variable - it's really hard to fix problems like that because they either don't normally show up for weeks or months, or they cause you application to crash randomly when executing totally unrelated code!
 
Share this answer
 
Quote:
How do I fixed the [warning] function returns address of local variable [-wreturn-local-addr] , the warning is on return set3

A local variable is allocated on stack, this means that as soon as you return from that function, that stack space is unallocated. This means that any call to another function will overwrite that variable.

Solutions are:
- allocate result array in the calling code and use a pointer to the array to tell the called function where to store the result.
- have the called function to allocate the array on heap (malloc), but the calling code will be in charge of freeing the array.
 
Share this answer
 
A proper (at least I hope) C implementation
Note it is a precise responsibility of the caller to release memory.
C
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <assert.h>

int * uni(int set1[], size_t size1, int set2[], size_t size2, size_t * psizer);

int main()
{ 
  int set1[] = {3, 5, 6,-1, 42, 28};
  int set2[] = {100, 5, -23, 42,18};
  
  size_t size1 = sizeof(set1) /sizeof(set1[0]);
  size_t size2 = sizeof(set2) /sizeof(set2[0]);
  
  int * set3;
  size_t size3;
  
  set3 =  uni(set1, size1, set2, size2, &size3);
  
  if ( set3 )
  { 
    for (size_t i = 0; i<size3; ++i)
      printf("%d ", set3[i]);
    printf("\n");
    free(set3);
  }
  return 0;
}

int * uni(int set1[], size_t size1, int set2[], size_t size2, size_t * psizer)
{ 
  assert( set1 &&  set2 && psizer);
  int * setr = (int * ) malloc( (size1+size2) * sizeof(setr[0]));
  if ( ! setr ) return NULL;
  
  memcpy( setr, set1, size1 * sizeof(set1[0]));
  *psizer = size1;
  
  for (size_t i = 0; i<size2; ++i)
  { 
    size_t j; 
    for (j=0; j<size1; ++j)
    { 
      if (set2[i] == set1[j])
        break;
    }
    if ( j == size1 )
    { 
      setr[(*psizer)++] = set2[i];
    }
  }
  setr = realloc( setr, *psizer*sizeof(setr[0]));
  return setr;
}


C++ on the other hand, with the power of its standard library allows you a completely different approach
C++"
#include <iostream>
#include <set>
using namespace std;

int main()
{
  set<int> set1{3, 5, 6,-1, 42, 28};
  set<int> set2{100, 5, -23, 42,18};

  set<int> setr{set1};
  setr.insert( set2.begin(), set2.end() );
  for (auto x : setr)
    cout << x << " ";
  cout << endl;
}
 
Share this answer
 
v4
The easiest way is to make your result array to an input parameter

C++
void uni(int len1, int len2, int set1[], int set2[], int set3[])

tip: rename the parameters and variables to a more speaking naming

bonus: you may also use reference syntax (&-operator).
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900