Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
becki:linux:c [2010-06-08 08:06] becki |
becki:linux:c [2017-12-07 14:19] (aktuell) becki [Definition of constant Strings] |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
====== C Tips == | ====== C Tips == | ||
- | ===== Loops == | ||
- | ==== Loops and break == | ||
- | <code c> | + | This is about ISO C and its standard library. POSIX/Linux enhancements and features are described in [[:becki:my:linux:linux programming]]. How to build applications is described in [[build tools]]. |
- | int i= 0; | + | |
- | while (i<MAX) { | + | |
- | if ( someThingHappend() ) break; | + | |
- | else { doSomething(); i++; } | + | |
- | } | + | |
- | </code> | + | |
- | is the same as: | + | |
- | <code c> | + | |
- | int i; | + | |
- | for (i=0; i<MAX; i++) { | + | |
- | if ( someThingHappend() ) break; | + | |
- | else doSomething(); | + | |
- | } | + | |
- | </code> | + | |
- | + | ||
- | ==== While and For == | + | |
- | + | ||
- | <code c> | + | |
- | for (expr1; expr2; expr3) | + | |
- | statement | + | |
- | </code> | + | |
- | ist according to "The C programming language" p.59 the same as: | + | |
- | <code c> | + | |
- | expr1; | + | |
- | while (expr2) { | + | |
- | statement | + | |
- | expr3 //expr3 comes after statement | + | |
- | } | + | |
- | </code> | + | |
===== CLI args and main() == | ===== CLI args and main() == | ||
Zeile 46: | Zeile 15: | ||
// don't omit void! (Carm p.278) | // don't omit void! (Carm p.278) | ||
</code> | </code> | ||
+ | |||
+ | ===== C Program Structure == | ||
+ | |||
+ | {{page>becki/my/linux/design_blog/2017-01-20_c_program_structure&noheader}} | ||
===== Position of Pointer Sign ====== | ===== Position of Pointer Sign ====== | ||
+ | |||
Some investigations: | Some investigations: | ||
<code c> | <code c> | ||
Zeile 66: | Zeile 40: | ||
- it seems to be more common | - it seems to be more common | ||
- declarations like "int a, *ap;" are possible | - declarations like "int a, *ap;" are possible | ||
+ | |||
+ | ===== Loops == | ||
+ | ==== Loops and break == | ||
+ | |||
+ | <code c> | ||
+ | int i= 0; | ||
+ | while (i<MAX) { | ||
+ | if ( someThingHappend() ) break; | ||
+ | else { doSomething(); i++; } | ||
+ | } | ||
+ | </code> | ||
+ | is the same as: | ||
+ | <code c> | ||
+ | int i; | ||
+ | for (i=0; i<MAX; i++) { | ||
+ | if ( someThingHappend() ) break; | ||
+ | else doSomething(); | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | ==== While and For == | ||
+ | |||
+ | <code c> | ||
+ | for (expr1; expr2; expr3) | ||
+ | statement | ||
+ | </code> | ||
+ | |||
+ | is the same as((The C programming language p.59)): | ||
+ | |||
+ | <code c> | ||
+ | expr1; | ||
+ | while (expr2) { | ||
+ | statement | ||
+ | expr3 //expr3 comes after statement | ||
+ | } | ||
+ | </code> | ||
===== Standard In- and Output == | ===== Standard In- and Output == | ||
Zeile 71: | Zeile 81: | ||
<code c> | <code c> | ||
+ | /* Read a character from stdin: */ | ||
+ | int i= getchar(); | ||
+ | </code> | ||
+ | |||
+ | <code c> | ||
+ | /* Read stdin line by line into the array lin: */ | ||
char lin[MAX_LINE_LEN]; | char lin[MAX_LINE_LEN]; | ||
while (fgets(lin, MAX_LINE_LEN, stdin)) {/* do some thing */} | while (fgets(lin, MAX_LINE_LEN, stdin)) {/* do some thing */} | ||
- | /* Reads stdin line by line into the array lin */ | ||
</code> | </code> | ||
+ | |||
+ | <note tip>If input line lenght is unknown, use ''getline()'' instead of ''fgets()''! | ||
+ | (See ''freesigs/io_modbus'')</note> | ||
+ | |||
+ | ''scanf'' can also be used for reading from ''stdin''. | ||
==== stdout, stderr == | ==== stdout, stderr == | ||
<code c> | <code c> | ||
- | printf("%s=%u\n", key, value); // writing to stdout | + | /* Write a character to stdout and stderr: */ |
- | fprintf(stderr, "%s=%u\n", key, value); // writing to stderr | + | int i= 'c'; |
+ | putchar(i); | ||
+ | putc(i, stderr): | ||
</code> | </code> | ||
- | ==== Colorizing stdout == | ||
- | |||
- | Just an example: | ||
<code c> | <code c> | ||
- | printf("\033[32mgreen text\033[0m"); | + | /* Write a line to stdout and stderr: */ |
- | printf("\033[1;31mbold red text\033[0m"); | + | printf("%s=%u\n", key, value); // writing to stdout (buffered) |
+ | fprintf(stderr, "%s=%u\n", key, value); // writing to stderr (unbuffered) | ||
</code> | </code> | ||
- | See ''color_indicator[]'' in sourcecode of ''ls'', [[http://ldp.bootet.net/LDP/abs/html/colorizing.html|ABS Guide]] and C&R S.38 | + | |
+ | Writing to ''stderr'' is unbuffered, writing to ''stdout'' is buffered ((CARM p.351)) | ||
+ | ⇒ Always use ''stderr'' for debugging messages ((RRUSP p.68)) | ||
===== Constants ====== | ===== Constants ====== | ||
Zeile 199: | Zeile 221: | ||
[static] const char *mystring= "String" // false, needs 6 Bytes + Pointer | [static] const char *mystring= "String" // false, needs 6 Bytes + Pointer | ||
</code> | </code> | ||
+ | |||
* ''static'' to limit the scope for global strings. Not necessary inside a code block. | * ''static'' to limit the scope for global strings. Not necessary inside a code block. | ||
* see also [[http://www.dclc-faq.de/kap2.htm|de.comp.lang.c FAQ]] -> Frage 2.2 / K&R p.101 / Carm p.124 | * see also [[http://www.dclc-faq.de/kap2.htm|de.comp.lang.c FAQ]] -> Frage 2.2 / K&R p.101 / Carm p.124 | ||
+ | * //Writable// strings must be declared as array (eg ''char a[]= "aff";'') not as pointer. See Carm p 32 | ||
=== Detailed Description == | === Detailed Description == | ||
Zeile 357: | Zeile 381: | ||
- Always use ''int'' (also when int is way too big or the value will never be never negative, eg. counter variable in for loops), unless one or more of the following exceptions apply: | - Always use ''int'' (also when int is way too big or the value will never be never negative, eg. counter variable in for loops), unless one or more of the following exceptions apply: | ||
- | - FIXME Test this: Use ''unsigned int'' as parameter type in function declarations when [[http://www.dclc-faq.de/kap10.htm|only positive values are allowed]]. This saves you from the overhead of testing for nonnegative values. | + | - Use ''unsigned int'' when [[http://www.dclc-faq.de/kap10.htm|only positive values are allowed]]. This saves you from the overhead of testing for negative values in function arguments and returned values from functions. |
- Use ''unsigned'' types when bit operations are performed (unsigned types with proper size recommended) | - Use ''unsigned'' types when bit operations are performed (unsigned types with proper size recommended) | ||
- Use another, smaller type when space is relevant (eg in ''struct'' definitions or large arrays) | - Use another, smaller type when space is relevant (eg in ''struct'' definitions or large arrays) | ||
- Use a bigger type when the space in ''int'' is not sufficient | - Use a bigger type when the space in ''int'' is not sufficient | ||
+ | |||
+ | ===== Private Members in structs == | ||
+ | |||
+ | Any pointer type may be an incomplete type. This can be used to get private members in an object: | ||
+ | |||
+ | ==== Library Code == | ||
+ | |||
+ | <code c> | ||
+ | /* file: point-private.h */ | ||
+ | |||
+ | struct point { | ||
+ | int x; | ||
+ | int y; | ||
+ | }; | ||
+ | </code> | ||
+ | |||
+ | <code c> | ||
+ | /* file: point.c */ | ||
+ | #include <stdlib.h> | ||
+ | #include "point-private.h" | ||
+ | |||
+ | struct point * point_new(int x, int y) { | ||
+ | struct point *p= malloc(sizeof(struct point)); | ||
+ | p->x= x; | ||
+ | p->y= y; | ||
+ | return p; | ||
+ | } | ||
+ | |||
+ | int point_get_x(struct point *this) { | ||
+ | return this->x; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | <code c> | ||
+ | /* file: point.h */ | ||
+ | |||
+ | struct point * point_new(int x, int y); | ||
+ | |||
+ | int point_get_x(struct point *this); | ||
+ | </code> | ||
+ | |||
+ | ==== Client Code == | ||
+ | |||
+ | <code c> | ||
+ | #include <stdio.h> | ||
+ | #include "point.h" | ||
+ | |||
+ | int main(void) { | ||
+ | struct point *p = point_new(7,4); | ||
+ | |||
+ | printf("x=%d\n", point_get_x(p)); | ||
+ | //printf("x=%d\n", p->x); // Error: incomplete type | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
===== Unsorted Tips == | ===== Unsorted Tips == | ||
Zeile 366: | Zeile 446: | ||
* Use ''stdint.h''. It offers exact length types; smallest types of at least given length and most efficient types | * Use ''stdint.h''. It offers exact length types; smallest types of at least given length and most efficient types | ||
* Use ''limits.h'' to get the ranges of integer types ((CARM p.112)) | * Use ''limits.h'' to get the ranges of integer types ((CARM p.112)) | ||
- | * [[http://library.gnome.org/devel/glib/stable/|Glib]] is to C what the STL is for C++ or the Platform API for Java. IBM has an [[http://www.ibm.com/developerworks/linux/library/l-glib.html|intro]] | + | * [[http://library.gnome.org/devel/glib/stable/|Glib]] is to C what the STL is for C++ or the Platform API for Java. IBM has an intro: [[http://www.ibm.com/developerworks/linux/library/l-glib.html|The wonders of GLib]] (currently broken --- 2010-10-20) |
* Buffer for strings: Define a constant for the maximal stringlen eg: ''#define MAXFOOLEN 80'' and reserve memory with one byte more for the 0-terminator: ''char sbf[MAXFOOLEN+1];'' | * Buffer for strings: Define a constant for the maximal stringlen eg: ''#define MAXFOOLEN 80'' and reserve memory with one byte more for the 0-terminator: ''char sbf[MAXFOOLEN+1];'' | ||
* :?: Test: Include header files which are necessary for the interface in ''foo.h''. Include header files necessary only for the implementation in the ''foo.c''. The dependencies for the makefile is the sum of both. | * :?: Test: Include header files which are necessary for the interface in ''foo.h''. Include header files necessary only for the implementation in the ''foo.c''. The dependencies for the makefile is the sum of both. |