Compiled files in Visual Studio print desired result, but return errors in Unix terminal

I have linked my two files together and compiled them in a Unix terminal and this is the error message the compiler returns for line 31, 46, and 64:

"'sizeof' on array function parameter 'array' will return size of 'Rectangle*'"

What is odd is that when I build a solution out of my two files in Visual Studio, no compilation errors are returned and the console that Visual studio creates prints out the desired results. It is only when I link and compile the files manually in the Unix terminal using the command: "g++ -std=c++17 -o Exercise15 exercise15version2.cpp rectangle.h" that the above error message is returned.

Note: When compiling my files in both Visual Studio and in the Unix terminal, I am compiling in the c++17 standard for the sake of consistency.

Here are the two files:

main.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#include <stdio.h>
#include <string>
#include <iterator>
#include "rectangle.h"

void arrayValueAssignment(Rectangle array[]);
void findLargestArea(Rectangle array[]);
void findLargestPerimeter(Rectangle array[]);



int main()
{
	Rectangle rectangleArray[4];

	arrayValueAssignment(rectangleArray);

	findLargestArea(rectangleArray);

	findLargestPerimeter(rectangleArray);

	return 0;


}

void arrayValueAssignment(Rectangle array[])
{
	int currentLengthValue = 0;
	int currentWidthValue = 2; 

	for (unsigned int i = 0; i < std::size(array); i++)
	{
		currentLengthValue++;
		currentWidthValue *= 2;
		array[i].setLength(currentLengthValue);
		array[i].setWidth(currentWidthValue);

	}
}

void findLargestArea(Rectangle array[])
{
	int currentLargestArea = 0;
	int currentIndexWithLargestArea = 0;

	for (unsigned int i = 0; i < std::size(array); i++)
	{
		if (array[i].getArea() > currentLargestArea)
		{
			currentLargestArea = array[i].getArea();
			currentIndexWithLargestArea = i;
		}
	}

	printf("The largest area is %d and belongs to rectangle %d\n", 
currentLargestArea, currentIndexWithLargestArea + 1);

}

void findLargestPerimeter(Rectangle array[])
{
	int currentLargestPerimeter = 0;
	int currentIndexWithLargestPerimeter = 0;

	for (unsigned int i = 0; i < std::size(array); i++)
	{
		if (array[i].getArea() > currentLargestPerimeter)
		{
			currentLargestPerimeter = array[i].getPerimeter();
			currentIndexWithLargestPerimeter = i;
		}
	}

	printf("The largest area is %d and belongs to rectangle %d\n", 
currentLargestPerimeter, currentIndexWithLargestPerimeter + 1);

}


rectangle.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Rectangle
{
public:
	explicit Rectangle(int initialWidth = 0, int initialLength = 0) : 
storedWidth{ initialWidth }, storedLength{ initialLength } { };

	void setWidth(int widthInput)
	{
		storedWidth = widthInput;
	}

	void setLength(int lengthInput)
	{
		storedLength = lengthInput;
	}

	int getArea()
	{
		return (storedLength * storedWidth);
	}

	int getPerimeter()
	{
		return (storedLength * 2) + (storedWidth * 2);
	}


private:
	int storedWidth;
	int storedLength;

};
Last edited on

Hi,

Your error message line numbers don't seem to match your code. I see a std::size on line 66 of main.cpp

Maybe this is happening because an ordinary array decays to a pointer when passed to a function.

A better way of doing this would be to use a container like std::vector, it has it's own size function.

I would not have inline functions in a header file. Usually put the class declaration in the header file - I like to use *.hpp to mean a C++ header file. Put the implementation of the functions in the cpp file.

Also, try to use std::cout rather than C's printf I guess you are trying to make the transition from C to C++.

About compiling with g++, turn on all the warnings, don't compile the header file, it's included in the c++ files:

g++ - std=c++17 -Wall -Wextra -pedantic-errors exercise15version2.cpp -o Exercise15


Good Luck!!

You're just lucky that the size of the array you chose in main happens to be 4, which might also be what the size of a pointer is on your machine.

Arrays decay to being just pointers when passed to functions.
There is no way to recover the real size of an array from just a pointer.


> #include <stdio.h>
Lose this, include iostream and start using std::cout instead of printf()

It would be better to use std::vector or std::array.
1
2
3
4
5
6
7
8
9
#include <vector>
void arrayValueAssignment(std::vector<Rectangle> &myRects);
void findLargestArea(std::vector<Rectangle> &myRects);
void findLargestPerimeter(std::vector<Rectangle> &myRects);

int main()
{
	std::vector<Rectangle> myRects(4);
	arrayValueAssignment(myRects);
Also:

Put header guards in the header file, and /or #pragma once . once is not standard, but widely used.

The reason for header guards is for when a header is included in more than one place in the code, and is also why code is bad in header files.
Thank you all for the feedback. I have some questions since I still am a beginner at all this stuff. If all you want is to provide a link, that is fine, too, but learning C++ has been a very steep difficulty curve and any pointers (pun not intended) in the right direction is welcome. (You also don't have to answer. I just have been researching these questions and having a hard time finding answers in plain English for my dumb beginner brain).

1) What does it mean for an array to "decay" to being just a pointer, @salem c? If you passed a vector as a parameter, wouldn't it, too, be decaying to a pointer? Basically, why do vectors seem preferable to arrays in most cases?

2) What does it mean for the machine to have a designated pointer size?

3) Why is std::cout better to use than printf? I know that printf is a C function but I have never understood why std::cout is better. It has something to do with overloading bytes in to memory right?

4) Why should I not use <stdio.h>?

5) Just to be clear, @TheIdeasMan, are you saying the declaration for a class could be in a header file but the definition shouldn't?

Thank you, @TheIdeasMan. I always forget to put header guards. I need to make it more of a habit. I also forgot that you don't need to compile the header file since the main cpp file includes it.

Once again, thank you all for taking time out of your busy schedules to help me!




Last edited on
HI,

1. Because that's how it worked in C, so it works that way in C++ too. The C language used pointers heavily, and pointer arithmetic.

std::vector was invented to get around the problems that arrays had. std::vector is a templated class, not just a pointer to a hopefully contiguous area of memory. if you look at the documentation for std::vector you will see that it has some member functions, STL algorithms work with it, and perhaps the best thing, one can keep pushing more objects on the end, it automatically resizes.

2. there are 32 bit and 64 bit systems, they have 32 bit and 64 bit memory addresses respectively.

3. Partly because one should think in C++, not C: the two are quite different. Also:
https://stackoverflow.com/questions/2872543/printf-vs-cout-in-c

4. See num 3.

5. The reason one does this is because classes are reused. If you have code somewhere that needs to use a class, then #include the header file for it. The compiler can find the relevant cpp file by itself.

MyClass.hpp // the class declaration and definition

1
2
3
4
5
6
7
8
9
10
11
class MyClass {
public:
  MyClass() = default;
  MyClass( int IntegerArg);

 double  MyFunction(double FredArg);

private:
  int Integer;
  
};


MyClass.cpp function definitions

1
2
3
4
5
6
7
8
9
10
11
12
#pragma once // put header guards as well if you want

#include MyClass.hpp

MyClass::MyClass(const int IntegerArg) 
: // colon introduces member initialization list 
Integer{IntegerArg} // brace initialization, initializes Integer with IntegerArg value
{} // function body , do validation here

double MyClass::MyFunction(const double FredArg) {
  return FredArg;
}


I always forget to put header guards. I need to make it more of a habit.


If you use an IDE, it should do it for you. Use the IDE to make a class, rather than just typing it into files. It should create both files for you as well, maybe other stuff too - you may be able to specify what member variable and functions you want - it could make function stubs for these.
Thank you for answering, @TheIdeasMan. Your input is very helpful. I still have a question about what you said, though. Why wouldn't I just define and declare the functions in the same header file? Wouldn't that be more efficient? I know that classes are reusable but couldn't you import a header file containing a class in to any cpp file where it needed to be used?

Nevermind. I am reading about header guards and realizing why it is bad to have the definition and declaration in the same header file. This is because if two files both import the same header file with a function definition, then the linker will complain about the function having two definitions. That is why, isn't it?
Yes.

Good Luck !!
Topic archived. No new replies allowed.