how this works ?

L

lector

in my code i am seperate components or modules. suppose



foo2.c

int foo2(int *a)
{
/* some operations which vary the value of a
the function returns 0 if successful or 1 if failure is
encountered. */
}

foo.c

#include "foo2.h"
#include <stdio.h>
int main(void)
{
int a,i;

i= foo2(&a);
if(i==1)
{
printf("failure");
return(EXIT_FAILURE);
}
else
{
printf("%d",a);
return(EXIT_SUCCESS);
}

}


when call a function and pass adress to it then it is call by
reference. the function foo2 will change the value at the address
given to it as parameter. but my question is won't the variable be
destroyed after the function foo2() is over ? if we make a variable
extern then is it true that it will appear everywhere in the whole
code with the same value ?
 
L

Lew Pitcher

lector said:
in my code i am seperate components or modules. suppose



foo2.c

int foo2(int *a)
{
/* some operations which vary the value of a
the function returns 0 if successful or 1 if failure is
encountered. */
}

foo.c

#include "foo2.h"
#include <stdio.h>
int main(void)
{
int a,i;

i= foo2(&a);
if(i==1)
{
printf("failure");
return(EXIT_FAILURE);
}
else
{
printf("%d",a);
return(EXIT_SUCCESS);
}

}


when call a function and pass adress to it then it is call by
reference.

No it isn't. C doesn't "call by reference". The
foo2(&a)
is a call by value, with the value being the "address" of the local variable
a.
the function foo2 will change the value at the address
given to it as parameter.
Yes.

but my question is won't the variable be
destroyed after the function foo2() is over ?

Certainly, the /argument/ passed to foo2() will be lost. But that argument
wasn't the local variable in main(), it was a "copy" of the /address/ of
the local variable in main().

if we make a variable
extern then is it true that it will appear everywhere in the whole
code with the same value ?

Yes and no

"extern" says that the variable is defined outside of the translation unit.
That means that the variable must be defined in some other translation
unit.

Global variables may be defined as "global within the translation unit, but
not accessable outside of the unit" by making them
"static"

And, of course, local variables take precedence over global variables

int Var;

void Func(void)
{
int Var;
Var = 7; /* changes the Var defined within Func() */
}


--
Lew Pitcher

Master Codewright & JOAT-in-training | Registered Linux User #112576
http://pitcher.digitalfreehold.ca/ | GPG public key available by request
---------- Slackware - Because I know what I'm doing. ------
 
L

lector

I will post another question which I believe is not offtopic with
regard to this thread

I am trying to build this link list here with following modules -

create.c : This module create the link list.

print.c : This module print the link list

ll.c: Contains main routine.

/* create.h */

#ifndef create_list
#define create_list

#include <stdio.h>
#include <stdlib.h>

typedef struct node_struct
{
int data;
struct node_struct *next;
}node;

extern void create_link_list(node *, int);

#endif


/* create.c */

#include "create.h"

void create_link_list(node *root, int n)
{
node *p, *prev;
int i;

for(i=0; i<n; i++)
{
p = malloc(sizeof(node));
p->next = NULL;
printf("Enter data\n");
scanf("%d", &p->data);
if(root == NULL)
{
root = p;
prev = root;
}
else
{
prev->next = p;
prev = p;
}
}
}

/* print.h */
#ifndef print_h
#define print_h

#include "create.h"

extern void print_link_list(node *);

#endif

/* print.c */
#include "print.h"

void print_link_list(node *root)
{
node *p;

p = root;

while(p != NULL)
{
printf("%d\n", p->data);
p = p->next;
}

}

/* ll.c */
#include "create.h"
#include "print.h"

int main(void)
{
node *root;
int n;
printf("Enter how many numbers\n");
scanf("%d", &n);
root = NULL;
create_link_list(root, n);
print_link_list(root);
return 0;

}


The program compile successfuly and I could link all the obj files
without any errors or warnings. When I execute the
application(ll.exe), I can input all the numbers but the link list is
not printed. I think the problem lies in the fact that the link list
has been created but the copy of updated pointer to the root node is
not available as it got destroyed once the create routine terminated.
As root was null, nothing was printed on the screen. I think it will
be better to return the pointer to root node but what if a function
causes exceptions and a 1 or 0 has to be returned to indicate if the
function executed successfuly or not ? We can only return 1 value from
a function. You cannot return an integer(0/1) and a pointer to root
node at the same time. Not sure if this explanation is accurate but I
really hope some one clarify what is going on here as this is the
first time I tried to write a link list program split into many source
files.
 
L

lector

lector said:


For example:

#include <stddef.h>

int foo2(int *a)
{
if(a != NULL)
{
*a = 6;
}
return a == NULL;

} /* was that so hard to type? */

Not supplied. I presume it looks something like this:

#ifndef H_FOO2
#define H_FOO2 1
int foo2(int *);
#endif



You don't need the parentheses around the expression in a return
statement. But, to use EXIT_FAILURE or EXIT_SUCCESS, you do need


No, a pointer value is passed. C is always pass-by-value. But a copy of a
pointer value is still a pointer value, and can still be used to access
the original object.


It will change the value of the object to which the pointer parameter
points, yes.


The copy of the pointer is destroyed, but so what?


If you use extern to qualify an object declaration, you are promising the
compiler that a definition exists at file scope, somewhere in the program.
It is up to you to ensure that this promise is kept. Whilst I decline to
be dogmatic about it, I would suggest that you avoid this feature wherever
possible, as file scope variables increase coupling (and maintenance time)
far in excess of the supposed benefits they bring in ease of writing.
Learn to see limited scope as a friend rather than an enemy.

Example of extern, using three files:

/* foo.h */
#ifndef H_FOO
#define H_FOO 1
extern int fsobj;
extern void foo(void);
#endif

/* foo.c */
#include "foo.h"

int fsobj = 42; /* initialised once only, at startup */

void foo(void)
{
fsobj = 6;

}

/* main.c */
#include <stdio.h>
#include "foo.h"

int main(void)
{
printf("Before: %d\n", fsobj);
foo();
printf("After: %d\n", fsobj);
return 0;

}

Sigh. I think my first post does not make any sense(was too tierd
last night) and its not what I really wanted to ask. Please refer to
the link list program that I just posted.
 
L

lector

Example of extern, using three files:

/* foo.h */
#ifndef H_FOO
#define H_FOO 1
extern int fsobj;
extern void foo(void);
#endif

/* foo.c */
#include "foo.h"

int fsobj = 42; /* initialised once only, at startup */

void foo(void)
{
fsobj = 6;

}

/* main.c */
#include <stdio.h>
#include "foo.h"

int main(void)
{
printf("Before: %d\n", fsobj);
foo();
printf("After: %d\n", fsobj);
return 0;

}

Wait. How did it print 42 first and then 6 ? Why is it that you can
only initialize an external variable outside the scope of a function ?
When I tried to comment the 'int fsobj = 42' bit and initialized
fsobj in foo() instead, I get an error.
 
D

Default User

lector wrote:

void create_link_list(node *root, int n)
{
node *p, *prev;
int i;

for(i=0; i<n; i++)
{
p = malloc(sizeof(node));
p->next = NULL;
printf("Enter data\n");
scanf("%d", &p->data);
if(root == NULL)
{
root = p;
prev = root;
}
else
{
prev->next = p;
prev = p;
}
}
}
The program compile successfuly and I could link all the obj files
without any errors or warnings. When I execute the
application(ll.exe), I can input all the numbers but the link list is
not printed. I think the problem lies in the fact that the link list
has been created but the copy of updated pointer to the root node is
not available as it got destroyed once the create routine terminated.

I didn't get destroyed, it got lost. See the FAQs:

<http://c-faq.com/ptrs/passptrinit.html>



Brian
 
L

lector

I didn't get destroyed, it got lost. See the FAQs:

<http://c-faq.com/ptrs/passptrinit.html>

Yeah, I read both 4.8 and 20.1. What happens is that you pass a copy
of pointer(which you want to change), the called function changes the
pointer value but then this changed value is lost after the function
is over. IF it was data that we wanted to modify, it would have worked
fine. So i guess it is better to treat the root pointer as 'data'
itself and pass a pointer to root pointer.
crete_link_list(**root, n);
print_link_list(**root, n);

This will mean even though the value of double pointer to root node is
lost, I still have the value of the root pointer
 
W

Willem

lector wrote:
) Yeah, I read both 4.8 and 20.1. What happens is that you pass a copy
) of pointer(which you want to change), the called function changes the
) pointer value but then this changed value is lost after the function
) is over. IF it was data that we wanted to modify, it would have worked
) fine. So i guess it is better to treat the root pointer as 'data'
) itself and pass a pointer to root pointer.
) create_link_list(**root, n);

Or you just return the new pointer:

node *create_link_list(n)

) print_link_list(**root, n);

Does print_link_list need to change the root pointer ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
L

lector

Or you just return the new pointer:

node *create_link_list(n)

One can do that but what if you can't malloc in create function
because of some error ? For that, it might be necessary to return an
int (EXIT_SUCCESS/EXIT_FAILURE) for checking.
) print_link_list(**root, n);

Does print_link_list need to change the root pointer ?

No, it only needs to print the list but even for that you need the
updated root pointer or else nothing is printed on the screen because
of root's null value.
 
W

Willem

lector wrote:
)
)> Or you just return the new pointer:
)>
)> node *create_link_list(n)
)
) One can do that but what if you can't malloc in create function
) because of some error ? For that, it might be necessary to return an
) int (EXIT_SUCCESS/EXIT_FAILURE) for checking.

How does malloc() return failure then ?

)> ) print_link_list(**root, n);
)>
)> Does print_link_list need to change the root pointer ?
)
) No, it only needs to print the list but even for that you need the
) updated root pointer or else nothing is printed on the screen because
) of root's null value.

And why is *root not 'the updated root pointer' ?


SaSW, Willem
--
Disclaimer: I am in no way responsible for any of the statements
made in the above text. For all I know I might be
drugged or something..
No I'm not paranoid. You all think I'm paranoid, don't you !
#EOT
 
K

Keith Thompson

lector said:
One can do that but what if you can't malloc in create function
because of some error ? For that, it might be necessary to return an
int (EXIT_SUCCESS/EXIT_FAILURE) for checking.

I advise against using EXIT_SUCCESS and EXIT_FAILURE as status codes
for functions other than main. It's not absolutely guaranteed that
they have distinct values (though I've never heard of a system where
they don't).

Many library functions return zero for success, non-zero for failure;
that's a reasonable convention to follow.
 
S

santosh

Keith said:
I advise against using EXIT_SUCCESS and EXIT_FAILURE as status codes
for functions other than main. It's not absolutely guaranteed that
they have distinct values (though I've never heard of a system where
they don't).

You mean that there may be implementations where EXIT_SUCCESS ==
EXIT_FAILURE? If so how will the environment distinguish between the
two?
 
R

Richard

santosh said:
You mean that there may be implementations where EXIT_SUCCESS ==
EXIT_FAILURE? If so how will the environment distinguish between the
two?

There would be more chance of a chip bit accidentally toggling then
them not being the same IMO.
 
S

santosh

pete said:
There is no requirement for the system
to be able to distinguish between the two.

void main (void)

I don't get it. From n1256 section 7.20 para 3:

+-----
| EXIT_FAILURE
| and
| EXIT_SUCCESS
|
| which expand to integer constant expressions that can be used as the
| argument to the exit function to return unsuccessful or successful
| termination status, respectively, to the host environment;
+-----

The above seems to be indicate pretty clearly that EXIT_FAILURE and
EXIT_SUCCESS return different termination statuses to the host. How
could this happen if the implementation could not distinguish between
them?

<snip>
 
D

Default User

santosh wrote:

The above seems to be indicate pretty clearly that EXIT_FAILURE and
EXIT_SUCCESS return different termination statuses to the host. How
could this happen if the implementation could not distinguish between
them?

What are you saying? If a host system doesn't have a way to distinguish
successful versus non-successful return, you can't have a C compiler?




Brian
 
S

santosh

Default said:
santosh wrote:



What are you saying? If a host system doesn't have a way to
distinguish successful versus non-successful return, you can't have a
C compiler?

As far as I can see EXIT_SUCCESS and EXIT_FAILURE merely return
successful termination status and unsuccessful termination status
respectively to the host environment. Whether the host is able to
distinguish between the two is not relevant to the C implementation.
What it can't do is to set EXIT_SUCCESS to be equal to EXIT_FAILURE.
They return different termination statuses and therefore must be
different.

That was what I was arguing in response to Keith Thompson's post
up-thread.
 
D

Default User

santosh said:
As far as I can see EXIT_SUCCESS and EXIT_FAILURE merely return
successful termination status and unsuccessful termination status
respectively to the host environment.

Which have to be values meaningful to the host.
Whether the host is able to
distinguish between the two is not relevant to the C implementation.
What it can't do is to set EXIT_SUCCESS to be equal to EXIT_FAILURE.
They return different termination statuses and therefore must be
different.

I'm not sure the Standard says they must be different. If the Standard
doesn't specify that they are required to be non-equal, and the host
system can't distinguish, then the as-if rule would seem to say that
they could be the same for some implementation.




Brian
 
C

Chris Torek

As far as I can see EXIT_SUCCESS and EXIT_FAILURE merely return
successful termination status and unsuccessful termination status
respectively to the host environment.
Right.

Whether the host is able to distinguish between the two is not
relevant to the C implementation.

Maybe. (I think this is correct, but I think one can at least
argue that it is not. This gets to be one of those philosophical
questions, like "if a tree falls in the forest and there is no one
around to observe it, does it make `a noise'", where the answer
hinges on the exact defintion of `noise'. If noise means "any
sound", then -- assuming we understand physics correctly -- it does
make sound and hence noise, but if it means "a sound that annoys
a person", then since there is no person being annoyed, it makes
no `noise'.)
What it can't do is to set EXIT_SUCCESS to be equal to EXIT_FAILURE.
They return different termination statuses and therefore must be
different.

But then we can appeal to the "as-if" rule and claim that, if the
user cannot tell whether they returned different statuses, the
compiler is allowed to have them return the same status, or even
no status at all. In which case, perhaps the compiler's freedom
to alter or remove the value returned from main() extends to further
freedom to "#define" both with the same value. In other words, if
the effect is not observable, the compiler can do whatever it likes:
we will not even be able to tell whether it has done anything.

There is another argument one can make, with clearer ground (less
appeal to philosophy). Consider the following C code fragment:

switch (f()) {
case EXIT_SUCCESS: ... code for success ... break;
case EXIT_FAILURE: ... code for failure ... break;
}

If EXIT_SUCCESS and EXIT_FAILURE are allowed, in some implementation,
to be "#define"d as the same value, this code will not compile
(because we are not allowed to have two "case"s with identical
constants). If they must be different, the code will compile.
The question then boils down to whether Standard C guarantees
that this code will compile, which *is* an observable effect.

Because I think that Standard C guarantees this code will compile,
I think that an implementation is not allowed to "#define" both as
the same constant, even on a host where the return value from main()
(or the value passed to exit() or _Exit()) is always discarded.
 
S

santosh

Default said:
Which have to be values meaningful to the host.

As I see it, this is outside the scope of the standard.
I'm not sure the Standard says they must be different. If the Standard
doesn't specify that they are required to be non-equal, and the host
system can't distinguish, then the as-if rule would seem to say that
they could be the same for some implementation.

The "as-if" rule really only makes sense if it, in some way, simplifies
things for the implementation or makes things more efficient. Strictly
speaking you may be right in your analysis, but I still say that making
EXIT_SUCCESS and EXIT_FAILURE the same is something only a DS9k would
do.

Also this can break code registered with atexit which might execute
different code depending on what termination status was passed to exit.
Again this might happen only in theory, but it's nevertheless another
point in favour of keeping EXIT_SUCCESS and EXIT_FAILURE distinct from
each other.
 
S

santosh

Chris said:
Maybe. (I think this is correct, but I think one can at least
argue that it is not. This gets to be one of those philosophical
questions, like "if a tree falls in the forest and there is no one
around to observe it, does it make `a noise'", where the answer
hinges on the exact defintion of `noise'. If noise means "any
sound", then -- assuming we understand physics correctly -- it does
make sound and hence noise, but if it means "a sound that annoys
a person", then since there is no person being annoyed, it makes
no `noise'.)


But then we can appeal to the "as-if" rule and claim that, if the
user cannot tell whether they returned different statuses, the
compiler is allowed to have them return the same status, or even
no status at all. In which case, perhaps the compiler's freedom
to alter or remove the value returned from main() extends to further
freedom to "#define" both with the same value. In other words, if
the effect is not observable, the compiler can do whatever it likes:
we will not even be able to tell whether it has done anything.

There is another argument one can make, with clearer ground (less
appeal to philosophy). Consider the following C code fragment:

switch (f()) {
case EXIT_SUCCESS: ... code for success ... break;
case EXIT_FAILURE: ... code for failure ... break;
}

If EXIT_SUCCESS and EXIT_FAILURE are allowed, in some implementation,
to be "#define"d as the same value, this code will not compile
(because we are not allowed to have two "case"s with identical
constants). If they must be different, the code will compile.
The question then boils down to whether Standard C guarantees
that this code will compile, which *is* an observable effect.

Because I think that Standard C guarantees this code will compile,
I think that an implementation is not allowed to "#define" both as
the same constant, even on a host where the return value from main()
(or the value passed to exit() or _Exit()) is always discarded.

An even stronger case (IMHO) for making EXIT_FAILURE and EXIT_SUCCESS
different might be the following code:

#include <stdlib.h>

int term_type;

void called_by_atexit(void) {
if (term_type == EXIT_SUCCESS) {
/* some code */
}
else if (term_type == EXIT_FAILURE) {
/* some other code */
}
else {
/* yet some other code */
}
return;
}

int main(void) {
atexit(called_by_atexit);
return(term_type = EXIT_FAILURE);
}

In called_by_atexit() the wrong block of code will be executed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top