Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
becki:linux:c [2010-11-08 14:21] becki |
becki:linux:c [2017-12-07 14:19] (aktuell) becki [Definition of constant Strings] |
||
---|---|---|---|
Zeile 2: | Zeile 2: | ||
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]]. | 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 38: | Zeile 76: | ||
} | } | ||
</code> | </code> | ||
- | |||
- | ===== 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> | ||
- | |||
- | ===== 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 | ||
===== Standard In- and Output == | ===== Standard In- and Output == | ||
Zeile 85: | Zeile 90: | ||
while (fgets(lin, MAX_LINE_LEN, stdin)) {/* do some thing */} | while (fgets(lin, MAX_LINE_LEN, stdin)) {/* do some thing */} | ||
</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''. | ''scanf'' can also be used for reading from ''stdin''. | ||
Zeile 103: | Zeile 111: | ||
</code> | </code> | ||
- | Writing to ''stderr'' is unbuffered, writing to ''stdout'' is buffered ((CARM p.351)) => Always use ''stderr'' for debugging messages ((RRUSP p.68)) | + | 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 212: | 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 374: | Zeile 385: | ||
- 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 == |