I have a function with the prototype as
void test( int array [] , int b);
I know we can replce the protoype as: void test(int*, int);
In main() we declare the following arrays :
int array1[10], array2[10];
To set the body of the function to 0,
test ( array1 , b)
{
for ( int i = 0 ; i < b ; i++)
array1[i] = 0;
}
can i do the follwing and why?
int main()
{// assuming b is the size of the array
test(array1 , b);
test(array2 , b) ;
return 0;
}
i know the basic of c++ im trying to write my own include files.
I am just wondering if this is possible and is it a good choise?
Not a direct answer to your question, but the fact that you talk about C++ and yet use plain old C arrays caught my attention:
Consider not using C arrays in the first place. Instead, use a std::vector<int>. This probably avoids the need to ask this question in the first place (and it avoids a whole lot of other issues). You don't need to bother about the right size type (int? size_t? Something else?) since std::vector gives you the right type already: std::vector<int>::size_type.
Your function signature would just be
void test( std::vector<int> &a );
The implementation for filling the vector with zeros would be:
void test( std::vector<int> &a )
{
std::fill( a.begin(), a.end(), 0 );
}
You may be asking about the difference between formal parameters and actual parameters.
In your prototype
void test(int *array, size_t size);
the names 'array' and 'size' are the formal parameters. You use those names inside the body of your function.
In the code that invokes the function, you can use different names, which are the actual parameters.
so
int main()
{
const size_t b = 10;
int array1[10], array2[10];
test(array1 , b);
test(array2 , b) ;
return 0;
}
Here array1 and b are the actual parameters to the first invocation and array2 and b are the actual parameters to the second invocation.
So yes, you can use whatever names you like as actual parameters, so long as the types of the variables match your prototype.
Yes, it's possible; but declaration in the function body should be same as what you declared as prototype:
void test (int array1[], int b) // <---- see here (prefer `unsigned int` for size)
{
for ( int i = 0 ; i < b ; i++)
array1[i] = 0;
}
It's better to use library function memset() if you want to set something to 0.
(As an advise, you can a build a library on top of what is already existing. Otherwise it will be like reinventing a wheel.)
Looks like you're migrating from C. Yes, this is possible, but you need to get the declarations right, or the compiler will throw an error.
The preferred C++ prototype would be
void test(int *array, size_t size);
In C++, you must declare the return type, and the type(s) of each argument in both the prototype and the implementation.
Note:
You don't need to use size_t, but it is preferred (even on C). size_t is included in stddef.h (and by extension cstddef which is the preferred C++ include). It is architecture dependent and is usually unsigned int in 32-bit systems and unsigned long long on 64-bit systems
Related
I got this declaration from https://en.cppreference.com/w/cpp/language/scope, but don't know how to parse this declaration even there is a comment below.
my questions is
how to parse the declaration statement (I see it as a function pointer to a function protocol like "int[3] foo(int n)" or "int foo(int n)[3] --- they are illegal in C++ )? Then, how can I construct a concrete function which can be assigned to this function pointer? Thanks.
const int n = 3;
int (*(*f2)(int n))[n]; // OK: the scope of the function parameter 'n'
// ends at the end of its function declarator
// in the array declarator, global n is in scope
// (this declares a pointer to function returning a pointer to an array of 3 int
It's a pointer to a function taking an int and returning a pointer to an int array of size three.
All the comment is saying is that there are two n identifiers in play here. The [n] (in array declarator) is using the const int 3, not the parameter to the function (which is in the function declarator).
Starting in the middle, with each segment being included in the subsequent bullet point as ...:
f2 is a pointer, (*f2).
It's a pointer to a function taking an integer, ...(int).
It returns a pointer to an int array of size three, int (*...)[3].
You can form a concrete function for it as per the following complete program, which output the first element, 42:
#include <iostream>
const int n = 3;
int (*(*f2)(int n))[n];
int (*g2(int))[n] {
static int x[::n] = { 42 }; // Use outer n, not the parameter.
return &x; // since C++ has no VLAs. This
// means parameter is not actually
// needed in this test case, though
// it may be in more complicated
// tests.
}
int main() {
f2 = &g2; // Assign concrete function to pointer.
auto y = f2(3); // Call via pointer, get array.
std::cout << *(y[0]) << '\n'; // Deref first element to get 42.
}
Having said that, I would be rather curious if one of my colleagues submitting something like that for a code review, at least without a large comment explaining it. Although seasoned developers may be able to work it out, those less experienced may have trouble.
And, in fact, even seasoned developers shouldn't have to work it out, especially given it took me a few minutes.
C++ has a very expressive type system which can easily build something like this up in parts, so you don't have to experience migraines trying to work it out. For something like this, I'd be using std::vector (or std::array) unless there was a compelling case for the added complexity caused by more basic types.
You can create a type for pointer to an array of 3 int
typedef int (*array_with_size_n)[n];
and then use it as return type
const int n = 3;
int (*(*f2)(int n))[n];
int arr[n];
array_with_size_n func(int n)
{
return &arr;
}
int main()
{
f2 = &func;
return 0;
}
There are two versions of a function (the code below is a simplified version). Both versions are used in the program. In the actual function, the differences between the two versions can occur at two or three different places.
How to avoid writing both versions in the code without sacrificing performance, through template or other means? This is an attempt
to make the code more readable.
Performance is critical because it will get run many many times, and I am writing benchmark for different implementations.
(Also, is this an ok api, if I am writing a library for a few people?)
Example:
int set_intersect(const int* A, const int s_a,
const int* B, const int s_b,
int* C = 0){
//if (int* C == 0), we are running version
//0 of the function.
//int* C is not known during compilation
//time for version 1.
int Count0 = 0;
//counter for version 0 of the function.
const int* const C_original(C);
//counter and pointer for version 1 of
//the function
int a = 0;
int b = 0;
int A_now;
int B_now;
while(a < s_a && b < s_b){
A_now = A[a];
B_now = B[b];
a += (A_now <= B_now);
b += (B_now <= A_now);
if (A_now == B_now){
if (C == 0){
Count0++;
} else {
C++;
*(C)=A_now;
}
}
}
if (C == 0){
return Count0;
}else{
return C - C_original;
}
}
Thanks.
Updates:
Conditional compile-time inclusion/exclusion of code based on template argument(s)
(some of those templates look so long)
Remove/Insert code at compile time without duplication in C++
(this is more similar to my case. my case is simpler though.)
I guess the following can work, but it adds a new argument.
int set_intersect(const int* A, const int s_a,
const int* B, const int s_b,
int* C = 0,
char flag);
put all code for version 0 into if (flag == '0') { /* version 0 code */ }
put all code for version 1 into if (flag == '1') { /* version 1 code */}
Probably can put the flag variable into template (as Barmar suggested in comments), that way, it doesn't feel like adding another argument for the function. Can also replace the 0 and 1 with enum (like enum class set_intersection_type {find_set, size_only}). Calling the function will be like set_intersect<find_set>(const int* A, const int s_a, const int* B, const int s_b, int* C) or set_intersect<size_only>(const int* A, const int s_a, const int* B, const int s_b) Hopefully this is more readable than before, and the compiler is smart enough to see what is going on.
Another problem is, what if someone uses the findset version (version 1), and then forgets to change the default argument (int C* = 0)? It is possible to call the function this way: set_intersect<find_set>(const int* A, const int s_a, const int* B, const int s_b).
May be I can use dasblinkenlight's idea in the comments. Create two wrapper functions (set_intersection, set_intersection_size). Each wrapper calls the actual function with different arguments. Also list the actual function as a private function so no one can call it directly.
For the different implementations of set intersections, maybe can create a common wrapper with templates. Calling the wrapper would be similar to set_intersection<basic>, set_intersection<binary_search>, or set_intersection_size<simd> etc. This seems to look better.
Generally seems doable, question is whether you want to do that. Would say no. From what I can tell you do two different things:
Version 0 computes the size of the intersection
Version 1 computes the size of the intersection, and writes the intersection to the location past C*, assuming there is enough space to store it.
I would not only for speed, but also for clarity make two distinct functions, set_intersection and set_intersection_size, but if you insist on having one I would benchmark your code against std::set_intersection, and if possible just redirect to the ::std version if C != 0.
In your current version I would not use your library. However I would also be hard-pressed to come up with a situation where I would prefer a custom-made version of set_intersection to the STL version. If I ever needed performance better than the STL, I would expect to have identified the point in code as the bottleneck, and I would not use a library call at all, but write the code myself, possibly in assembly and unrolling the loop etc..
What bugs me a bit is how this is supposed to work:
const int* const Count1(C);
//counter and pointer for version 1 of
//the function
...
Count1++;
*(Count1)=A_now;
If it is known at compilation time what version you want you can use Conditional Compilation.
#define Version_0 //assuming you know this compilation is version 0
Then you can go:
int set_intersect(...)
#ifdef Version_0
//Version 0 of the code
#else
//Version 1 of the code
This way only one version of the code gets compiled.
If you don't know which version it is for compilation, I suggest having two separate functions so you don't have to check for the version every instance of the function.
Have a type that you specialize on a bool parameter:
template<bool b>
struct Counter
{
};
template<>
struct Counter<false>
{
int c;
Counter(int *)
: c(0)
{
}
int operator++() { return ++c; }
void storeA(const int a_now) {}
};
template<>
struct Counter<true>
{
const int* const c;
Counter(int * c_orig)
: c(c_orig)
{
}
int operator++() { return ++C; }
void storeA(const int a_now) { *C = a_now; }
}
Then specialize your algorithm on Counter as a template argument. Note that this will be exactly the same for both cases, that is, you don't need to specialize:
template<typename Counter>
struct SetIntersectHelper
{
static int set_intersect(const int* A, const int s_a,
const int* B, const int s_b,
int* C)
{
// your function's body, using Counter
}
};
Now, you're ready to add the generic method:
int set_intersect(const int* A, const int s_a,
const int* B, const int s_b,
int* C = 0)
{
return C ? SetIntersectHelper< Counter< true > >::set_intersect(A, s_a, B, s_b, C):
SetIntersectHelper< Counter< false > >::set_intersect(A, s_a, B, s_b, C);
}
This question already has answers here:
How do I use arrays in C++?
(5 answers)
Closed 6 years ago.
I have looked at all the other posts with a similar topic, and none help, so please don't flag as a duplicate.
I am defining in main() a const int SIZE = 20;. Then, I pass this as an argument to my function, Mode:
int* Mode(int* numbers, int & mode, const int SIZE)
{
int occurences[SIZE];
// Calcualte mode
}
However, I get the error, expression must have a constant value.
My function call (in main) looks like this:
int* occurencesPtr = Mode(numbersPtr, mode, SIZE);
With SIZE being defined at the beginning to the literal 20.
I understand that the error is because the function's version of SIZE only acquires its value when the function is called (?), but I don't know how I could work around this.
I have even tried passing to the function a const int * const SIZEPtr = &SIZE, but that didn't work either. Help?
EDIT: I am not trying to use a variable size!! Notice that I have made SIZE a const everywhere! I just want to use that same SIZE constant to declare my array.
EDIT: Dynamic arrays are not what I need. I just want a normal, named, array, defined with a constant size value passed to the function.
There is a misconception here with what const means, probably because it's a little confusing that this works:
const int SIZE = 20;
int array[SIZE];
but this doesn't:
void foo(const int SIZE) {
int array[SIZE];
// ...
}
const int SIZE = 20;
foo(SIZE);
The issue is that the array size in an array declaration must be a core constant expression. Simplified, that means an expression that's evaluatable at compile time to be a constant. That is true in the first case (you can see that SIZE is the integral constant 20) but that is not true in the second case. There, the SIZE function parameter is just const - in the sense that it is nonmodifiable - and not a core constant expression. You can see the difference in that I can call foo() with something that is clearly unknowable until runtime:
int x;
if (std::cin >> x) {
foo(x);
}
In order to pass an argument into foo, and have that argument be used as an array bound, it is not enough to have it be const - the actual integral value must be encoded into the type (unless you call foo() as constexpr which I'm assuming is not the case here). In which case, you'd have to do something like:
template <int SIZE>
void foo() { ... }
const int SIZE = 20;
foo<SIZE>();
or:
template <int SIZE>
void foo(std::integral_constant<int, SIZE > ) { ... }
const int SIZE = 20;
foo(std::integral_constant<int, SIZE>{} );
or simply have SIZE be a global constant or otherwise accessible to foo() in a way that doesn't have to do with its arguments.
Or, there's always the simple option: use std::vector:
void foo(const int SIZE) {
std::vector<int> v(SIZE);
...
}
I understand that the error is because the function's version of SIZE only acquires its value when the function is called (?), but I don't know how I could work around this.
Option 1
Instead of defining SIZE in main, add a constexpr function. Use the constexpr function instead of passing the size.
constexpr int getSize()
{
return 20;
}
int* Mode(int* numbers, int & mode)
{
int occurences[getSize()];
// ...
}
Option 2
Use std::vector instead of array.
int* Mode(int* numbers, int & mode, int size)
{
std::vector<int> occurences[size];
// ...
}
Option 3
Use a function template.
template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)
{
int occurences[SIZE];
// ...
}
Option 4
Use a function template and std::array.
template <size_t SIZE>
int* Mode(int* numbers, int & mode, int size)
{
std::array<int, SIZE> occurences;
// ...
}
You're confusing things. A constant expression has nothing to do with const (at least not that much) ;).
let's think we are the compiler and face this function:
void foo(const int SIZE) { }
The constmerely says "we are not able to change the function-local variable SIZE inside the function body.
We need to compile it without assuming that SIZE is compile time constant. Why?
Because there is noone stoping us from doing something like:
int i{};
std::cin >> i;
foo(i);
You can pass any (matching/convertible) value to a by value const function argument.
What should happen when the compiler assumed the value passed to foo was a compile time constant expression?
If you want to pass compile time constants, use templates and while you're at it use std::array instead of T[N]:
template<std::size_t N>
void foo()
{
std::array<int, N> occurences;
}
const isn't doing what you think it's doing in your Mode function.
When const is used in function definition, const is simply telling the compiler that the function will not change the argument declared const inside of the scope of it's function. But that does not make the argument a constant, it is actually called a constant expression. Some compilers enforce this, others do not, and so will allow you to change const expressions (arguments passed with const keyword).
In order to use a globally accessible constant value which you can use, like SIZE, you'll need to declare a global constant before the function is called; which could be declared outside of main(), or at least outside the scope of all other functions but main(), if you must declare all inside main. Pass the global constant to the Mode function just as you would any other variable.
Oh, and, main() needs a return type.
I've edited the code to meet your specific constraints.
Here is a variation on your original code:
int main(){
//Declare constants first.
const int SIZE = 20; /*Could declare here instead.*/
//Declare variables next.
int *intPtr = 0; // to hold the pointer passed from Mode.
int *numbersPointer = 0;
int mode = 0;
//Define Mode (using OP's code.)
int* Mode(int* numbers, int & mode, const int size){
int occurences[size];
// Calculate mode
}
/*Now use constants, variables, and functions.*/
intPtr = Mode(numbersPointer, mode, SIZE); //Call mode.
return 0;
}
There are tons of similar questions, but still I could not find any answer relevant for the feature of variable length arrays in C99/C11.
How to pass multidimensional variable length array to a function in C99/C11?
For example:
void foo(int n, int arr[][]) // <-- error here, how to fix?
{
}
void bar(int n)
{
int arr[n][n];
foo(n, arr);
}
Compiler (g++-4.7 -std=gnu++11) says:
error: declaration of ‘arr’ as multidimensional array must have bounds for all dimensions except the first
If I change it to int *arr[], compiler still complains:
error: cannot convert ‘int (*)[(((sizetype)(((ssizetype)n) + -1)) + 1)]’ to ‘int**’ for argument ‘2’ to ‘void foo(int, int**)’
Next question, how to pass it by value and how to pass it by reference? Apparently, usually you don't want the entire array to be copied when you pass it to a function.
With constant length arrays it's simple, since, as the "constant" implies, you should know the length when you declare the function:
void foo2(int n, int arr[][10]) // <-- ok
{
}
void bar2()
{
int arr[10][10];
foo2(10, arr);
}
I know, passing arrays to functions like this is not a best practice, and I don't like it at all. It is probably better to do with flat pointers, or objects (like std:vector) or somehow else. But still, I'm a bit curios what is the answer here from a theoretical standpoint.
Passing arrays to functions is a bit funny in C and C++. There are no rvalues of array types, so you're actually passing a pointer.
To address a 2D array (a real one, not array of arrays), you'll need to pass 2 chunks of data:
the pointer to where it starts
how wide one row is
And these are two separate values, be it C or C++ or with VLA or without or whatnot.
Some ways to write that:
Simplest, works everywhere but needs more manual work
void foo(int width, int* arr) {
arr[x + y*width] = 5;
}
VLA, standard C99
void foo(int width, int arr[][width]) {
arr[x][y] = 5;
}
VLA w/ reversed arguments, forward parameter declaration (GNU C extension)
void foo(int width; int arr[][width], int width) {
arr[x][y]=5;
}
C++ w/ VLA (GNU C++ extension, terribly ugly)
void foo(int width, int* ptr) {
typedef int arrtype[][width];
arrtype& arr = *reinterpret_cast<arrtype*>(ptr);
arr[x][y]=5;
}
Big remark:
The [x][y] notation with a 2D array works because the array's type contains the width. No VLA = array types must be fixed at compile-time.
Hence: If you can't use VLA, then...
there's no way to handle it in C,
there's no way to handle it without a proxy class w/ overloaded operator overloading in C++.
If you can use VLA (C99 or GNU C++ extensions), then...
you're in the green in C,
you still need a mess in C++, use classes instead.
For C++, boost::multi_array is a solid choice.
A workaround
For 2D arrays, you can make two separate allocations:
a 1D array of pointers to T (A)
a 2D array of T (B)
Then set the pointers in (A) to point into respective rows of (B).
With this setup, you can just pass (A) around as a simple T** and it will behave well with [x][y] indexing.
This solution is nice for 2D, but needs more and more boilerplate for higher dimensions. It's also slower than the VLA solution because of the extra layer of indirection.
You may also run into a similar solution with a separate allocation for every B's row. In C this looks like a malloc-in-a-loop, and is analogous of C++'s vector-of-vectors. However this takes away the benefit of having the whole array in one block.
There is no clear cut way for doing this but you can use a workaround to treat a 2 dimensional array as a one dimensional array and then reconvert it to a two dimensional array inside the function.
void foo2(int n, int *arr)
{
int *ptr; // use this as a marker to go to next block
int i;
int j;
for(i = 0; i < n; i++)
{
ptr = arr + i*n; // this is the starting for arr[i] ...
for (j = 0; j < n ;j++)
{
printf(" %d ", ptr[j]); // This is same as arr[i][j]
}
}
}
void bar2()
{
int arr[10][10];
foo2(10, (int *)arr);
}
I am a bit confused. There are two ways to return an array from a method. The first suggests the following:
typedef int arrT[10];
arrT *func(int i);
However, how do I capture the return which is an int (*)[]?
Another way is through a reference or pointer:
int (*func(int i)[10];
or
int (&func(int i)[10];
The return types are either int (*)[] or int (&)[].
The trouble I am having is how I can assign a variable to accept the point and I continue to get errors such as:
can't convert int* to int (*)[]
Any idea what I am doing wrong or what is lacking in my knowledge?
If you want to return an array by value, put it in a structure.
The Standard committee already did that, and thus you can use std::array<int,10>.
std::array<int,10> func(int i);
std::array<int,10> x = func(77);
This makes it very straightforward to return by reference also:
std::array<int,10>& func2(int i);
std::array<int,10>& y = func2(5);
First, the information you give is incorrect.
You write,
“There are two ways to return an array from a method”
and then you give as examples of the ways
typedef int arrT[10];
arrT *func(int i);
and
int (*func(int i))[10];
(I’ve added the missing right parenthesis), where you say that this latter way, in contrast to the first, is an example of
“through a reference or pointer”
Well, these two declarations mean exactly the same, to wit:
typedef int A[10];
A* fp1( int i ) { return 0; }
int (*fp2( int i ))[10] { return 0; }
int main()
{
int (*p1)[10] = fp1( 100 );
int (*p2)[10] = fp2( 200 );
}
In both cases a pointer to the array is returned, and this pointer is typed as "pointer to array". Dereferencing that pointer yields the array itself, which decays to a pointer to itself again, but now typed as "pointer to item". It’s a pointer to the first item of the array. At the machine code level these two pointers are, in practice, exactly the same. Coming from a Pascal background that confused me for a long time, but the upshot is, since it’s generally impractical to carry the array size along in the type (which precludes dealing with arrays of different runtime sizes), most array handling code deals with the pointer-to-first-item instead of the pointer-to-the-whole-array.
I.e., normally such a low level C language like function would be declared as just
int* func()
return a pointer to the first item of an array of size established at run time.
Now, if you want to return an array by value then you have two choices:
Returning a fixed size array by value: put it in a struct.
The standard already provides a templated class that does this, std::array.
Returning a variable size array by value: use a class that deals with copying.
The standard already provides a templated class that does this, std::vector.
For example,
#include <vector>
using namespace std;
vector<int> foo() { return vector<int>( 10 ); }
int main()
{
vector<int> const v = foo();
// ...
}
This is the most general. Using std::array is more of an optimization for special cases. As a beginner, keep in mind Donald Knuth’s advice: “Premature optimization is the root of all evil.” I.e., just use std::vector unless there is a really really good reason to use std::array.
using arrT10 = int[10]; // Or you can use typedef if you want
arrT10 * func(int i)
{
arrT10 a10;
return &a10;
// int a[10];
// return a; // ERROR: can't convert int* to int (*)[]
}
This will give you a warning because func returns an address of a local variable so we should NEVER code like this but I'm sure this code can help you.