From 99ddf8fec686a137586e7a4cdf068b7d3c438cfc Mon Sep 17 00:00:00 2001 From: awschult002 <73046001+awschult002@users.noreply.github.com> Date: Tue, 24 Aug 2021 15:57:49 -0400 Subject: [c/en] mostly word clarification and extra descriptions (#4222) * Adds extra clarity to enum value assignment. The previous statement shows only 1 way to declare enums, and it happens that they specify a starting value. I clarify that a starting value is not necessary and that all enum value could contain user specified values. * Added clarity to `includes` section. specified that angle brackets are for system libraries and not just standard libs. I also added an example of relative paths in the local include statements. * Added more clarity for function prototyping and main return vals. I cleaned up some formatting; then added some clarity to how function prototyping works, as well as recommend techniques. * Fixed the mention of character sizes. they are not always 1 byte * Added clarity about floating point arithmetic. The previous comments on floating points made it feel like there was something broken with doing comparison and arithmetics with floating point types. I added clarity about how floats are stored in memory and why they seem to behave strangly when used in arithmetic expressions. * reworded boolean stuff for better clarity on _Bool type in C99 * Adds not about binary assignment * Added clarity for value roll over * Added section on multiple return values. C doesnt allow returning of multiple values, so i added a section on returning multiple values through pointers. * added section break for printing special characters * fix typo Co-authored-by: Andre Polykanine * fix typos Co-authored-by: Andre Polykanine * fix markdown syntax Co-authored-by: Andre Polykanine * fix markdown syntax Co-authored-by: Andre Polykanine * fix markdown syntax Co-authored-by: Andre Polykanine * reword with better english Co-authored-by: Andre Polykanine * reword with better english Co-authored-by: Andre Polykanine Co-authored-by: Andre Polykanine --- c.html.markdown | 83 ++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 67 insertions(+), 16 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index ff396d21..7405c7ab 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -46,31 +46,47 @@ Multi-line comments don't nest /* Be careful */ // comment ends on this line... // Enumeration constants are also ways to declare constants. // All statements must end with a semicolon -enum days {SUN = 1, MON, TUE, WED, THU, FRI, SAT}; +enum days {SUN, MON, TUE, WED, THU, FRI, SAT}; +// SUN gets 0, MON gets 1, TUE gets 2, etc. + +// Enumeration values can also be specified +enum days {SUN = 1, MON, TUE, WED = 99, THU, FRI, SAT}; // MON gets 2 automatically, TUE gets 3, etc. +// WED get 99, THU gets 100, FRI gets 101, etc. // Import headers with #include #include #include #include -// (File names between are headers from the C standard library.) -// For your own headers, use double quotes instead of angle brackets: -//#include "my_header.h" +// File names between tell the compiler to look in your system +// libraries for the headers. +// For your own headers, use double quotes instead of angle brackets, and +// provide the path: +#include "my_header.h" // local file +#include "../my_lib/my_lib_header.h" //relative path // Declare function signatures in advance in a .h file, or at the top of // your .c file. void function_1(); int function_2(void); -// Must declare a 'function prototype' before main() when functions occur after -// your main() function. +// At a minimum, you must declare a 'function prototype' before its use in any function. +// Normally, prototypes are placed at the top of a file before any function definition. int add_two_ints(int x1, int x2); // function prototype // although `int add_two_ints(int, int);` is also valid (no need to name the args), // it is recommended to name arguments in the prototype as well for easier inspection -// Your program's entry point is a function called -// main with an integer return type. +// Function prototypes are not necessary if the function definition comes before +// any other function that calls that function. However, it's standard practice to +// always add the function prototype to a header file (*.h) and then #include that +// file at the top. This prevents any issues where a function might be called +// before the compiler knows of its existence, while also giving the developer a +// clean header file to share with the rest of the project. + +// Your program's entry point is a function called "main". The return type can +// be anything, however most operating systems expect a return type of `int` for +// error code processing. int main(void) { // your program } @@ -96,13 +112,14 @@ int main (int argc, char** argv) // For the sake of the tutorial, variables are declared dynamically under // C99-compliant standards. - // ints are usually 4 bytes + // ints are usually 4 bytes (use the `sizeof` operator to check) int x_int = 0; - // shorts are usually 2 bytes + // shorts are usually 2 bytes (use the `sizeof` operator to check) short x_short = 0; - // chars are guaranteed to be 1 byte + // chars are defined as the smallest addressable unit for a processor. + // This is usually 1 byte, but for some systems it can be more (ex. for TMS320 from TI it's 2 bytes). char x_char = 0; char y_char = 'y'; // Char literals are quoted with '' @@ -225,13 +242,22 @@ int main (int argc, char** argv) i1 / (double)i2; // => 0.5 // Same with double f1 / f2; // => 0.5, plus or minus epsilon - // Floating-point numbers and calculations are not exact - // for instance it is not giving mathematically correct results + // Floating-point numbers are defined by IEEE 754, thus cannot store perfectly + // exact values. For instance, the following does not produce expected results + // because 0.1 might actually be 0.099999999999 insided the computer, and 0.3 + // might be stored as 0.300000000001. (0.1 + 0.1 + 0.1) != 0.3; // => 1 (true) - // and it is NOT associative + // and it is NOT associative due to reasons mentioned above. 1 + (1e123 - 1e123) != (1 + 1e123) - 1e123; // => 1 (true) // this notation is scientific notations for numbers: 1e123 = 1*10^123 + // It is important to note that most all systems have used IEEE 754 to + // represent floating points. Even python, used for scientific computing, + // eventually calls C which uses IEEE 754. It is mentioned this way not to + // indicate that this is a poor implementation, but instead as a warning + // that when doing floating point comparisons, a little bit of error (epsilon) + // needs to be considered. + // Modulo is there as well, but be careful if arguments are negative 11 % 3; // => 2 as 11 = 2 + 3*x (x=3) (-11) % 3; // => -2, as one would expect @@ -239,7 +265,7 @@ int main (int argc, char** argv) // Comparison operators are probably familiar, but // there is no Boolean type in C. We use ints instead. - // (Or _Bool or bool in C99.) + // (C99 introduced the _Bool type provided in stdbool.h) // 0 is false, anything else is true. (The comparison // operators always yield 0 or 1.) 3 == 2; // => 0 (false) @@ -391,13 +417,16 @@ int main (int argc, char** argv) // if you want (with some constraints). int x_hex = 0x01; // You can assign vars with hex literals + // binary is not in the standard, but allowed by some + // compilers (x_bin = 0b0010010110) // Casting between types will attempt to preserve their numeric values printf("%d\n", x_hex); // => Prints 1 printf("%d\n", (short) x_hex); // => Prints 1 printf("%d\n", (char) x_hex); // => Prints 1 - // Types will overflow without warning + // If you assign a value greater than a types max val, it will rollover + // without warning. printf("%d\n", (unsigned char) 257); // => 1 (Max char = 255 if char is 8 bits long) // For determining the max value of a `char`, a `signed char` and an `unsigned char`, @@ -588,6 +617,24 @@ printf("first: %d\nsecond: %d\n", first, second); // values will be swapped */ +// Return multiple values. +// C does not allow for returning multiple values with the return statement. If +// you would like to return multiple values, then the caller must pass in the +// variables where they would like the returned values to go. These variables must +// be passed in as pointers such that the function can modify them. +int return_multiple( int *array_of_3, int *ret1, int *ret2, int *ret3) +{ + if(array_of_3 == NULL) + return 0; //return error code (false) + + //de-reference the pointer so we modify its value + *ret1 = array_of_3[0]; + *ret2 = array_of_3[1]; + *ret3 = array_of_3[2]; + + return 1; //return error code (true) +} + /* With regards to arrays, they will always be passed to functions as pointers. Even if you statically allocate an array like `arr[10]`, @@ -716,6 +763,10 @@ typedef void (*my_fnp_type)(char *); // my_fnp_type f; +///////////////////////////// +// Printing characters with printf() +///////////////////////////// + //Special characters: /* '\a'; // alert (bell) character -- cgit v1.2.3 From 6a0b4aee8771bbb992b9ddcbfc3823ecc974bdd3 Mon Sep 17 00:00:00 2001 From: krotera <01101011@tuta.io> Date: Mon, 3 Jan 2022 09:44:49 -0700 Subject: [c/en] clarity, errata, and grammar in array section (#4102) * [c/en] clarity, errata, and grammar in array section - [x] I solemnly swear that this is all original content of which I am the original author - [x] Pull request title is prepended with `[language/lang-code]` (example `[python/fr-fr]` or `[java/en]`) - [x] Pull request touches only one file (or a set of logically related files with similar changes made) - [x] Content changes are aimed at *intermediate to experienced programmers* (this is a poor format for explaining fundamental programming concepts) - [x] If you've changed any part of the YAML Frontmatter, make sure it is formatted according to [CONTRIBUTING.md](https://github.com/adambard/learnxinyminutes-docs/blob/master/CONTRIBUTING.markdown) - [x] Yes, I have double-checked quotes and field names! * Overlooked type uniformity * Improve 80 col alignment and clarify loop control var declaration * Remove agrammatical comma * Mention typedef in struct declaration --- c.html.markdown | 53 ++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 17 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 7405c7ab..90b5ed2d 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -162,19 +162,25 @@ int main (int argc, char** argv) int my_int_array[20]; // This array occupies 4 * 20 = 80 bytes // (assuming 4-byte words) - // You can initialize an array to 0 thusly: - char my_array[20] = {0}; + // You can initialize an array of twenty ints that all equal 0 thusly: + int my_array[20] = {0}; // where the "{0}" part is called an "array initializer". - // NOTE that you get away without explicitly declaring the size of the array, - // IF you initialize the array on the same line. So, the following declaration - // is equivalent: - char my_array[] = {0}; - // BUT, then you have to evaluate the size of the array at run-time, like this: + // All elements (if any) past the ones in the initializer are initialized to 0: + int my_array[5] = {1, 2}; + // So my_array now has five elements, all but the first two of which are 0: + // [1, 2, 0, 0, 0] + // NOTE that you get away without explicitly declaring the size + // of the array IF you initialize the array on the same line: + int my_array[] = {0}; + // NOTE that, when not declaring the size, the size of the array is the number + // of elements in the initializer. With "{0}", my_array is now of size one: [0] + // To evaluate the size of the array at run-time, divide its byte size by the + // byte size of its element type: size_t my_array_size = sizeof(my_array) / sizeof(my_array[0]); - // WARNING If you adopt this approach, you should evaluate the size *before* - // you begin passing the array to function (see later discussion), because - // arrays get "downgraded" to raw pointers when they are passed to functions - // (so the statement above will produce the wrong result inside the function). + // WARNING You should evaluate the size *before* you begin passing the array + // to functions (see later discussion) because arrays get "downgraded" to + // raw pointers when they are passed to functions (so the statement above + // will produce the wrong result inside the function). // Indexing an array is like other languages -- or, // rather, other languages are like C @@ -572,7 +578,8 @@ the function are copies of the original arguments (except arrays). Anything you do to the arguments in the function do not change the value of the original argument where the function was called. -Use pointers if you need to edit the original argument values. +Use pointers if you need to edit the original argument values (arrays are always +passed in as pointers). Example: in-place string reversal */ @@ -583,9 +590,11 @@ void str_reverse(char *str_in) char tmp; size_t ii = 0; size_t len = strlen(str_in); // `strlen()` is part of the c standard library - // NOTE: length returned by `strlen` DOESN'T include the - // terminating NULL byte ('\0') - for (ii = 0; ii < len / 2; ii++) { // in C99 you can directly declare type of `ii` here + // NOTE: length returned by `strlen` DOESN'T + // include the terminating NULL byte ('\0') + // in C99 and newer versions, you can directly declare loop control variables + // in the loop's parentheses. e.g., `for (size_t ii = 0; ...` + for (ii = 0; ii < len / 2; ii++) { tmp = str_in[ii]; str_in[ii] = str_in[len - ii - 1]; // ii-th char from end str_in[len - ii - 1] = tmp; @@ -700,7 +709,7 @@ struct rectangle { void function_1() { - struct rectangle my_rec; + struct rectangle my_rec = { 1, 2 }; // Fields can be initialized immediately // Access struct members with . my_rec.width = 10; @@ -724,6 +733,16 @@ int area(rect r) return r.width * r.height; } +// Typedefs can also be defined right during struct definition +typedef struct { + int width; + int height; +} rect; +// Like before, doing this means one can type +rect r; +// instead of having to type +struct rectangle r; + // if you have large structs, you can pass them "by pointer" to avoid copying // the whole struct: int areaptr(const rect *r) @@ -876,7 +895,7 @@ enum traffic_light_state {GREEN, YELLOW, RED}; Node createLinkedList(int *vals, int len); /* Beyond the above elements, other definitions should be left to a C source */ -/* file. Excessive includes or definitions should, also not be contained in */ +/* file. Excessive includes or definitions should also not be contained in */ /* a header file but instead put into separate headers or a C file. */ #endif /* End of the if precompiler directive. */ -- cgit v1.2.3 From 577b70a2e8903b880aa3eec24227001fc5c85195 Mon Sep 17 00:00:00 2001 From: Jonathan Date: Mon, 1 Aug 2022 00:31:57 +0200 Subject: It's C, not c --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index 90b5ed2d..a898f052 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -1,5 +1,5 @@ --- -language: c +language: C filename: learnc.c contributors: - ["Adam Bard", "http://adambard.com/"] -- cgit v1.2.3 From 44e15f80047d0675c421c38aadb2a8dc09d32d06 Mon Sep 17 00:00:00 2001 From: Yash Date: Mon, 10 Oct 2022 22:27:35 +0530 Subject: Added missing information about scanf --- c.html.markdown | 63 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 35 insertions(+), 28 deletions(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index a898f052..cd6b5ad2 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -2,15 +2,15 @@ language: C filename: learnc.c contributors: - - ["Adam Bard", "http://adambard.com/"] - - ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"] - - ["Jakub Trzebiatowski", "http://cbs.stgn.pl"] - - ["Marco Scannadinari", "https://marcoms.github.io"] - - ["Zachary Ferguson", "https://github.io/zfergus2"] - - ["himanshu", "https://github.com/himanshu81494"] - - ["Joshua Li", "https://github.com/JoshuaRLi"] - - ["Dragos B. Chirila", "https://github.com/dchirila"] - - ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"] + - ["Adam Bard", "http://adambard.com/"] + - ["Árpád Goretity", "http://twitter.com/H2CO3_iOS"] + - ["Jakub Trzebiatowski", "http://cbs.stgn.pl"] + - ["Marco Scannadinari", "https://marcoms.github.io"] + - ["Zachary Ferguson", "https://github.io/zfergus2"] + - ["himanshu", "https://github.com/himanshu81494"] + - ["Joshua Li", "https://github.com/JoshuaRLi"] + - ["Dragos B. Chirila", "https://github.com/dchirila"] + - ["Heitor P. de Bittencourt", "https://github.com/heitorPB/"] --- Ah, C. Still **the** language of modern high-performance computing. @@ -101,6 +101,12 @@ int main (int argc, char** argv) // %d is an integer, \n is a newline printf("%d\n", 0); // => Prints 0 + // take input using scanf + // '&' is used to define the location + // where we want to store the input value + int input; + scanf("%d", &input); + /////////////////////////////////////// // Types /////////////////////////////////////// @@ -118,7 +124,7 @@ int main (int argc, char** argv) // shorts are usually 2 bytes (use the `sizeof` operator to check) short x_short = 0; - // chars are defined as the smallest addressable unit for a processor. + // chars are defined as the smallest addressable unit for a processor. // This is usually 1 byte, but for some systems it can be more (ex. for TMS320 from TI it's 2 bytes). char x_char = 0; char y_char = 'y'; // Char literals are quoted with '' @@ -167,19 +173,19 @@ int main (int argc, char** argv) // where the "{0}" part is called an "array initializer". // All elements (if any) past the ones in the initializer are initialized to 0: int my_array[5] = {1, 2}; - // So my_array now has five elements, all but the first two of which are 0: + // So my_array now has five elements, all but the first two of which are 0: // [1, 2, 0, 0, 0] - // NOTE that you get away without explicitly declaring the size + // NOTE that you get away without explicitly declaring the size // of the array IF you initialize the array on the same line: int my_array[] = {0}; - // NOTE that, when not declaring the size, the size of the array is the number + // NOTE that, when not declaring the size, the size of the array is the number // of elements in the initializer. With "{0}", my_array is now of size one: [0] // To evaluate the size of the array at run-time, divide its byte size by the // byte size of its element type: size_t my_array_size = sizeof(my_array) / sizeof(my_array[0]); - // WARNING You should evaluate the size *before* you begin passing the array - // to functions (see later discussion) because arrays get "downgraded" to - // raw pointers when they are passed to functions (so the statement above + // WARNING You should evaluate the size *before* you begin passing the array + // to functions (see later discussion) because arrays get "downgraded" to + // raw pointers when they are passed to functions (so the statement above // will produce the wrong result inside the function). // Indexing an array is like other languages -- or, @@ -247,11 +253,11 @@ int main (int argc, char** argv) (float)i1 / i2; // => 0.5f i1 / (double)i2; // => 0.5 // Same with double f1 / f2; // => 0.5, plus or minus epsilon - + // Floating-point numbers are defined by IEEE 754, thus cannot store perfectly - // exact values. For instance, the following does not produce expected results - // because 0.1 might actually be 0.099999999999 insided the computer, and 0.3 - // might be stored as 0.300000000001. + // exact values. For instance, the following does not produce expected results + // because 0.1 might actually be 0.099999999999 insided the computer, and 0.3 + // might be stored as 0.300000000001. (0.1 + 0.1 + 0.1) != 0.3; // => 1 (true) // and it is NOT associative due to reasons mentioned above. 1 + (1e123 - 1e123) != (1 + 1e123) - 1e123; // => 1 (true) @@ -262,7 +268,7 @@ int main (int argc, char** argv) // eventually calls C which uses IEEE 754. It is mentioned this way not to // indicate that this is a poor implementation, but instead as a warning // that when doing floating point comparisons, a little bit of error (epsilon) - // needs to be considered. + // needs to be considered. // Modulo is there as well, but be careful if arguments are negative 11 % 3; // => 2 as 11 = 2 + 3*x (x=3) @@ -411,7 +417,7 @@ int main (int argc, char** argv) */ /* it is generally considered bad practice to do so, except if - you really know what you are doing. See + you really know what you are doing. See https://en.wikipedia.org/wiki/Spaghetti_code#Meaning */ @@ -424,7 +430,7 @@ int main (int argc, char** argv) int x_hex = 0x01; // You can assign vars with hex literals // binary is not in the standard, but allowed by some - // compilers (x_bin = 0b0010010110) + // compilers (x_bin = 0b0010010110) // Casting between types will attempt to preserve their numeric values printf("%d\n", x_hex); // => Prints 1 @@ -626,7 +632,7 @@ printf("first: %d\nsecond: %d\n", first, second); // values will be swapped */ -// Return multiple values. +// Return multiple values. // C does not allow for returning multiple values with the return statement. If // you would like to return multiple values, then the caller must pass in the // variables where they would like the returned values to go. These variables must @@ -637,9 +643,9 @@ int return_multiple( int *array_of_3, int *ret1, int *ret2, int *ret3) return 0; //return error code (false) //de-reference the pointer so we modify its value - *ret1 = array_of_3[0]; - *ret2 = array_of_3[1]; - *ret3 = array_of_3[2]; + *ret1 = array_of_3[0]; + *ret2 = array_of_3[1]; + *ret3 = array_of_3[2]; return 1; //return error code (true) } @@ -901,10 +907,11 @@ Node createLinkedList(int *vals, int len); #endif /* End of the if precompiler directive. */ ``` + ## Further Reading Best to find yourself a copy of [K&R, aka "The C Programming Language"](https://en.wikipedia.org/wiki/The_C_Programming_Language) -It is *the* book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some +It is _the_ book about C, written by Dennis Ritchie, the creator of C, and Brian Kernighan. Be careful, though - it's ancient and it contains some inaccuracies (well, ideas that are not considered good anymore) or now-changed practices. Another good resource is [Learn C The Hard Way](http://learncodethehardway.org/c/) (not free). -- cgit v1.2.3 From bba9f7df211d63293e2a957872d156a0a6dfcd48 Mon Sep 17 00:00:00 2001 From: Marcel Ribeiro-Dantas Date: Sat, 10 Dec 2022 12:05:34 -0300 Subject: Fixes typos in many different English articles Signed-off-by: Marcel Ribeiro-Dantas --- c.html.markdown | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'c.html.markdown') diff --git a/c.html.markdown b/c.html.markdown index cd6b5ad2..ef341abf 100644 --- a/c.html.markdown +++ b/c.html.markdown @@ -256,7 +256,7 @@ int main (int argc, char** argv) // Floating-point numbers are defined by IEEE 754, thus cannot store perfectly // exact values. For instance, the following does not produce expected results - // because 0.1 might actually be 0.099999999999 insided the computer, and 0.3 + // because 0.1 might actually be 0.099999999999 inside the computer, and 0.3 // might be stored as 0.300000000001. (0.1 + 0.1 + 0.1) != 0.3; // => 1 (true) // and it is NOT associative due to reasons mentioned above. -- cgit v1.2.3