Learning C, Trying to Understand & (unary op)

T

Tom

Hello,

I've recently started trying to learn C (for the fun of it!). I have
been using Perl and other languages for many years, but they were
always very high level, this is giving me quite a ride. Here is my
situation:

I have the following code:

////////////////////////////////////////////////////////////
#include <linux/kernel.h>
int main()
{
struct sysinfo s;
sysinfo(&s);

printf("Server uptime: %i days.", s.uptime/60/60/24);
return 0;
}
////////////////////////////////////////////////////////////

This works fine and provides the uptime of a server. However, I'm
trying to understand exactly what it is doing. Here is where my
understanding gets fuzzy:

1) Assign "s" as an instance to the sysinfo structure.
2) ???
3) Print and calculate server uptime.

What is "sysinfo(%s);" actually doing? My limited understanding is
that it is running the sysinfo system call against the address of the
"s" variable. So, "s" is a new instance of the sysinfo structure and
then the address of that new instance is processed by the sysinfo
system call?

I'm just trying to get this concept through my thick head. Any
enlightenment would be appreciated! Thanks.

Tom
 
P

pemo

&s evaluates to the memory address of s - that address is passed to the
function; to effect a pass-by-reference call. C only has pass by value -
but here that value can be used to access s within the called function via
the dereference operator *.
 
S

Simon Morgan

comp.unix.programmer is that way --->

Only ANSI/ISO C is spoken here. System-specific extensions are
discussed elsewhere.

Try actually reading his post before jumping on your high horse, his
question had nothing to do with anything system-specific.
 
S

SM Ryan

# ////////////////////////////////////////////////////////////
# #include <linux/kernel.h>
# int main()
# {
# struct sysinfo s;
# sysinfo(&s);
#
# printf("Server uptime: %i days.", s.uptime/60/60/24);
# return 0;
# }
# ////////////////////////////////////////////////////////////
#
# This works fine and provides the uptime of a server. However, I'm
# trying to understand exactly what it is doing. Here is where my
# understanding gets fuzzy:
#
# 1) Assign "s" as an instance to the sysinfo structure.

'Assign' means something else in C. The variable is declared. It will
be allocated space in the compiled code.

# 2) ???

Passes a pointer to the allocated space to the function sysinfo.
Presumably it is storing into the space pointed to by the
passed pointer.

Originally C functions could not return structs, so you would
have to allocate space for struct and then pass a pointer to
a function to fill in the space. C now allows structs to be
returned, but the old interfaces persist.

# What is "sysinfo(%s);" actually doing? My limited understanding is
# that it is running the sysinfo system call against the address of the
# "s" variable. So, "s" is a new instance of the sysinfo structure and
# then the address of that new instance is processed by the sysinfo
# system call?

A new instance of s is created automatically as the main
function is enterred. s refers to this same instance throughout
that function invocation.

C does not hide memory allocation; and the usual C library
does not hide deallocation. The programmer has to handle these
issues.
 
E

Emmanuel Delahaye

Tom wrote on 23/09/05 :
I've recently started trying to learn C (for the fun of it!). <...>

I have the following code:

////////////////////////////////////////////////////////////
#include <linux/kernel.h>

Wait a minute. You claim to be an absolute beginner in C and you want
to play with the Linux kernel ? Don't you think that you are a little
green for that ?
int main()
{
struct sysinfo s;
sysinfo(&s);

printf("Server uptime: %i days.", s.uptime/60/60/24);

Huh, more that green. If you are writing a Linux daemon of a module
(main() in a module ?), you want printk() here, but it is absolutely
off-topic on c.l.c.

Please stick to standard C.

- it's on-topic here
- it's a good way to learn C (whatever the system you are using).
- it will prevent you to do things you are not allowed to do on a
managed system like wIndows NT/XP or Linux.

--
Emmanuel
The C-FAQ: http://www.eskimo.com/~scs/C-faq/faq.html
The C-library: http://www.dinkumware.com/refxc.html

..sig under repair
 
J

John Bode

Emmanuel said:
Tom wrote on 23/09/05 :

Wait a minute. You claim to be an absolute beginner in C and you want
to play with the Linux kernel ? Don't you think that you are a little
green for that ?


Huh, more that green. If you are writing a Linux daemon of a module
(main() in a module ?), you want printk() here, but it is absolutely
off-topic on c.l.c.

Please stick to standard C.

- it's on-topic here
- it's a good way to learn C (whatever the system you are using).
- it will prevent you to do things you are not allowed to do on a
managed system like wIndows NT/XP or Linux.

His actual question (which you snipped) is topical.
 
K

Kenneth Brody

Emmanuel said:
Tom wrote on 23/09/05 :

Wait a minute. You claim to be an absolute beginner in C and you want
to play with the Linux kernel ? Don't you think that you are a little
green for that ?

I see nothing in his post that he's doing anything like playing with
the kernel. He's simply including a system-specific header file
named "linux/kernel.h". (And the header file is not really related
to his question, beyond including a complete compilable [on Linux]
example of his question.)
Huh, more that green. If you are writing a Linux daemon of a module
(main() in a module ?), you want printk() here, but it is absolutely
off-topic on c.l.c.

I saw no indication anywhere in his post that he was writing anything
related to a kernel module. Rather, this is a 3-line program which
prints some information obtained via a system-specific "sysinfo()"
function call.
Please stick to standard C.

- it's on-topic here
- it's a good way to learn C (whatever the system you are using).
- it will prevent you to do things you are not allowed to do on a
managed system like wIndows NT/XP or Linux.

His actual question (what does "&s" as a parameter mean?) was on
topic. It was simply wrapped in non-portable example code.

--
+-------------------------+--------------------+-----------------------------+
| Kenneth J. Brody | www.hvcomputer.com | |
| kenbrody/at\spamcop.net | www.fptech.com | #include <std_disclaimer.h> |
+-------------------------+--------------------+-----------------------------+
Don't e-mail me at: <mailto:[email protected]>
 
J

John Bode

Tom wrote:
[snip]
What is "sysinfo(%s);"
sysinfo(&s)

actually doing?

The sysinfo function is modifying the contents of the s variable.

The expression &s evaluates to the address of s. C passes all function
parameters by value, so when a function writes to a parameter, that
change is not reflected in the calling function. For example, the
following code doesn't work as intended:

void swap(int x, int y)
{
int tmp;
tmp = x;
x = y;
y = tmp;
}

int main(void)
{
int foo = 1, bar = 10;
swap(foo, bar);
printf("foo = %d, bar = %d\n", foo, bar);
return 0;
}

The formal parameters x and y are different objects from foo and bar;
they occupy different memory addresses. The values of foo and bar are
copied into x and y respectively when swap is called, but the new
values of x and y are not written back to foo and bar when swap
returns.

In order to get around this, we use pointers to pass the addresses of
foo and bar to swap, which swap dereferences:

void swap (int *x, int *y)
{
int tmp;
tmp = *x;
*x = *y;
*y = tmp;
}

int main(void)
{
int foo = 1, bar = 10;
swap(&foo, &bar);
printf("foo = %d, bar = %d\n", foo, bar);
return 0;
}

x and y are still distinct variables with their own addresses in
memory, but instead of copying the values of foo and bar to them, we're
copying the *addresses* of foo and bar to them.

The declaration

int *x;

specifies that x is a pointer to int; that is, that the value of x is
the address of an object of int type in memory. The statement

*x = *y;

takes the value of the object pointed to by y (bar) and assigns it to
the object pointed to by x (foo).
 
K

Keith Thompson

Emmanuel Delahaye said:
Tom wrote on 23/09/05 :

Wait a minute. You claim to be an absolute beginner in C and you want
to play with the Linux kernel ? Don't you think that you are a little
green for that ?

You see, this is why we try to discourage off-topic answers as well as
off-topic questions. He's not really playing with the kernel; he's
just using the wrong header file. "man sysinfo" will tell you the
proper header file to use for the sysinfo() function and the type
"struct sysinfo". It's a perfectly appropriate thing for a beginner
to play with, as long as he realizes that it's Linux-specific.
("linux/kernel.h" may happen to work; the reasons for that are
entirely off-topic here.)

Here's the original program again:

#include <linux/kernel.h>
int main()
{
struct sysinfo s;
sysinfo(&s);

printf("Server uptime: %i days.", s.uptime/60/60/24);
return 0;
}

This does raise several points beyond the non-portability of sysinfo
and the use of the wrong header file.

1. Since you use printf(), you need a "#include <stdio.h>".

2. "int main()" is acceptable, but "int main(void)" is better because
it's more explicit.

3. There's no newline at the end of the program's output. It's
implementation-dependent whether one is required. <OT>On Linux,
the result is lkely to be that your output is immediately followed
by your prompt, making it difficult to read.</OT>

4. The "%i" format ("%d" is more common) is valid only if s.uptime is
of type int (or of a type that promotes to int). <OT>It isn't.</OT>
 

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

Forum statistics

Threads
474,169
Messages
2,570,920
Members
47,462
Latest member
ChanaLipsc

Latest Threads

Top