Hier werden die Unterschiede zwischen zwei Versionen angezeigt.
Beide Seiten der vorigen Revision Vorhergehende Überarbeitung Nächste Überarbeitung | Vorhergehende Überarbeitung | ||
becki:linux:c [2010-10-20 10:11] 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 370: | 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 == |