Skip to main content
replaced http://programmers.stackexchange.com/ with https://softwareengineering.stackexchange.com/
Source Link

Is this the only way to do it? No; you could put all of the implementation from headers.c into headers.h instead, remove references to headers.c from the Makefile, and it would still work. But the convention when writing C code is to do it this way; if you're interested in the reasons, there are some discussions on other Stack Exchange sites that you could look up -- I'll start you off with this one: Why do we need to write a header file?Why do we need to write a header file?

Is this the only way to do it? No; you could put all of the implementation from headers.c into headers.h instead, remove references to headers.c from the Makefile, and it would still work. But the convention when writing C code is to do it this way; if you're interested in the reasons, there are some discussions on other Stack Exchange sites that you could look up -- I'll start you off with this one: Why do we need to write a header file?

Is this the only way to do it? No; you could put all of the implementation from headers.c into headers.h instead, remove references to headers.c from the Makefile, and it would still work. But the convention when writing C code is to do it this way; if you're interested in the reasons, there are some discussions on other Stack Exchange sites that you could look up -- I'll start you off with this one: Why do we need to write a header file?

added 1688 characters in body
Source Link
Air
  • 2.1k
  • 18
  • 29

If you take a lookLooking at the distribution code for find.c, you'll findwe can see this line near the top of the file:

#include "helpers.h"
#include "helpers.h"

This #include statement is different from the others in that it uses quotes ("") rather than angle brackets (<>). This is becauseThat header file, helpers.h is a header file written just for you, and it's located incontains only the same directory asprototypes for your find.csearch and -- unlikesort functions; the actual implementations are in stdiohelpers.hc, for example, which is located somewhere in a directory of standard library header files.

 1 So, that's how do we get from find.c knows where the header code is. If you moved the header file to another folder, you would need to specify the full path to headershelpers.hc insidewithout the line #include helpers.c directive instead of justsomewhere in the file name.mix?

As for compiling the header files,The answer is that it all happens automatically when you compilethanks to the find.cmake utility -- and more specifically, thanks to the Makefile that's included in the same folder; itfind directory. The Makefile contains instructions for make, as explained in the pset specs:

How the Makefile works is explained in a recommended reading from the beginning of the specs:

This makefile contains two types of lines. The lines appearing flush left are dependency lines. The lines preceded by a tab are executable lines, which can contain any valid UNIX command. A dependency line says that some file is dependent on some other set of files. For example, main.o: main.c util.h says that the file main.o is dependent on the files main.c and util.h. If either of these two files changes, the following executable line(s) should be executed to recreate main.o.

In other wordsour case, you don't havewhat links the internal implementation of the header file prototypes to find.c at compile time is that:

  1. The dependency line of our Makefile shows that find depends on helpers.c;
  2. The executable line that follows provides that same dependency as a command-line argument to the compiler, clang.

Why isn't there a helpers.h argument, if it's listed as a dependency? Because it's already there -- we included it in find.c explicitly;-- we just need to remind make is issuing allthat it's there, because make looks for changes in the appropriate commands todependencies before clang is executed and the compiler when#include directive is processed.

So why don't you executehave to make#include findhelpers.c, because that's how? The straight answer is that all you are required to provide in the distribution code was set upsource file, at a minimum, is prototypes for the functions you call. Notice you didn't #include <stdio.c> either, just a header (.h) file!

If you were to write some code from scratch using header files like thisAs far as find.c is concerned, the only functions you would also need are search and sort, which are prototyped in helpers.h. You don't really need to know something aboutthe details of how clangsearch or another compileris implemented in order to issue the proper commandscall it -- in fact, you could modify helpers.c all you wanted and/or write a as long as the prototypes in helpers.h didn't change, you wouldn't have to make any changes to find.c.

Is this the only way to do it? No; you could put all of the implementation from headers.c into headers.h instead, remove references to headers.c from the Makefile, and it would still work. But the convention when writing C code is to usedo it this way; if you're interested in the reasons, there are some discussions on other Stack Exchange sites that you could look up -- I'll start you off with your project.this one: Why do we need to write a header file?

If you take a look at the distribution code for find.c, you'll find this line near the top of the file:

#include "helpers.h"

This #include statement is different from the others in that it uses quotes ("") rather than angle brackets (<>). This is because helpers.h is a header file written just for you, and it's located in the same directory as find.c -- unlike stdio.h, for example, which is located somewhere in a directory of standard library header files.

  So, that's how find.c knows where the header code is. If you moved the header file to another folder, you would need to specify the full path to headers.h inside the #include directive instead of just the file name.

As for compiling the header files, that happens automatically when you compile find.c, thanks to the Makefile that's included in the same folder; it contains instructions for make, as explained in the pset specs:

In other words, you don't have to compile helpers.c explicitly; make is issuing all the appropriate commands to the compiler when you execute make find, because that's how the distribution code was set up for you.

If you were to write some code from scratch using header files like this, you would also need to know something about clang or another compiler in order to issue the proper commands and/or write a Makefile to use with your project.

Looking at the distribution code for find.c, we can see this line near the top of the file:

#include "helpers.h"

That header file, helpers.h, contains only the prototypes for your search and sort functions; the actual implementations are in helpers.c.1 So how do we get from find.c to helpers.c without the line #include helpers.c somewhere in the mix?

The answer is that it all happens thanks to the make utility -- and more specifically, the Makefile that's included in the find directory. The Makefile contains instructions for make, as explained in the pset specs:

How the Makefile works is explained in a recommended reading from the beginning of the specs:

This makefile contains two types of lines. The lines appearing flush left are dependency lines. The lines preceded by a tab are executable lines, which can contain any valid UNIX command. A dependency line says that some file is dependent on some other set of files. For example, main.o: main.c util.h says that the file main.o is dependent on the files main.c and util.h. If either of these two files changes, the following executable line(s) should be executed to recreate main.o.

In our case, what links the internal implementation of the header file prototypes to find.c at compile time is that:

  1. The dependency line of our Makefile shows that find depends on helpers.c;
  2. The executable line that follows provides that same dependency as a command-line argument to the compiler, clang.

Why isn't there a helpers.h argument, if it's listed as a dependency? Because it's already there -- we included it in find.c -- we just need to remind make that it's there, because make looks for changes in the dependencies before clang is executed and the #include directive is processed.

So why don't you have to #include helpers.c? The straight answer is that all you are required to provide in the source file, at a minimum, is prototypes for the functions you call. Notice you didn't #include <stdio.c> either, just a header (.h) file!

As far as find.c is concerned, the only functions you need are search and sort, which are prototyped in helpers.h. You don't really need to know the details of how search is implemented in order to call it -- in fact, you could modify helpers.c all you wanted and as long as the prototypes in helpers.h didn't change, you wouldn't have to make any changes to find.c.

Is this the only way to do it? No; you could put all of the implementation from headers.c into headers.h instead, remove references to headers.c from the Makefile, and it would still work. But the convention when writing C code is to do it this way; if you're interested in the reasons, there are some discussions on other Stack Exchange sites that you could look up -- I'll start you off with this one: Why do we need to write a header file?

Source Link
Air
  • 2.1k
  • 18
  • 29

If you take a look at the distribution code for find.c, you'll find this line near the top of the file:

#include "helpers.h"

This #include statement is different from the others in that it uses quotes ("") rather than angle brackets (<>). This is because helpers.h is a header file written just for you, and it's located in the same directory as find.c -- unlike stdio.h, for example, which is located somewhere in a directory of standard library header files.

So, that's how find.c knows where the header code is. If you moved the header file to another folder, you would need to specify the full path to headers.h inside the #include directive instead of just the file name.

As for compiling the header files, that happens automatically when you compile find.c, thanks to the Makefile that's included in the same folder; it contains instructions for make, as explained in the pset specs:

Notice further that you just compiled a program comprising not one but two .c files: helpers.c and find.c. How did make know what to do? Well, again, open up Makefile to see the man behind the curtain. The relevant lines appear below.

find: find.c helpers.c helpers.h
    clang -ggdb -std=c99 -Wall -Werror -o find find.c helpers.c -lcs50 -lm

Per the dependencies implied above (after the colon), any changes to find.c, helpers.c, or helpers.h will compel make to rebuild find the next time it’s invoked for this target.

In other words, you don't have to compile helpers.c explicitly; make is issuing all the appropriate commands to the compiler when you execute make find, because that's how the distribution code was set up for you.

If you were to write some code from scratch using header files like this, you would also need to know something about clang or another compiler in order to issue the proper commands and/or write a Makefile to use with your project.