c - output is not changing after being put through a function
fuctionSumAvg
doesn't compute the sum or average of anything. It just sets the local variable sum
to the number that it received, and returns that same number. It's not adding it to a previous total. And calculating an average requires dividing the sum by the count of elements, but you never sum or count anything.
You can use static variables to hold the running sum and count. But since a function can only return one value, you'll need to use a pointer parameter to return a second value.
int functionSumAvg(int sumAvgInput, int *avg){ // return value is sum
static int sum = 0;
static int count = 0;
sum += sumAvgInput;
count++;
*avg = sum/count;
return sum;
}
Then you call it like this:
int sum, average;
sum = functionSumAvg(number, &average);
printf("Sum = %d Average = %d\n", sum, average);
How to change the variable value without changing its * value?
A pointer is an object in many programming languages that stores a memory address. A pointer references a location in memory, and obtaining the value stored at that location is known as dereferencing the pointer
Take a look at this code snippet
#include <stdio.h>
int main() {
int a = 6;
int *b = &a;
printf("a = %d b = %p *b = %d\n", a, (void*)b, *b);
a = 20;
printf("a = %d b = %p *b = %d\n", a, (void*)b, *b);
}
Output:
a = 6 b = 0x7fff3ead8d6c *b = 6
a = 20 b = 0x7fff3ead8d6c *b = 20
As you can see, assigning a new value to a did not change the value of b. It did change the value pointed to by b, however. That is, b did not change, while *b did.
how to change the arguments of main function before running it
Modifying the C Runtime Environment's int argc
argument counter before the C int main(int argc, char **argv)
method is called. . . - - - = = = (; A NASTY HACK ;) = = = - - - . . .
I am using:
- The latest C++ compiler currently available for OS X High Sierra,
- Installed the currently standard way, using
brew
.
To reproduce the results below argc.cpp
code listing, either:
- Update your Mac OS setup to reflect mine,
- Install GNU compilers on your Ubuntu 64
- Install GNU compilers for your particular setup
argc.cpp :
#include <stdio.h>
__attribute__((constructor)) void start(int argc, char **argv)
{
int * pc = (int *) argv - 2; // NASTY HACK TO GET C RUNTIME argc * ;)
printf("argc = %d \n", *pc); // the original argc, on most systems ;)
int NUMBER_OF_PARAMETERS_NEEDED_FOR_FUZZING = 1; // Replace this line
// with the simple/complex logic needed for fuzz testing (fuzzing)
if(!(argc > NUMBER_OF_PARAMETERS_NEEDED_FOR_FUZZING)){
argc = NUMBER_OF_PARAMETERS_NEEDED_FOR_FUZZING + 1;
*pc = argc; // NASTY HACK TO OVERWRITE C RUNTIME argc ;)
}
// *pc = 2; // uncomment this to see that you can also reduce argc
argv[1] = "hello"; // Example setting of a fuzzy argument
// Add more lines, a loop, etc... here to set more fuzzy arguments
for (int i = 0; i < argc; i++) {
printf("%s: argv[%d] = '%s'\n", __FUNCTION__, i, argv[i]);
}
printf("argc = %d \n", argc); // the possibly modified argc
}
int main(int argc, char **argv)
{
for (int i = 0; i < argc; i++) {
printf("%s: argv[%d] = '%s'\n", __FUNCTION__, i, argv[i]);
}
printf("argc = %d \n", argc); // the possibly modified argc
return 0;
}
Mac OS Terminal:
Compilation:
$ /usr/local/bin/c++-9 argc.cpp -o argc
Running with 0
arguments, original int argc = 1
:
$ ./argc
argc = 1
start: argv[0] = './argc'
start: argv[1] = 'hello'
argc = 2
main: argv[0] = './argc'
main: argv[1] = 'hello'
argc = 2
Running with 3
arguments, original int argc = 4
:
$ ./argc 1 2 3
argc = 4
start: argv[0] = './argc'
start: argv[1] = 'hello'
start: argv[2] = '2'
start: argv[3] = '3'
argc = 4
main: argv[0] = './argc'
main: argv[1] = 'hello'
main: argv[2] = '2'
main: argv[3] = '3'
argc = 4
Running , to demonstrate argc
reduction capability,
- after uncommenting line 13 and recompiling (that hardcodes
argc = 2
) :
*pc = 2; // uncomment this to see that you can also reduce argc
with the same 3
arguments, as above, original int argc = 4
:
$ ./argc 1 2 3
argc = 4
start: argv[0] = './argc'
start: argv[1] = 'hello'
start: argv[2] = '2'
start: argv[3] = '3'
argc = 4
main: argv[0] = './argc'
main: argv[1] = 'hello'
argc = 2
If the C Runtime Environment is not initialized on your system similar to the listing:
- Initialization code run first thing by the ELF startup code of the GNU C Library,
you may need to either:
- Research the difference, by comparing your local C Runtime Environment to the GNU sample above, and/or
- Experimentally modify my code, until it works for you. For example: walk the int pointers before and also !after! the location of
argv
and see what you find there...
If you find hacking your current C Runtime Environment too hard, try to:
- Install GNU compilers on your Ubuntu 64,
- Install GNU compilers for your particular setup.
Here is how/why this hack works:
- The
C Runtime Environment
function applicable for your setup (there are multiple possibilities) saves theint argc, char **argv, char **envp
arguments in some memory locations - these are luckily adjacent in case of my setup. - On my
64 bit
system, due to memory alignment rules theint argc
address would be just 1 extrasizeof(int)
ahead of the memory pointed to bychar **argv
, that is why the- 2
in the:int * pc = (int *) argv - 2;
line is not- 1
.
╦ ╦ ╔═╗ ╔═╗ ╔═╗ ╦ ╦ ╦ ╦ ╔═╗ ╔═╗ ╦╔═ ╦ ╔╗╔ ╔═╗ ╦ ╦ ╦
╠═╣ ╠═╣ ╠═╝ ╠═╝ ╚╦╝ ─── ╠═╣ ╠═╣ ║ ╠╩╗ ║ ║║║ ║ ╦ ║ ║ ║
╩ ╩ ╩ ╩ ╩ ╩ ╩ ╩ ╩ ╩ ╩ ╚═╝ ╩ ╩ ╩ ╝╚╝ ╚═╝ o o o
Why the value of b does not change in main function?
In C, all parameters are pass by value. That means that changing the value of a function parameter is not reflected in the calling function.
You can however emulate passing by reference by passing the address of a variable to a function, as you did with c
. When you then dereference the pointer variable in the function, you're changing what c
in test_func
points to, i.e. c
in main.
This is why b
doesn't change in main
. For the same reason, a
also doesn't change. a
does however change on the following line when it is assigned to.
It's also important to note that a
, b
, and c
in main
are not the same as a
, b
, and c
in test_func
. You could change the names in either one and it will work the same way.
In order for a
and b
to change, you need to pass their addresses, just like you did with c
. So change the type of the parameters of your function (and dereference to get the values):
void test_func(int *a, int *b, int *c) {
*a ^= 5;
*c = *a + *b;
*b <<= 4;
}
Then call it like this, passing in the addresses of a
and b
:
test_func(&a, &b, &c);
Change value in main using void sub-function
The code
void change_number(int *x)
{
x = *x+3;
printf("In the subroutine: x = %d\n", x);
}
should read
void change_number(int *x)
{
*x = *x+3;
printf("In the subroutine: *x = %d\n", *x);
}
This will use the pointers as intended (you need to dereference them on the LHS as well)
Related Topics
How to Ignore False Positive Memory Leaks from _Crtdumpmemoryleaks
Detect When Network Cable Unplugged
Partial Specialization Ordering with Non-Deduced Context
What's the Semantically Accurate Position for the Ampersand in C++ References
Difference Between Console (/Subsystem:Console) and Windows (/Subsystem:Windows)
Why Are C++ Int and Long Types Both 4 Bytes
Advantages of Using Initializer List
Concurrent Writes in the Same Global Memory Location
Generate N Random Numbers Within a Range with a Constant Sum
Vector of Class Without Default Constructor
Explicit Call to Destructor Is Not Destroying My Object Why
C++ Virtual Function Table Memory Cost
Why Does Long Long 2147483647 + 1 = -2147483648
How Does the Friend Keyword (Class/Function) Break Encapsulation in C++
What Does Afx_Manage_State(Afxgetstaticmodulestate()) Do Exactly