Changing C++ Output Without Changing the Main() Function

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:

  1. The C Runtime Environment function applicable for your setup (there are multiple possibilities) saves the int argc, char **argv, char **envp arguments in some memory locations - these are luckily adjacent in case of my setup.
  2. On my 64 bit system, due to memory alignment rules the int argc address would be just 1 extra sizeof(int) ahead of the memory pointed to by char **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



Leave a reply



Submit