Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do many C functions use pointers to pass on data instead of using "return"? [closed]

Tags:

c

function

This is more or less a question about methodology and rationale than anything. In programming various kernel modules for Linux, I'm confounded by what I consider to be a clunky way of designing functions. For example, to retrieve the inode of a file given its path, I had to use something like:

struct inode *inode;
struct path path;
kern_path(path_name, LOOKUP_FOLLOW, &path);
inode = path.dentry->d_inode;

Why not just a function that works like:

struct inode inode;
struct path path = kern_path(path_name, LOOKUP_FOLLOW);
inode = path.dentry->d_inode;

Seems much more intuitive.

like image 661
Melab Avatar asked Jul 02 '15 19:07

Melab


3 Answers

And what would you do with the int that kern_path returns?

It's important for functions to be able to return some kind of error code so the user can ensure the function succeeded. There are two obvious options:

  1. Return the error code.

    This means you must take the other value that you'd like to return as a parameter.

  2. Return the value.

    This means you must take the error code as a parameter.

Since you can only return 1 value in C, you've got to take something as a parameter, as ultimately you want to return two things to the user (the error code and the value).

like image 82
Cornstalks Avatar answered Nov 11 '22 13:11

Cornstalks


The kernel is a C program with special constraints. In particular, the call stack is not allowed to be deep (IIRC, it is limited to 4Kbytes).

When you return a struct, the ABI (see the x86-64 ABI ...) mandates that (except for some short struct fitting in two words) the returned struct goes thru the stack. So such a style would favor quite big stack frames, hence would more easily meet the stack limit.

BTW, the usual style would be to return some integer error code, and modify the data pointed by argument pointers.

On x86-64/Linux returning a structure of two scalar values (integers, pointers, enums, doubles, ....) is definitely worth it, see this.

like image 42
Basile Starynkevitch Avatar answered Nov 11 '22 14:11

Basile Starynkevitch


That has a benefit of reducing copying memory blocks back and forth.

Using this methodology allows the invoked function to only modify certain parts of the passed in struct and no memory is being copied at all.

like image 2
Amit Avatar answered Nov 11 '22 13:11

Amit