C: Passing variable down the functions, is this design valid? - c

This question may appear too basic, but please do look at it:
#include <stdio.h>
void f3(int *p) {
*p = 100;
}
void f2(int *p) {
f3(p);
}
void f1(int *p) {
f2(p);
}
int main(int argc, char **argv) {
int a;
f1(&a);
printf("%d\n", a);
return 0;
}
Basically, the address of a stack variable (a) is passed to multiple functions down the call stack where its value is changed at the last function.
Is this way of changing values a good design? If not, what should be a better design?
My question arises because with a Heap variable (say a being a heap variable as shown below), this design is OK since the allocated memory is "global" to all functions.
int main(int argc, char **argv) {
int *a = malloc(sizeof(int)*1);
f1(a);
printf("%d\n", a);
free(a)
return 0;
}
But with a local variable, I'm doubtful if 2 levels down the call stack, its still valid to access the memory with just a single level pointer.
Should I pass another level of pointer down each function call? (like f1(&a) then f2(&p) and so on).

What you are doing is absolutely correct. The variable a exists all the time, and f3 will receive the address of variable a. No problem at all.

Related

C: why should I declare a pointer?

It seems there are many questions of the form "should I declare X?" but not this specific one. I hope it is ok to ask this.
The title says it all: why should I declare a pointer? Even better: there are risks if I do not declare the pointer? Consider the following examples:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <string.h>
void func(int *ptr);
int main (int argc, char **argv)
{
int a;
int *PTRa;
a = -1;
PTRa = &a;
func(PTRa);
printf("%d\n", a);
return 0;
}
void func(int *ptr)
{
*ptr = 1;
return;
}
I get a=1. In this case I would say the pointer is declared (and assigned as well): I have the line int *PTRa; (declaration) and the line PTRa = &a; (assignment). The results is correct. I don't get any warning.
Imagine now to replace the main with the following:
int main (int argc, char **argv)
{
int a;
a = -1;
func(&a);
printf("%d\n", a);
return 0;
}
Here I do not declare the pointer but just give the address of a to func. The result is correct and I don't get warnings.
My understanding is that the two approaches are identical: func always gets the same input, the address of a. I would even dare to say that I feel the second approach to be better, as I feel it to be clearer and I feel the variable PTRa to be useless and somewhat redundant. However, I always see codes where the first approach is used and I have the feeling I will be told to do so. Why?
You are correct: there's no point in declaring a pointer in your example. A pointer is just a variable that holds an address. The cleaner approach is to pass directly the address of the variable: func(&a) instead of doing one extra step and declaring PTRa.
Note that not all cases are this simple. For example, if you want to have an array of ints, but you want to be able to grow that array dynamically because you don't know how big it should be you have to declare a pointer:
int count = ...; // get the count from the user, from a file, etc
int *list_of_ints = malloc(sizeof(int) * count);
if (list_of_ints == NULL)
{
// malloc failed.
printf("Not enough memory!\n");
exit(1);
}
// Now `list_of_ints` has enough space to store exactly `count` `int`s
EDIT: as #paulsm4 pointed out in a comment, the question Why use pointers? is a great source of information related to this topic.
EDIT 2: one good reason to want a pointer to the address of a variable might be that you want a pointer inside a structure or array:
struct foo
{
int x;
};
struct bar
{
int y;
struct foo f;
};
struct bar b;
struct foo *ptr_foo = &b.f;
You can now work more easily with b.f because you're just working with a struct foo.
In this case there's no benefit in creating a separate pointer variable.
It might be necessary in more complex cases, just like it's sometimes necessary to create variables of any other type.
From the title, I thought you're talking about pointer type, but actually, you are asking if declaring a variable is needed.
Variable is a piece of memory, storing some numbers(bytes), and the type of the variable, indicating how you and your program interpret those bytes: integer? float? character? etc.
Pointer is the memory address, it could be of a variable, or a function, or something else.
A variable of pointer is a small area in the memory, storing the address of other(or even same) memory.
You decide if you need an extra variable to store the pointer. It's the same to the decision that if you want a variable to store an integer:
int v = -1;
abs(v); // use variable
abs(-1); // use constant

Why can we initialize inside a function and still use that value outside the function?

For example:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
typedef struct {
int n;
double d;
} some_thing;
void alloc_and_init_some_thing(some_thing** s, int n, double d) {
some_thing si = { .n=n, .d=d };
*s = malloc(sizeof(**s));
memcpy(*s, &si, sizeof(**s));
}
void alloc_and_init_int(int **i) {
int j = 21;
*i = malloc(sizeof(**i));
memcpy(*i, &j, sizeof(**i));
}
int main() {
some_thing *s;
alloc_and_init_some_thing(&s, 41, 31);
printf("s->n=%d s->d=%f\n", s->n, s->d);
int *i;
alloc_and_init_int(&i);
printf("*i=%d\n", *i);
return 0;
}
I'm still learning C and the difference between the stack and the heap. When we declare and initialize the variable si in the function alloc_and_init_some_thing, doesn't this value exist on the stack? Hence it should get wiped out when the function finishes?
But I can see that that doesn't actually occur. Back in the main function, when we print s->n, we get the value 41.
Similarly, when we print the value for *i in the main function, it prints 21.
Why is that?
The line memcpy(*s, &si, sizeof(**s)); copies the the structure si on the stack into the heap allocated structure s, thus making it persist in memory as heap allocations can be accessed anywhere in the program. It's merely a pointer to an address in memory.
The same thing happens in the similar function.
You are right that the lifetime of "si" and "j" are limited to their respective functions and not available after the return from those functions. However, their contents have been replicated via malloc/memcpy prior to the return of the functions and the pointers to the replicas are stored in variables "s" and "i", which are still alive at the time of printing (or using) those replicas.

Pthread struct argument with void*

Hy,
I was wondering if something like this is possible, without using heap(malloc/calloc) Suppose I have a struct
like this:
typedef struct {
void* par1_;
void* par2_;
}parameters;
and another one for position:
typedef struct {
short x;
short y;
}position;
This is a function that gets called by the thread.
void* car(void* arg)
{
parameters car_type = *((parameters*) arg);
int first_par = *(int*)&car_type.par1_;
int second_par = *(int*)&car_type.par2_; // can I do this?
//if yes how do I extract now values from position struct "pos.x and pos.y"
}
From my main thread I want to mark position in the struct "position", assign that struct to the second parametar "par2_", and than send that to my function car.
int main()
{
parameters pars;
position pos;
pos.x = 44;
pos.y = 25;
pars.par1_ = (void*) CAR_TYPE; // Global Variable
pars.par2_ = &pos; // not sure about this?
pthread_t tid;
pthread_create(&tid, NULL, car, (void*) &pars);
pthread_join(tid, NULL);
I'm sorry if this is a stupid question. Obviously I'm new to all this. Once again, I do not want to use heap. This is minimal example of my program.
I think you want something more like this;
void* car(void* arg)
{
parameters car_type = *((parameters*) arg);
int first_par = car_type.par1_; // This is CAR_TYPE is it really an int?
position *second_par = (position *)car_type.par2_;
second_par->x, second_par->y;
}
Although you might just want to change your parameters struct to include the types you really want.
typedef struct {
int par1_;
position* par2_;
}parameters;
void* car(void* arg)
{
parameters car_type = *((parameters*) arg);
int first_par = car_type.par1_; // This is CAR_TYPE is it really an int?
car_type.par2_->x; //access like this
}
Not sure what you're asking, so I'll give you standard advice that seems like it pertains to the situation.
Lifetime
Be very careful when passing pointers to stack memory. Always keep these three things in mind:
What will use the pointer?
What will it be used for? Which functions will end up with it? You'll need to know this to deal with the next two points.
Where will the pointer be stored?
If the pointer never leaves the stack, it's fine. If the pointer gets stored in heap memory, which has a chance of outliving the stack frame, alarm bells. If the pointer outlives the stack frame, scary unexpected data corruption is par for the course. Do not allow that to happen.
When will the pointer be used?
Anything in or called by the stack frame in which the memory is first used is OK. Anything above that, and the memory is not yours to play with. Make sure that you never ever EVER EVER EVER return a pointer to stack memory you've just got.
To reiterate:
Do:
#include <stdio.h>
int main(int argc, char *argv[]) {
int nums = {12, 630, 43, 0};
printf("%d", sum(nums));
}
int sum(int *num_pointer) {
int count = 0;
for (; *num_pointer; num_pointer += 1) {
add(&count, *num_pointer);
}
return count;
}
void add(int *a, int b) {
*a += b;
}
Don't:
int main(int argc, char *argv[]) {
print_int(get_int(7));
}
int *get_int(int value) {
return &value;
}
void print_int(int *num) {
printf("%d", *num);
}
Also, don't type-cast when you don't have to. It's a big sign pointing towards bad program design; consider revising it.

Why uninitialized local variable always has the same initial value?

In this piece of code, why in my testing the result is always 1, 2, and 3?
#include <stdio.h>
void test() {
int a;
a++;
printf("%d",a);
}
int main(int argc, char *argv[]) {
test();
test();
test();
}
I think the variable in test() is static, isn't it? And Why?
The variable is not static. You're accessing an uninitialized variable. The behavior is undefined.
As other answers told, your variable is not initialized.
It prints 1, 2 and 3 possibly because of your compiler compiled the code with prolog(prologue) that cleans the stack with zeros.
The local variables in C, actually point to the offset on your stack, and the stack frame will be restored after the call is returned.
I googled and selected a artical randomly that told about this, see [How function calls work?].
Here is a video talk about that [Assembly Programming Assembly Function Stack Frame Explained ] (again, selected randomly).
And Wikipedia explains the [Call stack] as well.
Because you are working with an unintialize value... (random behaviour in this case).
Initialize your variable (example to 0) :
#include <stdio.h>
void test(){
int a=0;
a++;
printf("%d",a);
}
int main(int argc, char *argv[]) {
test();
test();
test();
}
No, your variable is not static at all!
https://stackoverflow.com/a/1597426/1758762
Static variables (file scope and function static) are initialized to zero:
int x; // zero
int y = 0; // also zero
void foo() {
static int x; // also zero
}
Non-static variables (local variables) are indeterminate. Reading them prior to assigning a value results in undefined behavior.
void foo() {
int x;
printf("%d", x); // the compiler is free to crash here
}
the variable you are trying to print is not static and neither it is initialized , thus it is taking garbage value , which seems random to you , if you execute this program on a different machine ,then there you will have different output because there you will have different garbage value
in order to avoid it , you will have to initialize your variable with some value

struct return error-C

this program is written in C
it supposed to get a two D array( matrixAdd) and scan it with scanMtx (the scanning function isn't here becuase the code isn't relevant)
the problem: the EDMtx function return the scanning matrix 1,1,1,,1,-8,1,,1,1,1
when it return back to main it is : 0,0,0,0,0,0,junk,junk,junk
it seems that there is a address error
what did i do wrong?
#include "stdafx.h"
#include <stdio.h>
#include <stdlib.h>
struct matrix
{
int* ptr;
int row;
int column;
};
matrix EDMtx();
void main( int argc, char* argv[])
{
int matrixAdd[5][5]={{1,1,1,3,4},{1,1,1,3,4},{1,1,1,3,4},{1,1,1,3,4},{1,1,1,3,4}};
matrix mtx;
matrix scanMtx;
mtx.ptr=&matrixAdd[0][0];
mtx.row=5;
mtx.column=5;
scanMtx= EDMtx();
// mtx= ScanM(mtx,1,1,scanMtx);- doesn't important to you.
getchar();
}
matrix EDMtx()
{
int matrx[3][3]={{1,1,1},{1,-8,1},{1,1,1}};
matrix Mtx;
Mtx.ptr=&matrx[0][0];
Mtx.row=3;
Mtx.column=3;
return Mtx;
}
The variables matrixAdd and matrx, and the memory they point to, have local scope only. If you want them to persist after returning from a function, either declare them static, or redesign your code logic. (e.g. by using malloc to allocate memory explicitly)
In EDMtx, Mtx.ptr is pointed to a stack variable. This is getting destroyed probably. If you want to exchange pointers to variables they must be on the heap
matrix EDMtx()
{
int matrx[3][3]={{1,1,1},{1,-8,1},{1,1,1}};
matrix Mtx;
Mtx.ptr=&matrx[0][0];
Mtx.row=3;
Mtx.column=3;
return Mtx;
}
matrx is a local variable. So, it goes out of scope when upon return of EDMtx(). And the Mtx.ptr has the reference of the local variable matrx. And so the pointer member of scnMtx, is getting garbage values upon dereferencing. Never return references of a local variable.

Resources