0

Suppose I want only one (or a few) function from a certain header but it's a function I can define with the same efficiency as the library's implementation. Should I include a library header or implement my own function? Which is better?

I'm learning my first language C and I'm loving it.

EDIT:

Most of you didn't get the question. Forget about portability, and if it makes you happy "assume" that I can make a function with exactly the same efficiency. Or let's just say I've got the same implementation somehow.

I read somewhere that

The #include directive tells the preprocessor to open a specified file and insert its contents into the current file.

The header like <stdlib.h> consists of many things so I wonder whether inserting all it's content to the file, or inserting a custom header with just what I want, which is more efficient in terms of speed or memory or program size?

  • 2
    include the header - the header author may change something in the header file that might cause all sorts of isssues for your code – pm100 Apr 11 '22 at 18:57
  • 1
    Looks like you are not asking about the header, but about re-implementing library functions. That would depend. – Eugene Sh. Apr 11 '22 at 19:03
  • If you're `re-writing` some simple library functions for learning, then avoid conflicting names; say prefix all your functions with `my_`. Now, include library headers as necessary to compile your code. – जलजनक Apr 11 '22 at 19:10
  • @SupportUkraine: A function I write with the same efficiency as a library routine would give me portability (no dependence on a binary for the library), freedom from potential licensing or cost issues, better documentation, and likely better quality code. – Eric Postpischil Apr 11 '22 at 20:32
  • Note the C standard explicitly says ([§7.1.4 Use of library functions ¶2](http://port70.net/~nsz/c/c11/n1570.html#7.1.4p2)): _Provided that a library function can be declared without reference to any type defined in a header, it is also permissible to declare the function and use it without including its associated header._. What you're thinking is allowed (with caveats) but ill-advised. Use the header. – Jonathan Leffler Apr 11 '22 at 21:10
  • @JonathanLeffler and others, Would you please read the edited question. – Abdidier Dribbler Apr 11 '22 at 22:41
  • 1
    You're worrying about micro-optimizations. Don't! Unless your chip speed is measured in double-digits of megahertz or less, you are wasting your time in order to save minuscule amounts of computer time. Don't! Include the headers. If you get to 50 headers in a module, then you might start worrying — perhaps. You're not there yet. And if the headers are written correctly, you still won't beat including them. Using the header protects you against changes in the header. There's little more frustrating than finding the header was not included, the function was changed, but you didn't know! – Jonathan Leffler Apr 11 '22 at 22:45
  • Generally speaking, the header only declares the function and supporting information needed to call the function. The implementation is in a library that is linked separately. You use the header for the declarations so you can call the functions — their implementation is in the library that is loaded while linking and executing your program. You don't get a copy of the functions in your code — there's a library that supplies the function when you link the program. So, including `` makes a variety of functions available for calling, but doesn't add any of them to your object file. – Jonathan Leffler Apr 11 '22 at 22:57
  • @JonathanLeffler In real production I would never waste my time writing something that's been written, I learned that. I'm just wondering which of those is better and why? Assumming that the header is just as inaccessible for editing as the library header, so that the same protection is guaranteed. – Abdidier Dribbler Apr 11 '22 at 23:00
  • Practice what you'd do in "real production". I think I've made it clear: ***Use the header!*** I'm not sure how to be clearer — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** — ***Use the header!*** – Jonathan Leffler Apr 11 '22 at 23:03
  • @JonathanLeffler That's not a proper advice. Maybe the question is hard? – Abdidier Dribbler Apr 11 '22 at 23:06
  • Then I don't understand what you're asking. You don't reimplement what's in the library unless it is defective. You use the library, and to use the library, you use the header. The header contains the declarations of the functions; the library contains the implementations of the functions. If it is the standard C library code, or the POSIX library code, or the O/S extra functions, you're going to get a shared library loaded at runtime. If you use static linking, the functions are linked into your executable. Either way, you don't worry about it — not while you're learning, nor later. – Jonathan Leffler Apr 11 '22 at 23:12
  • 1
    You are worrying about micro-optimizations. You should not worry about micro-optimizations yet. Not for a long time. OK — I've said what I can. You can continue to ignore me; that's your prerogative. I'm not going to give you the answer you seem to want because I don't think it's the right answer. Bye! – Jonathan Leffler Apr 11 '22 at 23:13
  • @JonathanLeffler Yeah, you probably didn't get the question. I'll try to edit again. – Abdidier Dribbler Apr 12 '22 at 01:00
  • @JonathanLeffler I'm not in a position to ignore someone. I'm just trying to get something I want, an answer. It's wrong to assume that the answer I want will not be helpful in my learning. I want to know as much as I can. – Abdidier Dribbler Apr 12 '22 at 01:05
  • You seem to want an answer to the effect that "Don't include the header because of all the junk in it that will make your program bigger than necessary". That's not a correct answer because including a header does not make your program bigger than necessary. A header only includes declarations — not definitions. Declarations don't take up space. Definitions do. At runtime, if your system uses shared libraries, the whole shared library will be memory, but all the processes will be using so there's a net win on memory space. Static linking alters the space equation. _[…continued…]_ – Jonathan Leffler Apr 12 '22 at 01:13
  • _[…continuation…]_ A statically-linked program will contain the functions it uses, and the functions those functions use, but won't contain anything that it doesn't need. That will all be separate from the code used by any other program, so if you have multiple statically-linked programs running, each program will have its own image in memory, including its own copy of any library functions. If you have your own implementations of any functions linked into your program, those will occupy separate memory per program because they are statically linked. _[…continued 2…]_ – Jonathan Leffler Apr 12 '22 at 01:16
  • _[…continuation 2]… And, if your program uses any shared libraries, those will still be loaded on the system, so there'll be overhead for the functions in the shared libraries that you're not using. It's not a question of portability; it's not a question of runtime efficiency of your replacement functions. It's a question of sanity and basic good software engineering. You don't re-create code with a very good reason. – Jonathan Leffler Apr 12 '22 at 01:18
  • @JonathanLeffler Just what I wanted to know. Only if you could Answer officially so that others could benefit. Thanks ALOT. – Abdidier Dribbler Apr 12 '22 at 01:20
  • Gimme some time. I'll transfer an edited version of my comments into an answer. – Jonathan Leffler Apr 12 '22 at 01:22

4 Answers4

1

and welcome to Stack Overflow. First let me say that what you are asking about generally doesn't happen. Libraries are generally created to prevent re-writing large amounts of code. However, if it did happen, the first thing to consider is portability.

While it's not entirely accurate, we can make the assumption that deployed software is more likely to be maintained than the program you wrote. If a change needs to be made with that software, you will end up pulling in that change after updating your system and re-compiling.

If on the other hand, if you determine, that even if something changed, you wouldn't want it to, then by all means implement it yourself. Assuming your code is as efficient as the library, there isn't going to be a performance difference.

mreff555
  • 1,049
  • 1
  • 11
  • 21
1

I think that as you're learning, you should do the following two things, in order:

  1. Implement and test your home-grown function
  2. See how the library function differs from your implementation

Library functions are not always the "best" solution: They're the best in general, not necessarily the most efficient.

Although I rely on libraries almost exclusively in my work, I started, as many programmers do, with a lot of home-grown (and buggy) equivalents to standard library functions. Writing that code has helped me become a better programmer.

Josh Greifer
  • 3,151
  • 24
  • 25
1

Transferring an edited version of selected comments (mostly mine) into an answer.

Include the header - the header author may change something in the header file that might cause all sorts of isssues for your code. pm100

Note the C standard explicitly says (§7.1.4 Use of library functions ¶2):

Provided that a library function can be declared without reference to any type defined in a header, it is also permissible to declare the function and use it without including its associated header.

What you're thinking of doing is allowed (with caveats), but doing so is ill-advised. Use the header.

You're worrying about micro-optimizations. Don't! Unless the chip speed on the computer where you do the compiling is measured in double-digits of megahertz or less, you are wasting your time in order to save minuscule amounts of computer time.

  • Include the headers. Include the standard headers.

If you get to 50 headers in a module, then perhaps you might start worrying. You're not there yet. And if the headers are written correctly, you still won't beat including them. Using the header protects you against changes in the declarations in the header. There's little more frustrating than finding that a header was not included but some declarations were written out longhand, and then the function was changed in the header, but you didn't know because you didn't use the header. This is a double-maintenance nightmare — or worse than a double-maintenance nightmare if you have the old version of the function declarations in more than one file.

Generally speaking, the header only declares the function and supporting information needed to call the function (types, macros). The implementation of the function is in a library that is linked separately. You use the header for the declarations so you can call the functions — their implementation is in the library that is loaded while linking and executing your program. You don't get a copy of the functions in your code — there's a library that supplies the function when you link the program. So, including <stdlib.h> makes a wide variety of functions available for calling, but doesn't add any of them to your object file.

You don't reimplement what's in the library unless it is defective. You use the library, and to use the library, you use the header. The header contains the declarations of the functions; the library contains the implementations of the functions. If it is the standard C library code, or the POSIX library code, or the O/S extra functions, you're going to get a shared library loaded at runtime. If you use static linking, the functions are linked into your executable. Either way, you don't worry about it — not while you're learning, nor later usually.

You are worrying about micro-optimizations. You should not worry about micro-optimizations yet. Not for a long time.

You seem to want an answer to the effect that "Don't include the header because of all the junk in it that will make your program bigger than necessary". That's not a correct answer because including a header does not make your program bigger than necessary.

  • A header only includes declarations — not definitions.
  • Declarations don't take up space in your executable (though they take up some space in the compiler).
  • Definitions do take space in your executable.

If your system uses shared libraries at runtime, the whole shared library will be in memory. However, all the processes that use the same shared library will be using the same memory for the code (but each will have its own copy of any modifiable data), so there's a net win on memory space.

Static linking alters the space equation. A statically-linked program will contain the functions it uses, and the functions those functions use, but won't contain anything that it doesn't need. That will all be separate from the code used by any other program, so if you have multiple statically-linked programs running, each program will have its own image in memory, including its own copy of any library functions. If you have your own implementations of any functions linked into your program, those will occupy separate memory per program because they are statically linked.

And, if your program uses any shared libraries, those will still be loaded on the system, so there'll be overhead for the functions in the shared libraries that you're not using.

It's not a question of portability; it's not a question of the runtime efficiency of your replacement functions. It's a question of sanity and basic good software engineering. You don't re-create code with a very good reason. And (the key point), including a header doesn't make your program grow.

(NB: C++ does have 'header-only' libraries with templates — the Boost libraries are a primary example. Including such headers means that the functions called by your code may be instantiated using the information from the header. The linker normally manages to avoid too much overhead by eliminating duplicate copies of instantiated functions. So, you still don't have to worry much about program growth because of including headers. Header-only libraries are rare in C.)

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
-1

Yes, use the already written, and presumably much better tested version.

I can define with the same efficiency as the library's implementation

You are mistaking. I don't care if you're Kernighan or Ritchie or whoever, you will not write code even half as optimized as your compiler's standard library. You will have bugs you need to fix and as such you will never be able to trust your standard library when something crashes, so you'll always have to debug it as well.

Blindy
  • 65,249
  • 10
  • 91
  • 131