Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
I had to convert a C++ program to C, which has been done. The question is whether the codes presented are equivalent and whether I missed anything.
Both codes presented are complete and should compile. Both give the same answers when run, too. But I am new to C++ and I don't know if I missed something in my conversion that might be important.
One more question, in the C++ code, int x and int y were declared as global, I don't have, and don't think I need anything analogous to that, but I don't really know what they are doing. Guidance?
C++
#include <iostream>
// a point on the integer grid
struct Point
{
// constructor
Point()
{
x = y = 0;
}
// add point componentwise
void add(const Point &p)
{
x += p.x;
y += p.y;
}
// print to standard output
void print() const
{
std::cout << "[" << x << "," << y << "]" << std::endl;
}
// data
int x, y;
};
int main()
{
const int N = 200;
Point *A = new Point[N], sum;
for (int i=0; i < N; ++i) {
sum.print();
A[i].x = i; A[i].y = -i;
sum.add(A[i]);
}
sum.print();
delete [] A;
}
C
#include <stdio.h>
#include <stdlib.h>
typedef struct //constructor
{
int x;
int y;
} Point;
void add(const Point * p, Point * sum)
{
(*sum).x += (*p).x;
(*sum).y += (*p).y;
}
void print(const int x, const int y)
{
printf("[%d,%d]\n", x, y);
}
int main()
{
int i = 0;
const int N = 200;
Point *A = malloc(N*sizeof(Point)), sum;
if(!A)
{
printf(stderr, "malloc() failed to allocate memory!");
abort();
}
sum.x =0;
sum.y = 0;
for (i = 0; i <N; i++)
{
print (sum.x, sum.y);
A[i].x = i; A[i].y = -i;
add(&A[i], &sum);
}
print(sum.x, sum.y);
free(A);
return 0;
}
It is fairly equivalent functionally (aside from the constructor issue, see below). But for some reason it contains a number of inconsistencies and "illogical" stylistic decisions.
The "standard" approach to approximate a C++ method by a C function is to implement the C++ implicit this parameter through an explicit parameter. That would make your add function look as follows
void add(Point *this, const Point *p)
{
this->x += p->x;
this->y += p->y;
}
Note that in C++ version you could also use the this->x syntax on the left-hand side (instead of just x), which would only emphasize the similarity. Obviously, my version above is the same as yours, but arranged in what I believe is more "traditional" fashion.
You forgot to define a "constructor" for your Point in C version of the code. In C++ code your Point objects begin their lives initialized to zero. In C code these objects begin their lives with garbage in x and y. Later you assign definitive values to x and y, which makes the non-initialization issue non-consequential, but still it is there.
Of course, if you decide to implement a "constructor" function, you will have to call it manually for each array element, while in C++ it is called automatically for you.
For some reason you decided to "disassemble" the object into x and y parameters for print function. Why? Again, the same approach with an explicit this parameter can be used for print and it would look as follows
void print(const Point *this)
{
printf("[%d,%d]\n", this->x, this->y);
}
In your current version
void print(const int x, const int y)
const qualifiers applied to parameters achieve virtually nothing useful and do not promote equivalence to the C++ version (i.e. these const qualifiers are not equivalent to that trailing const in the C++ version).
But, in any case, these are purely stylistic suggestions.
Note also that in C++ language
const int N = 200;
defines a constant, while in C language it does not define a constant. In C it defines what essentially is a "non-modifiable variable". But this is completely non-consequential for your code, since your code does not care whether N is a constant or not. (I don't know whether you care about this sort of pedantic equivalence.)
It depends on the level of 'equivalency' you're looking for. In the C version you don't have a function equivalent to the Point constructor and you avoid the default initialization on the array of points, your C print function operates on ints instead of a Point object, and I see some const mismatches such as the fact that your C add function takes a pointer to non-const Point on the right hand side while the C++ version takes a reference to const Point.
Related
I know this is already a commonly asked question, but I'm more curious about how pointers and references behave at a lower level (like how compiler deals with them, and how they look like in memory), and I didn't find a solution, so here I am.
At first I was wondering if an array can be passed as a parameter without being cast (or decay) into a pointer. More specifically. I would like the following code:
void func(?? arr) {
cout << sizeof(arr) << "\n";
}
int main() {
int arr[4];
func(arr);
return 0;
}
to output 16 instead of 8, which is the size of a pointer.
First I tried
void func(int arr[4]);
Hoping that specifying the size can keep the property of an array, but arr is still treated as a pointer.
Then I found something that worked:
void func(int (&arr)[4]);
But it confused me.
In the past I was under the impression that although pointers and references had different meanings, they had the same behavior when the code was actually executed.
I got that idea from my own experiments:
void swap(int* a, int* b) {
int c = *a;
*a = *b;
*b = c;
}
int main() {
int a = 3, b = 5;
swap(&a, &b);
}
and
void swap(int& a, int& b) {
int c = a;
a = b;
b = c;
}
int main() {
int a = 3, b = 5;
swap(a, b);
}
were compiled into the same assembly code, and so did
int main() {
int a = 3;
int& b = a;
b = 127;
return 0;
}
and
int main() {
int a = 3;
int* b = &a;
*b = 127;
return 0;
}
I turned off optimization and both g++ and clang++ showed this result.
Also my thought on the first experiment:
when thinking in terms of memory, swap should have its own stack frame and local variables. Having a in swap directly mapped to the a in main didn't make much sense to me. It was as if the a in main magically appeared in the stack frame of swap, where it shouldn't belong. So it didn't surprise me that it got compiled into the same assembly as the pointer version. Maybe the magic of reference was achieved by a pointer underneath the hood. But now I'm not sure.
So how does a compiler handle references and how do references look like in memory? Are they variable that occupies space? And how can I explain the result of my experiments and the array problem?
The old C idiom is, that arrays get turned into pointers to the array type, when a function is called. And that is mostly still true für C++.
So for the details of it, let's look at two functions taking an integer argument, first:
void f(int x) { x = 42; } // function called with x by value
void g(int& x) { x = 42; } // function called with x by reference
As f() is called by value, a copy of the argument is made, and the assignment x = 42; inside the function has effectively no effect for the caller of the function. But for g(), the assignment of x becomes visible to the caller:
int a = 0, b = 0; // initialize both a and b to zero
f(a); // a is not changed, because f is called by value
g(b); // b is changed, because g is called by reference
std::cout << a << " " << b << std::endl; // prints 0 42
For arrays, the same rules should hold, but don't. So let's try it:
void farr(int x[4]) { x[0] = 42; } // hypothetical call by value
void garr(int (&x)[4]) { x[0] = 42; } // call by reference
And let's call these functions:
int c[4] = { 1, 2, 3, 4 }, d[4] = { 5, 6, 7, 8 };
farr(c); // call by value?
garr(d); // call by reference
for(unsigned i = 0; i < 4; i++)
std::cout << c[i] << (i < 3 ? ", " : "\n");
for(unsigned i = 0; i < 4; i++)
std::cout << d[i] << (i < 3 ? ", " : "\n");
The unexpected result is, that the farr() function (unlike the f function before) does modify its array, too. The reason is an old C idiom: Because arrays must not be copied directly by assignment, functions cannot be called with arrays by value. Therefore array declarations in parameter lists are automatically converted into a pointer to the first element of the array. So the following four function declarations are syntactically identical in C:
void farr1(int a[]) {}
void farr2(int a[4]) {}
void farr3(int a[40]) {}
void farr4(int *a) {}
Being compatible with C, C++ took over that property. So it is not a syntactical error (but likely causes undefined behaviour!) to call farr2() or farr3() with an array of different size. Furthermore, though, references come in in C++. And yes, as you already suspected, a reference to an array is internally represented as a pointer to the first array element. But, and that is the advantage of C++: If you call a function, that expects a reference to an array (and not just an array or a pointer), the size of array is actually validated!
So, calling farr() with an int-Array of size 5 is possible, calling garr() with the same leads to an compiler error. That gives you better type checking, so you should use it, whereever possible. And it even allows you to pass the array size to a function by using a template:
template<std::size_t N>
void harr(int (&x)[N]) { for(std::size_t i = 0; i < N; i++) x[i] = i*i; }
I understand how arrays can be passed to functions in c++, but I don't understand what is the point of including array's size in a function declaration when this size is ignored anyway, because what we are really passing to function is a pointer to the first element of the array.
For example if we have following code:
void ArrayTest1(int(&ints)[3])
{
for (int i = 0; i < 3; i++) std::cout << ints[i];
}
void ArrayTest2(int ints[3])
{
for (int i = 0; i < 3; i++) std::cout << ints[i];
}
void ArrayTest3(int ints[])
{
for (int i = 0; i < 3; i++) std::cout << ints[i];
}
int main()
{
int ints[] = { 1, 2 };
//ArrayTest1(ints); //won't compile
ArrayTest2(ints); //ok
ArrayTest3(ints); //ok
return 0;
}
Then from what I understand functions ArrayTest2 and ArrayTest3 are identical.
Is syntax used in ArrayTest2 only meant to make it clear that this function expects an array with 3 elements and passing array with a different size can cause errors? I'm not new to programming, but I'm new to c++ so I'd like to know what is the point of such syntax and when do people use it.
One of C++’s major design goals was far reaching compatibility with C. Not supporting all aspects of C-array usage would have been seriously detrimental to this goal.
Your examples even give a good indication that compatibility is indeed the intent, and that C++ would work differently if that hadn’t been the case. Consider your ArrayTest1(). It takes a C-array by reference, something that does not exist in C. And in this case the array dimension is significant.
// C-array of length 3 taken by reference
void foo(int (&x)[3]);
void bar() {
int a[4] = {1,2,3,4};
foo(a); // Does not compile. Wrong array size.
}
Only ArrayTest2() and ArrayTest3() are exactly equivalent to:
void foo(int*);
Btw: Bjarne Stroustrup’s The Design and Evolution of C++ is a good read if you’re interested in why C++ is designed the way it is.
I don't exactly know why C permits this (yes, this comes from C), but it is indeed pointless.
Worse than that, the "wrong" dimension would be very misleading to readers of your code.
We might argue that it was to keep the language grammar simple, as the grammar of a declarator already makes the dimension optional (consider int x[] = {1,2,3} vs int x[3] = {1,2,3}).
Maybe some people use it to document intent; I certainly never would.
I am a beginner in C++ and want to do simple example of composite function.
For example, in MATLAB, I can write
a = #(x) 2*x
b = #(y) 3*y
a(b(1))
Answer is 6
I searched following questions.
function composition in C++ / C++11 and
Function Composition in C++
But they are created using advanced features, such as templates, to which I am not much familiar at this time. Is there a simple and more direct way to achieve this? In above MATLAB code, user does not need to know implementation of function handles. User can just use proper syntax to get result. Is there such way in C++?
** Another Edit:**
In above code, I am putting a value at the end. However, if I want to pass the result to a third function, MATLAB can still consider it as a function. But, how to do this in C++?
For example, in addition to above code, consider this code:
c = #(p,q) a(p)* b(q) %This results a function
c(1,2)
answer=12
d = #(r) a(b(r))
d(1)
answer=6
function [ output1 ] = f1( arg1 )
val = 2.0;
output1 = feval(arg1,val)
end
f1(d)
answer = 12
In this code, c takes two functions as input and d is composite function. In the next example, function f1 takes a function as argument and use MATLAB builtin function feval to evaluate the function at val.
How can I achieve this in C++?
How about:
#include <iostream>
int main(int, char**)
{
auto a = [](int x) { return 2 * x; };
auto b = [](int y) { return 3 * y; };
for (int i = 0; i < 5; ++i)
std::cout << i << " -> " << a(b(i)) << std::endl;
return 0;
}
Perhaps I'm misunderstanding your question, but it sounds easy:
int a(const int x) { return x * 2; }
int b(const int y) { return y * 3; }
std::cout << a(b(1)) << std::endl;
Regarding your latest edit, you can make a function return a result of another function:
int fun1(const int c) { return a(c); }
std::cout << fun1(1) << std::endl;
Note that this returns a number, the result of calling a, not the function a itself. Sure, you can return a pointer to that function, but then the syntax would be different: you'd have to write something like fun1()(1), which is rather ugly and complicated.
C++'s evaluation strategy for function arguments is always "eager" and usually "by value". The short version of what that means is, a composed function call sequence such as
x = a(b(c(1)));
is exactly the same as
{
auto t0 = c(1);
auto t1 = b(t0);
x = a(t1);
}
(auto t0 means "give t0 whatever type is most appropriate"; it is a relatively new feature and may not work in your C++ compiler. The curly braces indicate that the temporary variables t0 and t1 are destroyed after the assignment to x.)
I bring this up because you keep talking about functions "taking functions as input". There are programming languages, such as R, where writing a(b(1)) would pass the expression b(1) to a, and only actually call b when a asked for the expression to be evaluated. I thought MATLAB was not like that, but I could be wrong. Regardless, C++ is definitely not like that. In C++, a(b(1)) first evaluates b(1) and then passes the result of that evaluation to a; a has no way of finding out that the result came from a call to b. The only case in C++ that is correctly described as "a function taking another function as input" would correspond to your example using feval.
Now: The most direct translation of the MATLAB code you've shown is
#include <stdio.h>
static double a(double x) { return 2*x; }
static double b(double y) { return 3*y; }
static double c(double p, double q) { return a(p) * b(q); }
static double d(double r) { return a(b(r)); }
static double f1(double (*arg1)(double))
{ return arg1(2.0); }
int main()
{
printf("%g\n", a(b(1))); // prints 6
printf("%g\n", c(1,2)); // prints 12
printf("%g\n", d(1)); // prints 6
printf("%g\n", f1(d)); // prints 12
printf("%g\n", f1(a)); // prints 4
return 0;
}
(C++ has no need for explicit syntax like feval, because the typed parameter declaration, double (*arg1)(double) tells the compiler that arg1(2.0) is valid. In older code you may see (*arg1)(2.0) but that's not required, and I think it makes the code less readable.)
(I have used printf in this code, instead of C++'s iostreams, partly because I personally think printf is much more ergonomic than iostreams, and partly because that makes this program also a valid C program with the same semantics. That may be useful, for instance, if the reason you are learning C++ is because you want to write MATLAB extensions, which, the last time I checked, was actually easier if you stuck to plain C.)
There are significant differences; for instance, the MATLAB functions accept vectors, whereas these C++ functions only take single values; if I'd wanted b to call c I would have had to swap them or write a "forward declaration" of c above b; and in C++, (with a few exceptions that you don't need to worry about right now,) all your code has to be inside one function or another. Learning these differences is part of learning C++, but you don't need to confuse yourself with templates and lambdas and classes and so on just yet. Stick to free functions with fixed type signatures at first.
Finally, I would be remiss if I didn't mention that in
static double c(double p, double q) { return a(p) * b(q); }
the calls to a and b might happen in either order. There is talk of changing this but it has not happened yet.
int a(const int x){return x * 2;}
int b(const int x){return x * 3;}
int fun1(const int x){return a(x);}
std::cout << fun1(1) << std::endl; //returns 2
This is basic compile-time composition. If you wanted runtime composition, things get a tad more involved.
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
The code snippet is as follows
#include <iostream>
using namespace std;
int a(int m)
{
return ++m;
}
int b(int &m)
{
return ++m;
}
int c(int &m)
{
return ++m;
}
int main(void)
{
int p=0,q=0,r=0;
p+=a(b(p));
q+=b(a(q));
r+=a(c(r));
cout<<p<<q<<r;
return 0;
}
The error occurring is invalid initialization of non-const reference of type 'int&' from an rvalue of type 'int' at q+=b(a(q)). How to go about the error so that this program prints a desired output
Timothy J Williams is one or both of the following things:
wrong;
teaching C++ as it pertains to Visual Studio only, without disclaiming it, which is ill-advised.
References cannot bind to temporaries. It is not allowed in C++. Visual Studio allows it as a non-standard extension, but that's it. Some people get confused and think that means it's valid C++. It's not.
You will have to store the results of function calls like b(1) into named variables before you pass them anywhere by reference.
int main()
{
int p = 0, q = 0, r = 0;
int result_of_b_p = b(p);
p += a(result_of_b_p);
int result_of_a_q = a(q);
q += b(result_of_a_q);
int result_of_c_r = c(r);
r += a(result_of_c_r);
std::cout << p << q << r << '\n';
}
I should also note that the cited code is confusing and appears to serve no purpose other than for contrived "test your knowledge" challenges. I'd pay not too much attention to this and instead learn C++ from a proper book. After all, Timothy Williams claims that the above program outputs 322; it doesn't.
You cannot pass by reference a constant.
To break down your code.
int a(int m){
return ++m;
}
This will return an int (constant, eg. 5)
Then in
int b(int &m){
return ++m;
}
You are now technically passing in an integer (constant) not a variable into B. You must pass B in as a variable.
Try exactly what you have but passing in
int x = a(your_number_here);
int z = b(x);
EDIT:
int main(void){
int p=0,q=0;
int x = 5;
p = a(x);
q = b(p);
cout << q << endl;
return 0;
}
Returns 7.
The error is a result of trying to call a function that takes a reference with a value. It would be like calling b with a value literal b(1). That can't work...
The function call is where you pass by reference. See below:
void foo (int* m)
{
(*m)++;
}
int main (void)
{
int a = 0;
foo (&a);
cout << a << endl; // prints 1
}
So here b(int& m) takes a reference to an integer. Think about it this way. A reference is a "safe pointer" for which the compiler automatically handles the dereferencing operations.
The return value of a(int m) is a temporary, i.e. it is a temporary value that goes out of scope as soon as the function returns and its value has been utilized in some way. So you can do x = a(15); and x will become a copy of the returned 16. This is what an r-value is. A sort of "temporary" (r because it is on the right side of the expression). So when you have a pointer to a temporary value it does not make sense in most cases. For example in the following code
int* return_local() {
int a = 10;
return &a;
}
This will give you a compiler warning. Because you don't want to bind a pointer to a value which will go out of scope. Similarly you don't want a reference to an object that will go out of scope as soon as the function has returned and its value has been utilized. That is why there is an error in your code. a(int m) returns an r-value and when you do b(a(q) you are trying to bind a reference to an r-value
Now there is something called an r-value reference which takes the form void some_func(int&& rvalue_reference) in syntax. The && means r-value reference not reference to reference. Look it up if you are interested.
It's not allowed to pass a r-value as a non-const reference argument. This happens in the line whereyou call the function b with a(q) as its argument, which is an r-value (an expression which is not a simple variable).
So you need to first call a and store itsvalue in a variable, and then pass this variable to b:
int main(void)
{
int p=0,q=0,r=0;
p+=a(b(p));
int t=a(q);
q+=b(t);
r+=a(c(r));
cout<<p<<q<<r;
return 0;
}
This question already has answers here:
ampersand (&) at the end of variable etc
(5 answers)
Closed 3 years ago.
I am fairly new to programming. I am just moving on to C++ from C in my college courses, and I encountered something that I haven't seen before in C. Sometimes after the type, either in a function declaration or passing a parameter, a & immediately follows the type. For example, we use a struct called Customer in one of our projects, and some of the functions pass Customer&. Why is the ampersand after the type, as opposed to in front? Thanks!
References in C++ simply allow for a cleaner way to execute the following code:
int x = 16;
int* y = &x;
cout << *y;
Which could be written instead as
int x = 16;
int& y = x;
cout << y;
When defining functions, a reference allows a function to change the value of parameters without causing the user of the function to put an ampersand before everything. E.g.
void func( int& a )
{
a = 5;
}
void main()
{
int A = 10;
func( A );
cout << A; // Will output '5'
}
Be careful with this type of mutation, as a programmer using functions like this without checking the implementation might not realize that the function is changing the value of the parameters unless the intent is obvious. init_server(my_server) would be an example of a case where it's obvious, but to_json(my_struct) would clearly be an example where you should not be using a reference to change the struct in any way.
But, one of the most important uses of references, would be function like
int sum_vector( const vector<int>& a ) {
int sum = 0;
for( int i = 0; i < a.size(); i++ ) {
sum += a[i];
}
return sum;
}
If you tried to make sum_vector take in a vector, and you passed in a vector with 100 million entries, then it would have to copy them all over, taking forever. You could take in a pointer, but then the internal parts of the function would have to constantly dereference, and it must called with sum_vector(&myvec), which is more annoying than sum_vector(myvec). In this way, using a const reference, you can prevent the highly inefficient copying of the whole vector into the function body, while keeping syntax neat. Using const lets you reassure yourself that you're not going to change the vector that you were given. And, it also assures the user of your function that you won't change it. Similarly, void to_json(const some_struct&) would be a better function definition as it ensures you won't change the user's data.