C++ arrays as parameters, EDIT: now includes variable scoping - c++

Alright, I'm guessing this is an easy question, so I'll take the knocks, but I'm not finding what I need on google or SO. I'd like to create an array in one place, and populate it inside a different function.
I define a function:
void someFunction(double results[])
{
for (int i = 0; i<100; ++i)
{
for (int n = 0; n<16; ++n) //note this iteration limit
{
results[n] += i * n;
}
}
}
That's an approximation to what my code is doing, but regardless, shouldn't be running into any overflow or out of bounds issues or anything. I generate an array:
double result[16];
for(int i = 0; i<16; i++)
{
result[i] = -1;
}
then I want to pass it to someFunction
someFunction(result);
When I set breakpoints and step through the code, upon entering someFunction, results is set to the same address as result, and the value there is -1.000000 as expected. However, when I start iterating through the loop, results[n] doesn't seem to resolve to *(results+n) or *(results+n*sizeof(double)), it just seems to resolve to *(results). What I end up with is that instead of populating my result array, I just get one value. What am I doing wrong?
EDIT
Oh fun, I have a typo: it wasn't void someFunction(double results[]). It was:
void someFunction(double result[])...
So perhaps this is turning into a scoping question. If my double result[16] array is defined in a main.cpp, and someFunction is defined in a Utils.h file that's included by the main.cpp, does the result variable in someFunction then wreak havoc on the result array in main?
EDIT 2:
#gf, in the process of trying to reproduce this problem with a fresh project, the original project "magically" started working.
I don't know how to explain it, as nothing changed, but I'm pretty sure of what I saw - my original description of the issue was pretty clear, so I don't think I was hallucinating. I appreciate the time and answers...sorry for wasting your time. I'll update again if it happens again, but for the meantime, I think I'm in the clear. Thanks again.

Just a point about the variable scope part of the question - there is no issue of variable scope here. result/results in your someFunction definition is a parameter -> it will take on the value passed in. There is no relation between variables in a called function and it's caller -> the variables in the caller function are unknown to the called function unless passed in. Also, variable scoping issues do not occur between routines in C++ because there are no nested routines. The following pieces of code would demonstrate scoping issues:
int i = 0;
{
int i = 0;
i = 5; //changes the second i, not the first.
//The first is aliased by the second i defined first.
}
i = 5; //now changes the first i; the inner block is gone and so is its local i
so if C++ did have nested routines, this would cause variable scoping
void main()
{
double results[16];
double blah[16];
doSomething(blah);
void doSomething(double * results)
{
//blah doing something here uses our parameter results,
//which refers to blah, but not to the results in the higher scope.
//The results in the higher scope is hidden.
}
}

void someFunction(double results[])
should be exactly equivalent to
void someFunction(double *results)
Try using the alternative declaration and see if the problem persists.

To me it seems that your code should simply work.
I just tried this in g++ and worked fine. I guess your problem is elsewhere? have you tried the snipped you posted?
#include <iostream>
void someFunction(double results[])
{
for (int i = 0; i<100; ++i)
{
for (int n = 0; n<16; ++n) //note this iteration limit
{
results[n] += i * n;
}
}
}
int main()
{
double result[16];
for(int i = 0; i<16; i++)
{
result[i] = -1;
}
someFunction(result);
for(int i = 0; i<16; i++)
std::cerr << result[i] << " ";
std::cerr << std::endl;
}

Have you perhaps double defined your results array in a couple places and then accidently refered to one copy in one place and another copy elsewhere? Perhaps the second is a pointer and not an array and that is why the debugger is confused?

To ensure this problem doesn't occur, you should never use global variables like that. If you absolutely must have one, put it in a namespace for clarity.

Related

How can I initialize a variable but when said function is initiated the value of the variable is not reset?

I've made this example to show what I'm talking about. I want to know if there is a way to run through main() without resetting value to 0.
int main(){
int value = 0;
value++;
cout << value << endl;
main();
}
Before answering the question, your example has two big problems
Calling, or even taking the address of, main is not allowed.
Your function has infinite recursion which makes your program have undefined behavior.
A different example where value is saved between calls could look like this. It uses a static variable, initialized to 0 the first time the function is called, and is never initialized again during the program execution.
#include <iostream>
int a_function() {
static int value = 0;
++value;
if(value < 100) a_function();
return value;
}
int main(){
std::cout << a_function(); // prints 100
}
If you want to keep the variable value local to the main function, you can declare it as static int value = 0;.
As has been pointed out in various comments though, recursively calling any function without an escape mechanism like you are is a bad idea. Doing it with main is a worse idea still apparently not even possible.

Copy member value on stack or access it with pointer?

So I got a structure, that holds an integer. I usually create that structure on the heap. If I now pass a pointer to such a structure into a function and use the integer member, would it be faster if I at first copied the members value on the stack and use that local variable in the function, or should I access the member through the pointer? What is potentially faster? Obviously I dont want to modify the member value. Code example:
Sample structure:
struct sample_s
{
int sample_member;
}
Way 1:
void sample_func(struct sample_s *sample_instance)
{
for(int i = 0; i < 1000; i++)
{
printf("%d", sample_instance->sample_member);
}
}
Way 2:
void sample_func_two(struct sample_s *sample_instance)
{
int a = sample_instance->sample_member;
for(int i = 0; i < 1000; i++)
{
printf("%d", a);
}
}
In your specific case, sample_func_two is potentially faster. This is because you're calling an external function, printf:
printf("%d", sample_instance->sample_member);
The compiler probably doesn't know that this call won't modify *sample_instance1, so it will reload sample_member from memory each time through the loop.
Now as for whether that makes an actual difference in the running time of your program, you'll have to benchmark it yourself.
1 The compiler doesn't know because it can't see the code of printf (it's in a library somewhere) and printf is not declared pure. In fact, printf can't be declared pure because depending on the format string it may write through its arguments (with %n).

a function which convert integer to an array of digits c++ [duplicate]

This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
#include<iostream>
using namespace std;
int *Arr(int y,int size){
int arg[size];
for(int i=size-1;i>=0;i--){
arg[i]=y%10;
y=y/10;
}
return arg;
}
int main(){
int *p=Arr(2587,4);
for(int j=0;j<4;j++){
cout<<p[j]<<" ";
}
return 0;
}
> Blockquote
I dont why this isn't working ...I'm trying to back an array but the problem is in the second digits.Can somebody help ;) thanks
The problem is you are putting your result into a local array that is destroyed when the function ends. You need to dynamicaly allocate the array so that its life-span is not limited to the function it was created in:
#include<iostream>
using namespace std;
int *Arr(int y, int size)
{
// This local array will be destroyed when the function ends
// int arg[size];
// Do this instead: allocate non-local memory
int* arg = new int[size];
for(int i = size - 1; i >= 0; i--)
{
arg[i] = y % 10;
y = y / 10;
}
return arg;
}
int main()
{
int *p = Arr(2587, 4);
for(int j = 0; j < 4; j++)
{
cout << p[j] << " ";
}
// You need to manually free the non-local memory
delete[] p; // free memory
return 0;
}
NOTE:
Allocating dynamic memory using new is to be avoided if possible. You may want to study up on smart pointers for managing it.
Also, in real C++ code, you would use a container like std::vector<int> rather than a builtin array
Of course it is not working.
At best, the behaviour is undefined, since Arg() is returning the address of a local variable (arg) that no longer exists for main(). main() uses that returned address when it is not the address of anything that exists as far as your program is concerned.
There is also the incidental problem that int arg[size], where size is not fixed at compile time, is not valid C++. Depending on how exacting your compiler is (some C++ compilers reject constructs that are not valid C++, but others accept extensions like this) your code will not even compile successfully.
To fix the problem, have your function return a std::vector<int> (vector is templated container defined in the standard header <vector>). Then all your function needs to do is add the values to a local vector, which CAN be returned safely by value to the caller.
If you do it right, you won't even need to use a pointer anywhere in your code.

Why can't we declare two variable in a for loop?

The below code generates an error when i run it but if i declare at-least one variable outside the loop the code works fine.Why can't i declare both the variables in the loop itself?
Error:
#include<iostream>
#include<conio.h>
using namespace std ;
int main()
{
for(int j=0,int i=0;i<4&&j<2;i++,j++)
{
cout<<"Hello"<<endl ;
}
getch() ;
return 0 ;
}
Works Fine:
#include<iostream>
#include<conio.h>
using namespace std ;
int main()
{
int i ;
for(int j=0,i=0;i<4&&j<2;i++,j++)
{
cout<<"Hello"<<endl ;
}
getch() ;
return 0 ;
}
You can, but the notation for declaring two variables in a single declaration is like this:
int j=0, i=0;
with no second int.
(This is actually what your second version is doing; you might think it's assigning the already-declared i, but actually it's declaring a new one, whose scope is the for-loop.)
Because that's how the Standard defines the syntax. There's nothing "wrong" in particular with the idea, but apparently it was decided that you can only have one declaration in the initialization part.
If you want to declare multiple variables, use a comma to enumerate them (but this way, you can only declare variables of the same type):
for (int i = 0, j = 10; i < 10; i++, j--)
However, I'm not sure you should be doing this. After a certain point, this evolves into an unreadable mess.
Note that the given answers "only" handles making multiple variables of the same type.
If, for some bizarre reason, you would need to do multiple types, this is valid (though awful):
for(struct {int a; double b} loop = {0, 1.5}; loop.a < loop.b; loop.a++)
{
// Awful hacks
}

C++ use `const int` as looping variable?

I want to write code that compiles conditionally and according to the following two cases:
CASE_A:
for(int i = 1; i <= 10; ++i){
// do something...
}
CASE_B: ( == !CASE_A)
{
const int i = 0;
// do something...
}
That is, in case A, I want to have a normal loop over variable i but, in case B, i want to restrict local scope variable i to only a special case (designated here as i = 0). Obviously, I could write something along the lines:
for(int i = (CASE_A ? 1 : 0); i <= (CASE_A ? 10 : 0); ++i){
// do something
}
However, I do not like this design as it doesn't allow me to take advantage of the const declaration in the special case B. Such declaration would presumably allow for lots of optimization as the body of this loop benefits greatly from a potential compile-time replacement of i by its constant value.
Looking forward to any tips from the community on how to efficiently achieve this.
Thank you!
EDITS:
CASE_A vs CASE_B can be evaluated at compile-time.
i is not passed as reference
i is not re-evaluated in the body (otherwise const would not make sense), but I am not sure the compiler will go through the effort to certify that
Assuming, you aren't over-simplifying your example, it shouldn't matter. Assuming CASE_A can be evaluated at compile-time, the code:
for( int i = 0; i <= 0; ++i ) {
do_something_with( i );
}
is going to generate the same machine code as:
const int i = 0;
do_something_with( i );
for any decent compiler (with optimization turned on, of course).
In researching this, I find there is a fine point here. If i gets passed to a function via a pointer or reference, the compiler can't assume it doesn't change. This is true even if the pointer or reference is const! (Since the const can be cast away in the function.)
Seems to be the obvious solution:
template<int CASE>
void do_case();
template<>
void do_case<CASE_A>()
{
for(int i = 1; i <= 10; ++i){
do_something( i );
}
}
template<>
void do_case<CASE_B>()
{
do_something( 0 );
}
// Usage
...
do_case<CURRENT_CASE>(); // CURRENT_CASE is the compile time constant
If your CASE_B/CASE_B determination can be expressed as a compile time constant, then you can do what you want in a nice, readable format using something like the following (which is just a variation on your example of using the ?: operator for the for loop initialization and condition):
enum {
kLowerBound = (CASE_A ? 1 : 0),
kUpperBound = (CASE_A ? 10 : 0)
};
for (int i = kLowerBound; i <= kUpperBound; ++i) {
// do something
}
This makes it clear that the for loop bounds are compile time constants - note that I think most compilers today would have no problem making that determination even if the ?: expressions were used directly in the for statement's controlling clauses. However, I do think using enums makes it more evident to people reading the code.
Again, any compiler worth its salt today should recognize when i is invariant inside the loop, and in the CASE_B situation also determine that the loop will never iterate. Making i const won't benefit the compiler's optimization possibilities.
If you're convinced that the compiler might be able to optimize better if i is const, then a simple modification can help:
for (int ii = kLowerBound; ii <= kUpperBound; ++ii) {
const int i = ii;
// do something
}
I doubt this will help the compiler much (but check it's output - I could be wrong) if i isn't modified or has its address taken (even by passing it as a reference). However, it might help you make sure that i isn't inappropriately modified or passed by reference/address in the loop.
On the other hand, you might actually see a benefit to optimizations produced by the compiler if you use the const modifier on it - in the cases where the address of i is taken or the const is cast away, the compiler is still permitted to treat i as not being modified for its lifetime. Any modifications that might be made by something that cast away the const would be undefined behavior, so the compiler is allowed to ignore that they might occur. Of course, if you have code that might do this, you have bigger worries than optimization. So it's more important to make sure that there are no 'behind the back' modification attempts to i than to simply marking i as const 'for optimization', but using const might help you identify whether modifications are made (but remember that casts can continue to hide that).
I'm not quite sure that this is what you're looking for, but I'm using this macro version of the vanilla FOR loop which enforces the loop counter to be const to catch any modification of it in the body
#define FOR(type, var, start, maxExclusive, inc) if (bool a = true) for (type var##_ = start; var##_ < maxExclusive; a=true,var##_ += inc) for (const auto var = var##_;a;a=false)
Usage:
#include <stdio.h>
#define FOR(type, var, start, maxExclusive, inc) if (bool a = true) for (type var##_ = start; var##_ < maxExclusive; a=true,var##_ += inc) for (const auto var = var##_;a;a=false)
int main()
{
FOR(int, i, 0, 10, 1) {
printf("i: %d\n", i);
}
// does the same as:
for (int i = 0; i < 10; i++) {
printf("i: %d\n", i);
}
// FOR catches some bugs:
for (int i = 0; i < 10; i++) {
i += 10; // is legal but bad
printf("i: %d\n", i);
}
FOR(int, i, 0, 10, 1) {
i += 10; // is illlegal and will not compile
printf("i: %d\n", i);
}
return 0;
}