learn:programming_c
Differences
This shows you the differences between two versions of the page.
| Both sides previous revisionPrevious revisionNext revision | Previous revision | ||
| learn:programming_c [2026/04/28 02:17] – removed - external edit (Unknown date) 127.0.0.1 | learn:programming_c [2026/06/18 00:36] (current) – [Managing a Project] azman | ||
|---|---|---|---|
| Line 1: | Line 1: | ||
| + | ====== Basic Programming in C ====== | ||
| + | |||
| + | This is mainly just to look back at basic C code structure - some of these are never taught in the basic programming course. The codes in this topic emphasize on C language standard - you should be able to compile and run the codes on any platform that has a C compiler. You just have to remember that some libraries only exists on specific platforms - so, make sure you know your target and development platforms. There are also some info on project management using makefiles. | ||
| + | |||
| + | ====== Development Environment ====== | ||
| + | |||
| + | If you really understood what you did in your introductory programming course, development on Linux platform is no different compared to using Windows platform. You obviously need a text editor to write your code, a C compiler to compile your code and a linker to create the executable. What you most probably have used is an Integrated Development Environment (IDE) which combines all of them into a single environment which is mainly the editor - the compiler and linker are just menu items or buttons somewhere within. | ||
| + | |||
| + | It is advisable to manage your source file in proper folder/path hierarchy. One thing about naming files and paths is NEVER use a whitespace character (' ') in them, no matter what Windows says about them not being a problem. | ||
| + | |||
| + | ===== Code Editing ===== | ||
| + | |||
| + | The source file is just a text file - so, you can actually use any text editor. On Windows platform, you can in fact use '' | ||
| + | |||
| + | On Linux, IDEs are also available but many veteran programmers simply use Linux text editors which naturally supports syntax highlighting. Among the popular editors are '' | ||
| + | |||
| + | ===== Compiling (and Linking) ===== | ||
| + | |||
| + | The instructions in this section require you to use the terminal. If you are using an IDE, just look for a menu item or button that says compile or build or make or something similar (they actually do the same thing as what is mentioned here). | ||
| + | |||
| + | If you have a single source file '' | ||
| + | |||
| + | Note that both compiling and linking can be done in this single command. They are actually separate processes and most of the time, it is very useful to execute them in separate stages especially when managing a software with multiple source files. | ||
| + | |||
| + | ===== Managing a Project ===== | ||
| + | |||
| + | If you are using a full-fledged IDE, you will find everything but the kitchen sink available (sometimes a sink can also be found :-D). One of the things that '' | ||
| + | |||
| + | Like other configuration files in Unix/Linux systems, writing a '' | ||
| + | |||
| + | //**Note**: This is based on GNU make utility. There are other variation(s) such as the BSD make.// | ||
| + | |||
| + | <file make makefile> | ||
| + | # makefile to compile a c program | ||
| + | single: single.c | ||
| + | gcc -o single single.c | ||
| + | </ | ||
| + | |||
| + | I will explain the syntax after the next example. Take note that there should be a single hard tab before the gcc command. The given example however is not very convenient because I have to change a lot of things (three words at least in the example) if I decided to change file or project name. The example below gives us a more generic '' | ||
| + | |||
| + | <file make makefile> | ||
| + | # makefile to compile a c program | ||
| + | PROJECT = single | ||
| + | SOURCE = $(PROJECT).c | ||
| + | CC = gcc | ||
| + | $(PROJECT): $(SOURCE) | ||
| + | $(CC) -o $(PROJECT) $(SOURCE) | ||
| + | </ | ||
| + | |||
| + | The two common things that we do in a makefile is to define build rules and to define variables. The lines that contains a ' | ||
| + | |||
| + | Imagine now that you have a hundred source files. Using the above rule, changing one source file will cause all the other source files to be recompiled again. This is not very efficient. Thus, if you remember you introductory lecture for computer programming, | ||
| + | |||
| + | <file make makefile> | ||
| + | # makefile to compile a c program | ||
| + | PROJECT = single | ||
| + | OBJECTS = $(PROJECT).o | ||
| + | CC = gcc | ||
| + | CFLAGS = | ||
| + | LDFLAGS = | ||
| + | $(PROJECT): $(OBJECTS) | ||
| + | $(CC) $(CFLAGS) -o $@ $+ $(LDFLAGS) | ||
| + | %.o: %.c | ||
| + | $(CC) $(CFLAGS) -c $< | ||
| + | </ | ||
| + | |||
| + | There are a few new things here. Special variables like $@, $+ and $< are now used. To know what they mean, you may refer to the note at the end of this section. The prerequisites are now object files that needs to be built as well. In order to build these, '' | ||
| + | |||
| + | One thing you should know is '' | ||
| + | |||
| + | The given information so far about makefiles should be sufficient for basic projects. You will learn, in time, of more advanced ways to specify rules that will show you how the '' | ||
| + | |||
| + | Some notes on special '' | ||
| + | |||
| + | <code make> | ||
| + | # $@ ==> target file | ||
| + | # $? ==> changed dependents | ||
| + | # $* ==> shared target/ | ||
| + | # $< ==> first dependent | ||
| + | # $^ ==> all dependents, duplicates omitted | ||
| + | # $+ ==> all dependents, order retained | ||
| + | </ | ||
| + | |||
| + | ====== Writing Programs in C ====== | ||
| + | |||
| + | All programs written in C must have a '' | ||
| + | |||
| + | The code in '' | ||
| + | |||
| + | It is sometimes very useful to be able to provide information (@input) to the program at command line. This can be made possible by declaring 2 parameters: <code c param.c> | ||
| + | # | ||
| + | int main(int argc, char *argv[]) | ||
| + | { | ||
| + | int loop; | ||
| + | printf(" | ||
| + | for(loop=0; | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | |||
| + | ====== Temporary Dumping Ground ====== | ||
| + | |||
| + | Some stuffs to share... | ||
| + | |||
| + | ===== Primitive Variable Size ===== | ||
| + | |||
| + | Variable in C - a simple C code to check C variable size. | ||
| + | <file c chksize.c> | ||
| + | # | ||
| + | # | ||
| + | |||
| + | int main(int argc, char** argv) | ||
| + | { | ||
| + | int loop; | ||
| + | if (argc<2) | ||
| + | { | ||
| + | printf(" | ||
| + | printf(" | ||
| + | printf(" | ||
| + | printf(" | ||
| + | printf(" | ||
| + | printf(" | ||
| + | printf(" | ||
| + | printf(" | ||
| + | } | ||
| + | for (loop=1; | ||
| + | { | ||
| + | if (!strcasecmp(argv[loop]," | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | else if (!strcasecmp(argv[loop]," | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | else if (!strcasecmp(argv[loop]," | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | else if (!strcasecmp(argv[loop]," | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | else if (!strcasecmp(argv[loop]," | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | else if (!strcasecmp(argv[loop]," | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | else if (!strcasecmp(argv[loop]," | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | else if (!strcasecmp(argv[loop]," | ||
| + | { | ||
| + | printf(" | ||
| + | } | ||
| + | } | ||
| + | return 0; | ||
| + | } | ||
| + | </ | ||
| + | Up-to-date version should always be available [[https:// | ||
| + | |||
| + | ===== Practical makefile ===== | ||
| + | |||
| + | This is what I use (extracted from [[https:// | ||
| + | |||
| + | <file make makefile> | ||
| + | # makefile for single source file app (my1codeapp) | ||
| + | |||
| + | ALLSRC = $(subst src/,, | ||
| + | ALLSRC += $(wildcard *.c) | ||
| + | ALLAPP = $(subst .c,, | ||
| + | |||
| + | TARGET ?= | ||
| + | OBJLST ?= | ||
| + | DOFLAG ?= | ||
| + | DOLINK ?= | ||
| + | |||
| + | CC = gcc | ||
| + | |||
| + | DELETE = rm -rf | ||
| + | |||
| + | CFLAGS += -Wall -Isrc | ||
| + | # i prefer to build static bin | ||
| + | #CFLAGS += -static | ||
| + | LFLAGS += $(LDFLAGS) | ||
| + | OFLAGS += | ||
| + | # when working with large files | ||
| + | #XFLAGS += -D_LARGEFILE_SOURCE=1 -D_FILE_OFFSET_BITS=64 | ||
| + | ifneq ($(DOFLAG), | ||
| + | CFLAGS += $(DOFLAG) | ||
| + | endif | ||
| + | ifneq ($(DOLINK), | ||
| + | LFLAGS += $(DOLINK) | ||
| + | endif | ||
| + | |||
| + | # i can still squeeze in some external code(s) => OBJLST! | ||
| + | EXTPATH = ../ | ||
| + | ifneq ($(wildcard $(EXTPATH)), | ||
| + | CFLAGS += -I$(EXTPATH) | ||
| + | endif | ||
| + | |||
| + | .PHONY: dummy all clean | ||
| + | |||
| + | # TARGET can be temporary code (reside at top level) | ||
| + | $(TARGET): $(OBJLST) $(TARGET).o | ||
| + | $(CC) $(CFLAGS) -o $@ $^ $(LFLAGS) $(OFLAGS) | ||
| + | |||
| + | dummy: | ||
| + | @echo "Run 'make < | ||
| + | @echo " | ||
| + | @echo | ||
| + | @echo "To set compiler flag (e.g. static), do 'make <app> DOFLAG=-static'" | ||
| + | @echo "To link a library (e.g. math), do 'make <app> DOLINK=-lm'" | ||
| + | |||
| + | all: $(ALLAPP) | ||
| + | |||
| + | %: src/%.c | ||
| + | $(CC) $(CFLAGS) -o $@ $< $(LFLAGS) $(OFLAGS) | ||
| + | |||
| + | %: %.c | ||
| + | $(CC) $(CFLAGS) -o $@ $< $(LFLAGS) $(OFLAGS) | ||
| + | |||
| + | # to compile those external code(s) => OBJLST! | ||
| + | %.o: $(EXTPATH)/ | ||
| + | $(CC) -c $(CFLAGS) -o $@ $< | ||
| + | |||
| + | clean: | ||
| + | -$(DELETE) $(ALLAPP) *.o | ||
| + | </ | ||
