I am taking an OS course and I have some questions about the following codes
#include <stdio.h>
int * addition(int a, int b){
int c = a + b;
int *d = &c;
return d;
}
int main(void){
int result = *(addition(1,2));
int *result_ptr = addition(1,2);
/*never interchange */
printf("result = %d\n", *result_ptr);
printf("result = %d\n", result);
return 0;
}
//this code outputs 3
3
Here is what happens when i swap the printfs, in fact the second one just prints out a random address
#include <stdio.h>
int * addition(int a, int b){
int c = a + b;
int *d = &c;
return d;
}
int main(void){
int result = *(addition(1,2));
int *result_ptr = addition(1,2);
/*never interchange */
printf("result = %d\n", result);
printf("result = %d\n", *result_ptr);
return 0;
}
//this code outputs 3
and a random address
However, if i make them into one printf
#include <stdio.h>
int * addition(int a, int b){
int c = a + b;
int *d = &c;
return d;
}
int main(void){
int result = *(addition(1,2));
int *result_ptr = addition(1,2);
/*never interchange */
printf("result = %d %d \n", result, *result_ptr);
return 0;
}
//this code outputs 3 3
I wonder if the printf clear the memory so the pointer becomes dangerous?
The problem is in your addition function. You're returning the address of a local variable. Because locals live on the stack, the memory for that variable goes out of scope when the function returns. This caused undefined behavior such as what you experienced.
For this to work properly, you need to allocate memory on the heap using malloc:
int *addition(int a, int b){
int *d = malloc(sizeof(int));
*d = a + b;
return d;
}
When this function returns, you need to be sure to free the pointer that was returned after you're done with it. Otherwise, you'll have a memory leak.
Related
So I was practicing some coding about how functions work and I ran into a problem:
The code is meant to reverse a number. The algorithm works perfectly well so I don't have any problem with that. But I want to use functions in my code so I edited it like below and somehow it doesn't work anymore(there was no error, but when I run the code, after I entered in the first scanf, the code stopped and stays like that, no response). Can someone help me with this pls (This question may sound a little stupid but I'm just trying to be better at it :v)
Code:
#include <stdio.h>
#include <string.h>
int input(int *a) {
scanf("%d", &*a);
}
int revint(int *a, int *b){
int c;
while(a != 0)
{
c = *a % 10;
*b *= 10;
b += c;
*a /= 10;
}
return *b;
}
int output(int b) {
printf("%d", b);
}
int main(){
int a;
int b = 0;
input(&a);
revint(&a, &b);
output(b);
return 0;
}
There are several issues in your code:
input() and output() do not have a return statement and should be declared to return void in your code.
It makes more sense for input() to return the value rather then fill a pointer parameter. Therefore in my version input() does return a proper int value.
Several occurrences of a, b in revint() should be *a,*b (since a and b are pointers and we need to de-reference it first).
See the code below:
int input(void) {
int a;
scanf("%d", &a);
return a;
}
int revint(int *a, int *b)
{
int c;
*b = 0;
while (*a != 0)
{
c = *a % 10;
*b = *b * 10 + c;
*a /= 10;
}
return *b;
}
void output(int b) {
printf("%d", b);
}
int main(void)
{
int a;
int b = 0;
a = input();
revint(&a, &b); // passing the addresses
output(b);
return 0;
}
NOTE: For simplicity the input() function doesn't validate that scanf() actually succeeded. In should better be done in the real code in which the user is handling.
Better scanf():
if (scanf("%d", &a) != 1)
{
fprintf(stderr, "bad input\n");
exit(1);
}
In the real code the user can consider retrying getting the input as long as it is invalid.
Update:
As you can see in #Gerhard's answer, revint could be re-written to avoid the pointer semantics altogether. It will indeed make the code simpler and for this particular use case I actually think it is better.
My answer was written trying to maintain as much as possible the semantics that the user introduced in his question code. So I suggest you apply my solution only if it really makes sense for you to pass pointers.
input changed to use the pointer correctly (&*a).
Removed the pointers to revint as it is not helping and your code had an point error there (b += c; modifies pointer not value).
#include <stdio.h>
#include <string.h>
void input(int *a) {
scanf("%d", a);
}
int revint(int a){
int b = 0;
int c;
while(a != 0)
{
c = a % 10;
b *= 10;
b += c;
a /= 10;
}
return b;
}
int output(int b) {
printf("%d", b);
}
int main(){
int a;
int b = 0;
input(&a);
b = revint(a);
output(b);
return 0;
}
I have the following code:
#include <stdio.h>
#include <stdlib.h>
int f(int x, int *py, int **ppz) {
int y, z;
**ppz += 1;
z = **ppz;
*py += 2;
y = *py;
x += 3;
return x + y + z;
}
int main(void) {
int c = 4;
printf("f(): %d\n", f(c, &c, &&c));
printf("c: %d\n", c);
return EXIT_SUCCESS;
}
How can I access **ppz correctly, because so I get an error message: "label 'c' used, but not defined".
An int** is a pointer to an int*. You need to create a variable of type int* to be able to pass a pointer to it somewhere. Here is what you should do:
int main(void) {
int c = 4;
int* pc = &c;
printf("f(): %d\n", f(c, pc, &pc));
printf("c: %d\n", c);
return EXIT_SUCCESS;
}
Refer #ikegami's answer for an explanation of the proper use of a pointer to a pointer.
You want to modify a variable of type int, so the parameter should be int *, not int **.
You'd use int ** if you wanted to modify a variable of type int * variable. That's not the case here.
For example,
void f(int **pp) {
*pp = malloc(10);
}
int main(void) {
int *p;
f(&p);
// ...
free(p);
}
Can you explain the code below? How we can use #define for a keyword of C?
#include <stdio.h>
#define int int*
int main(void) {
int *p;
int q;
p = 10;
q = 5;
printf("%d %d", p, q);
// your code goes here
return 0;
}
Output:
10 5
This #define int int* is a preprocessor macro. If you want to define your own synonyms for types then use typedef. You cannot create keywords in a language you did not create.
Sample:
#include <stdio.h>
typedef int * myIntPtr;
int main(void) {
int i = 10;
myIntPtr x = &i;
printf("%d", *x);
return 0;
}
Output:
10
Also semantically making an int to an int * makes no sense.
#define a b
will change all "a" to "b" in your source after the #define
#include <stdio.h>
#define int int*
int main(void) {
int *p;
int q;
p = 10;
q = 5;
printf("%d %d", p, q);
// your code goes here
return 0;
}
will change to
int main(void) {
int **p;
int *q;
p = 10;
q = 5;
printf("%d %d", p, q);
// your code goes here
return 0;
}
i have code to array of func pointer
#include <stdio.h>
int sum(int a, int b);
int subtract(int a, int b);
int mul(int a, int b);
int div(int a, int b);
int (*p[4]) (int x, int y);
int main(void)
{
int result;
int i, j, op;
p[0] = sum; /* address of sum() */
p[1] = subtract; /* address of subtract() */
p[2] = mul; /* address of mul() */
p[3] = div; /* address of div() */
printf("Enter two numbers: ");
scanf("%d %d", &i, &j);
printf("0: Add, 1: Subtract, 2: Multiply, 3: Divide\n");
do {
printf("Enter number of operation: ");
scanf("%d", &op);
} while(op<0 || op>3);
result = (*p[op]) (i, j);
printf("%d", result);
return 0;
}
int sum(int a, int b)
{
return a + b;
}
int subtract(int a, int b)
{
return a - b;
}
int mul(int a, int b)
{
return a * b;
}
int div(int a, int b)
{
if(b)
return a / b;
else
return 0;
}
code for array of pointer to function:
#include <stdio.h>
int sum(int, int);
int product(int, int);
int subtract(int, int);
int main()
{
int i = 0;
int a = 10;
int b = 5;
int result = 0;
int (*pfun[3])(int, int);
pfun[0] = sum;
pfun[1] = product;
pfun[2] = subtract;
for( i = 0 ; i < 3 ; i++)
{
result = pfun[i](a, b);
printf("\nresult = %d", result);
}
result = pfun[1](pfun[0](a, b), pfun[2](a, b));
printf("\n\nThe product of the sum and the subtract = %d\n",result);
}
int sum(int x, int y)
{
return x + y;
}
int product(int x, int y)
{
return x * y;
}
int subtract(int x, int y)
{
return x - y;
}
now how to combine this two program. such that array of pointers pointing to func pointers and the func pointers may have different number of args? any suggestion.
You not only need to store function pointers with a variable number of arguments (that is not very difficult, you could use a union for instance), but you also need to make sure you call the functions with the correct argument, and that is a bit trickier given your design.
I suggest to use a stack instead. All your functions would only take the stack as an argument:
void sum(stack_t *stack);
void subtract(stack_t *stack);
void product(stack_t *stack);
And your array could be declared this way:
typedef void callback_t(stack_t *);
callback_t *p[] =
{
sum,
subtract,
product,
/* ... */
};
Then for instance sum would be implemented as such:
void sum(stack_t *stack)
{
if (depth(stack) < 2)
perror("Not enough arguments in stack!");
int b = popstack(stack);
int a = popstack(stack);
int c = a + b;
pushstack(stack, c);
}
But unary minus would be implemented this way:
void neg(stack_t *stack)
{
if (depth(stack) < 1)
perror("Not enough arguments in stack!");
int a = popstack(stack);
pushstack(stack, -a);
}
Each function decides how many arguments they need. The caller does not need to know.
I have a funtion_ptr function pointer which point to add_int function.
case 1: when lay a statement function_ptr = &add_int outside main function
--> compiler error: error C2373: 'function_ptr' : redefinition; different type modifiers (this is in )
#include <stdio.h>
int add_int(int n, int m){
return n + m;
}
int(*function_ptr)(int, int);
function_ptr = &add_int; // it's here
void main(){
int sum = (* function_ptr)(2, 3);
printf("sum = %d", sum);
_getch();
}
case 2: function_ptr = &add_int; in main function --> it is true
#include <stdio.h>
int add_int(int n, int m){
return n + m;
}
int(*function_ptr)(int, int);
void main(){
function_ptr = &add_int; // it's now here
int sum = (* function_ptr)(2, 3);
printf("sum = %d", sum);
_getch();
}
Could anyone explain for me different between the two case.
Thanks!
function_ptr = &add_int; is an assignment statement. Statements are allowed inside functions, but outside functions only declarations are allowed. Since assignment is not a declaration, the compiler issues an error.
If you want to assign the pointer as part of its declaration/definition, you could combine the declaration and the assignment, like this:
#include <stdio.h>
int add_int(int n, int m){
return n + m;
}
int(*function_ptr)(int, int) = &add_int;
int main(){
int sum = (* function_ptr)(2, 3);
printf("sum = %d", sum);
return 0;
}
Demo.
You don't need the & in the assignment statement, the function's name (add_int) IS its address... and the assignment statement should be within the bounds of a function.
Here's an example that works:
#include <stdio.h>
int add_int(int n, int m);
int(*function_ptr)(int, int);
void main(){
function_ptr = add_int;
int sum = (* function_ptr)(2, 3);
printf("sum = %d", sum);
getc(stdin);
}
int add_int(int n, int m){
return n + m;
}