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-10 12:16] becki |
becki:linux:c [2017-12-07 14:19] (aktuell) becki [Definition of constant Strings] |
||
---|---|---|---|
Zeile 1: | Zeile 1: | ||
====== C Tips == | ====== C Tips == | ||
- | This is about ISO C and its standard library. POSIX/Linux enhancemnts and features are described in [[:becki:my:linux:linux programming]] | + | 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]]. |
+ | |||
+ | ===== CLI args and main() == | ||
+ | |||
+ | <code c> | ||
+ | int main(int argc, char **argv){ | ||
+ | char * progName= argv[0]; // Filename of programm itself | ||
+ | if (argc >= 2) char * firstArg= argv[1]; // First Argument | ||
+ | } | ||
+ | |||
+ | int main(void){} | ||
+ | // is also possible (Carm p.416) | ||
+ | // don't omit void! (Carm p.278) | ||
+ | </code> | ||
+ | |||
+ | ===== C Program Structure == | ||
+ | |||
+ | {{page>becki/my/linux/design_blog/2017-01-20_c_program_structure&noheader}} | ||
+ | |||
+ | ===== Position of Pointer Sign ====== | ||
+ | |||
+ | Some investigations: | ||
+ | <code c> | ||
+ | int main(int argc, char* argv[]) // Stroustrup p.126 | ||
+ | int main(int argc, char* argv[]) // Josuttis p.21 | ||
+ | int main(int argc, char* argv[], char *env[]) // (!) Breymann p.216 | ||
+ | int main(int argc, char *argv[]) // glibc reference | ||
+ | int main(int argc, char *argv[]) // Kernighan / Ritchie | ||
+ | int main(int argc, char *argv[]) // Harbison / Steele | ||
+ | int main(int argc, char **argv) // gtk reference | ||
+ | int main(int argc, char **argv) // qt reference | ||
+ | int main(int argc, char **argv) // fluxbox source | ||
+ | </code> | ||
+ | |||
+ | -> I use | ||
+ | <code c>char *cp</code> | ||
+ | because | ||
+ | - it seems to be more common | ||
+ | - declarations like "int a, *ap;" are possible | ||
===== Loops == | ===== Loops == | ||
Zeile 28: | Zeile 66: | ||
statement | statement | ||
</code> | </code> | ||
- | ist according to "The C programming language" p.59 the same as: | + | |
+ | is the same as((The C programming language p.59)): | ||
<code c> | <code c> | ||
expr1; | expr1; | ||
Zeile 37: | Zeile 77: | ||
</code> | </code> | ||
- | ===== CLI args and main() == | + | ===== Standard In- and Output == |
+ | ==== stdin == | ||
<code c> | <code c> | ||
- | int main(int argc, char **argv){ | + | /* Read a character from stdin: */ |
- | char * progName= argv[0]; // Filename of programm itself | + | int i= getchar(); |
- | if (argc >= 2) char * firstArg= argv[1]; // First Argument | + | |
- | } | + | |
- | + | ||
- | int main(void){} | + | |
- | // is also possible (Carm p.416) | + | |
- | // don't omit void! (Carm p.278) | + | |
</code> | </code> | ||
- | ===== Position of Pointer Sign ====== | ||
- | Some investigations: | ||
<code c> | <code c> | ||
- | int main(int argc, char* argv[]) // Stroustrup p.126 | + | /* Read stdin line by line into the array lin: */ |
- | int main(int argc, char* argv[]) // Josuttis p.21 | + | char lin[MAX_LINE_LEN]; |
- | int main(int argc, char* argv[], char *env[]) // (!) Breymann p.216 | + | while (fgets(lin, MAX_LINE_LEN, stdin)) {/* do some thing */} |
- | int main(int argc, char *argv[]) // glibc reference | + | |
- | int main(int argc, char *argv[]) // Kernighan / Ritchie | + | |
- | int main(int argc, char *argv[]) // Harbison / Steele | + | |
- | int main(int argc, char **argv) // gtk reference | + | |
- | int main(int argc, char **argv) // qt reference | + | |
- | int main(int argc, char **argv) // fluxbox source | + | |
</code> | </code> | ||
- | -> I use | + | <note tip>If input line lenght is unknown, use ''getline()'' instead of ''fgets()''! |
- | <code c>char *cp</code> | + | (See ''freesigs/io_modbus'')</note> |
- | because | + | |
- | - it seems to be more common | + | |
- | - declarations like "int a, *ap;" are possible | + | |
- | ===== Standard In- and Output == | + | ''scanf'' can also be used for reading from ''stdin''. |
- | ==== stdin == | + | |
- | + | ||
- | <code c> | + | |
- | char lin[MAX_LINE_LEN]; | + | |
- | while (fgets(lin, MAX_LINE_LEN, stdin)) {/* do some thing */} | + | |
- | /* Reads stdin line by line into the array lin */ | + | |
- | </code> | + | |
==== 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 202: | 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 360: | 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 369: | 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. |