and | becomes | && |
---|---|---|
and_eq | becomes | &= |
bitand | becomes | & |
bitor | becomes | | |
compl | becomes | ~ |
not | becomes | ! |
not_eq | becomes | != |
or | becomes | || |
or_eq | becomes | |= |
xor | becomes | ^ |
xor_eq | becomes | ^= |
Priority | Operator | Associativity |
---|---|---|
1st | () [] . -> |
Left-to-right |
2nd | ++foo --foo + - ! ~ (type) *foo & sizeof() _Alignof() |
Right-to-left |
3rd | * / % |
Left-to-right |
4th | + - |
Left-to-right |
5th | << >> |
Left-to-right |
6th | < > <= >= |
Left-to-right |
7th | == != |
Left-to-right |
8th | & | Left-to-right |
9th | ^ | Left-to-right |
10th | | | Left-to-right |
11th | && | Left-to-right |
12th | || | Left-to-right |
13th | () ? : |
Right-to-left |
14th | = += -= *= /= %= <<= >>= &= ^= |= |
Right-to-left |
15th | foo++ foo-- |
NA |
16th | , | Left-to-right |
_Bool <= char <= short <= int <= void/pointer*(if allowed in implementation) <= long <= long long <= float <= double <= long double
int x = 2; int y = x; x = 4; // The value of 2 is stored in y, the value 4 is stored in x int x = 3; int y = x; int x = y + 1; // The value of 3 is stored in y, the value of 4 is stored in x int x = 2; int y = (3 == 3) + 4; // The value 5 is stored in y, x stores the value 2This has to do with pass by value. (note this is implementation defined and should be avoided when possible)
int x = 2; int y = ++x; (Y is now 3, and X is now 3) int y = x++; (Y is now 2, X is now 3)Example 2:
int x = 2; int y = x--; (Y is now 2, X is now 1) int y = --x; (Y is now 1, X is now 1);It should be noted that only one increment or decrement operator can safely be used in a single expression. It is undefined behavior to have multiple pre and/or post increment/decrement operators in a single expression. The reason for this is simply because it has no algebraic/mathematical replacement and thus the compiler has to decide which increment and decrement operation is performed first.
int i=4; printf("%d", ++i + ++i + ++i); // Prints 18 to the screen on my computerExample 4:
int i=4; int x = ++i + ++i + ++i; printf("%d", x); // Prints 23 to the screen on my computer
char array[5] = “Clay”; char array[5] = {‘C’,’l’,’a’,’y’,’\0’}; char array[5] = {67,108,97,121,0};
char arr[] = “C Programming”;is equivalent to:
char arr[] = {‘C’,’ ’,’P’,’r’,’o’,’g’,’r’,’a’,’m’,’m’,’i’,’n’,’g’,’\0’};and also:
char arr[14]; char arr[0] = ‘C’; char arr[1] = ‘ ’; char arr[2] = ‘P’; char arr[3] = ‘r’; char arr[4] = ‘o’; char arr[5] = ‘g’; char arr[6] = ‘r’; char arr[7] = ‘a’; char arr[8] = ‘m’; char arr[9] = ‘m’; char arr[10] = ‘i’; char arr[11] = ‘n’; char arr[12] = ‘g’; char arr[13] = 0;
int myArr[] = 6; //ERROR, cannot assign to value using this notation int arr2[20] = arr; //ERROR, cannot assign to value using this notation char name[10]; name = “Clay”; //ERROR, can only be INITIALIZED with a string, cannot be ASSIGNED to string
char chArray[6] = {h, e, l, l, o, \0};The number in the brackets referred to the size of the array, in this case it stored 6 characters. In a following example we could do:
printf(“%c”, array[0]);Which would print a ‘h’ on the screen because arrays start at value 0. (Most languages start arrays at value 0 with few exceptions (Lua, COBOL, Fortran, R, MATLAB, and AWK to name of few examples)) (Explained more under arrays)
%[flag(s)][field width][. precision][length modifier]conversion-specifier
%[flag(s)][field width][length modifier]conversion-specifier
- | Left justifies the conversion. If left out the default is that the string is right justified to the field width. |
+ | Adds a positive '+' sign to the conversion if it is a positive number. Default is no prefix to positive numbers, only a '-' on negative numbers. |
# | Not really sure tbh, when used with the g/G conversion specifiers it removes trailing 0s after the decimal place. |
0 | Adds preceding 0s to fill the field-width as needed. |
' ' (space) |
(only scanf family of functions) Used with 'c', 'n' and '[set]' conversion specifiers that are whitespace sensitive. This tells them to skip preceding whitespace and start at the first non-whitespace character. |
* | (only scanf family of functions at least as a flag) tells scanf to match the conversion specifier, but do not store it in a variable. In printf it can be a placeholder in both the precision and the field width to which it is used as a placeholder for an argument to be passed after the formatted string with an integer value that will be used in the asterisks place. |
%* | Depends on if it is used in the printf or the scanf family of functions. In printf it functions as a place holder for an int to be passed in via argument before one of the aforementioned escape sequences. In scanf it essentially means "skip" this in the string and do not store it in a variable. This is useful if you have garbage you don't care about between some information you do care about that you want to store in variables, this lets you skip the garbage and still be able to assign to the variables you want. Example 1: scanf("%d %*s %*s %d", &i, &j); printf("%d, %d.\n", i, j); Stores two integers that have a string of character between them in two variables i and j. SO if the input was 123 wofjw lnwv 987, the out put onto the screen would be 123, 987. |
%% | Escape to allow % to be printed |
%[A-Z] |
Used in scanf functions only, reads up until the character(s) (ABC...Z in this case) are NOT used (inverse of following format specifier), can use escape sequence characters as well. Stores it in a variable (character array). Note that this format specifier does not play well with %n on some implementations and makes that format specifier impossible to use in conjunction with this one. Can use a range of characters like in this case or can use single characters or a list of comma separated characters including non-printing characters that require escape sequences. This format specifier is actually called a scanset in the C Standard. |
%[^X] | Used in scanf functions only, reads up until the character (X in this case), can use escape sequence characters as well. Stores it in a variable (character array). Note that this format specifier does not play well with %n on some implementations and makes that format specifier impossible to use in conjunction with this one. This format specifier is actually called a scanset in the C Standard. |
%n | Stores the number of characters preceding it into the variable |
%c | Character (any ASCII character)(need an array for Unicode characters) |
%s | String in human readable form. |
%p | Address that the pointer holds |
%a/A | Converts a floating point number to its hexadecimal equivalent |
%d | Signed decimal integer. |
%u | Unsigned integer value |
%e/E | Scientific notation |
%f | Float (same as %lf in printf family functions, but do actually differ in scanf family functions (because scanf needs to know the size of the variable and printf doesn't care) Thus for clarity of intent to other programmers reading your code use %f for floats always and %lf for double, but for backwards compatibility you would use %f (if you have to, g++ rejects %lf) ) |
%g/G | Prints the more concise format between float and scientific notation |
%x/X | Converts the number passed to it to hexadecimal |
%o | Octal |
%i | Integer of any type (auto detects) |
\a | Audio or visual bell |
\b | Backspace (moves the cursor back, but does not delete characters, only removes if replaced with later text) |
\n | Newline |
\r | Carriage Return (Puts cursor at start of current line) |
\t | Tab |
\v | Vertical Tab |
\\ | Stops a '\' character from being interpreted as an escape character and instead simply as itself |
\' | Prevents a ' character from being interpreted as a operator and instead treats it as a character itself |
\" | Prevents the " character from being interpreted as the ending of the string and simply as itself |
\0 | Adds the null character (zero in binary), used to set the end of a string |
\x | \xHEX where "HEX" is a hexadecimal number prints the corresponding ASCII character in printf |
\u | \uFFFF where "FFFF" is a hexadecimal character that refers to a Unicode code point (similar to \x) |
\U | \UFFFFFFFF just like \u but for Unicode characters above 4 places |
\f | Form feed, LEGACY |
\e | Deletes character to its right, LEGACY |
\? | Prevents sequence from being interpreted as a trigraph, LEGACY |
# | When used at the beginning of a line, tells the preprocessor that the word following it is a preprocessor directive. This is why all of the following directives have a '#' in front of them. Otherwise the compiler will think that it is part of the standard C code and will be confused. |
#include | Used to copy the contents of a file verbatim at this location in the source code during preprocessing. The directive is followed by a file path ether relative or absolute in double quotes or angle brackets. |
#pragma | This directive is implementation/compiler specific/dependent. It can do all sorts of things on different compilers, including but not limited to turning on and off features of a compiler in the source code rather than passing flags to it in the terminal. Can be used to turn off all warnings, to make an identifier illegal to use, to run certain functions on startup or exit and many more. |
#define | Used to create macros in C which are words that expand out to some other literal. Can also be used to make function-like macros. When not used to make macros with arguments, then it will act as a simple find and replace feature making it easier to change text in multiple places by simply modifying it in one spot. Example 1: #define MAXLEN 7This would create a macro named MAXLEN, and everywhere in the code except in strings that this is found will be converted to 7 before compilation even occurs. This is useful because if we have a number we need to use a lot for a specific reason, making it a constant both provides clarity and makes it easy to swap out for testing and so forth in one place, and change it wherever the constant is used. Example 2: #define min(X, Y) ((X) < (Y) ? (X) : (Y))This creates a function-like macro that will return the lower of two numbers passed to it. Note: One of the reasons macros, and macro-like functions are used/or used to be used was because they were done at the preprocessor level rather than during execution and were faster. This is negligible today, but still something to keep in mind. The reason for this, is because there is no time wasted in a function call, as it simply replaces the macro with the function everywhere in the code. |
## | Often referred to as the merging/combining or concatenation operator is used to well... Concatenate the left and right operators. Example: #define tokenpaster(n) printf ("var" #n " = %d", var##n) int main(void) { int var1 = 10; int var2 = 20; int var2 = 30; tokenpaster(2); return 0; }This prints: var2 = 20 |
#error | Often used inside of #if or #ifdef preprocessor directives, this #error directive simply throws an error to standard out while stopping any further preprocessing or compilation of the program. Used similar to assert. |
#warning | Similar to the #error directive, but does not stop further preprocessing and compilation. Still prints the warning to the output. |
#undef | Undefines a previously defined macro. Often used after #ifdef guards which check what other macros are defined including those specifying what operating system is being used. |
#if | Conditional operator that runs at the preprocessor level. Checks the value of a variable or constant and then adds the code between it if result returns true, otherwise the code inside of the #if statement is not compiled into the executable. |
#else | Used like a normal else keyword, but works with the preprocessor #if instead. |
#elif | Used like an else if statement in C, but again is used with the preprocessor directives #if and #else instead. |
#endif | Unlike in if statements in C that either execute just one line of code if no brackets are available or whenever it finds the corresponding '}' bracket, this directive is ALWAYS used with #if, #ifdef, and #ifndef to specify where they end. |
#ifdef | Checks to see if a macro with the same identifier as the word immediately following this directive is defined and if it is returns true and is used like a normal #if. |
#ifndef | Same as the #ifdef except that it returns true if the following macro is NOT defined and false if it is. |
#line | Is followed by two arguments and fills the __LINE__ and __FILE__ macros to those values respectively. This is a very useful macro that can help the compiler correct where it thinks errors and warnings are occurring by setting those values yourself. |
_FILE_ | Set by the #line preprocessor directive and can be used to help produce better and more clear warning and error messages by specifying where the location of the error or warning really occurred. |
_LINE_ | Set by the #line preprocessor directive and can be used to help produce better and more clear warning and error messages by specifying where the location of the error or warning really occurred. |
_FILE_and_LINE_ | Same as above, but together. |
_DATE_ | A preprocessor macro that expands to the current system date. |
_TIME_ | A preprocessor macro that expands to the current system time. |
_STDC_ | Macro that expands to 1 if the current implementation conforms to the C Standard |
_STDC_VERSION_ | Macro that expands to the version of the standard that the implementation conforms too |
_STDC_HOSTED_ | Macro that expands to 1 if the current environment conforms to the standard definition of a hosted environment or 0 if it does not. |
_cplusplus | A macro that returns true if the following compilation unit was compiled by a C++ compiler rather than a C compiler. |
_OBJC_ | Same as _cpluplus, but for Objective C. |
char <= short <= int <= * (pointer) <= long <= long long float <= double <= long double
double var; //This will set aside a block of memory large enough to store a double and label it "var".
double div2Nums(int param1, int param2); // this tells the compiler a lot. Firstly it implies that there is a function defined later that returns a double when two integer values are passed into it, and also the name to call it by.
x = 3;or
double div2nums(int param1, int param2) { double sum = param1 / param2; return sum; } // this function is now complete and can be called and used in your code. Once you add an already declared element with a definition you have completed the requirement to use it.
int x; //could store any value (undefined/garbage) (unless static or extern) int x = 5; //stores a specific value of 5.
int *a,b,c; int *d,*e,*f; printf("sizeof() returns: %zu, %zu, %zu\n", sizeof(a), sizeof(b), sizeof(c)); printf("sizeof() returns: %zu, %zu, %zu\n", sizeof(d), sizeof(e), sizeof(f));Prints:
sizeof returns: 8, 4, 4 sizeof returns: 8, 8, 8
int* a,b,c;is equivalent to:
int *a; int b; int c;Where only the variable 'a' is created as a pointer to an int and the following variables are just type int.
int array[10] = {[9] = 0, [0] = 62}; //this assigns only the 9th (last) element and the 0th (first) element in the array to a value and everything else will be unassigned (unless declared statically or globally).
struct myPerson { char* name; short age; short weight; }; struct myPerson clay = {.weight = 205, .age = 23}; //only members age and weight are assigned and member name is uninitialized ( or is initialized to 0/NULL if declared in static memory) clay.name = "Clay"; printf("%s, %d, %d\n", clay.name, clay.age, clay.weight);Prints: "Clay, 23, 205" to the screen.
A/A+ = 4.0, A- = 3.7, B+ = 3.3, B = 3.0, B- = 2.7, C+ = 2.3, C = 2.0, C- = 1.7, D+ = 1.3, D = 1.0, D- = .7, F = 0 #define CLASSES_TAKEN = 8;Array was assigned out of order and my_gpa[3] was excluded just to show that you can. Keep in mind that if an array is defined in local/auto scope/storage class than it is implementation defined, but common for the values to be initialized in those elements to be garbage/undefined. And thus my_gpa[3] could hold any value.
double my_gpa[CLASSES_TAKEN] = {3.3, 2.3, 1.7, 4.0, 3.7, 3.7, 3.7, 2.7, 3.0}; //error exceeds array limit double my_gpa[CLASSES_TAKEN] = {3.3, 2.3, 1.7, 4.0, 3.7, 3.7, 3.7, 2.7}; // Much better! or double my_gpa[8]; my_gpa[0] = 3.3; my_gpa[7] = 2.7; my_gpa[2] = 1.7; my_gpa[1] = 2.3; my_gpa[5] = 3.7; my_gpa[6] = 3.7; my_gpa[4] = 3.7; my_gpa[8] = 3.0; // ERROR, exceeds array boundaries
//12 months in one year, up to 31 days in a month (a few months will just not use the 31st index.) const int MAXWORDS = 5; const in WORDLEN = 20; char* [MAXWORDS][WORDLEN]; for (int i = 0; i < MAXWORDS; ++i) { for (int j = 0; j < WORDLEN; ++j) { one_year_journal[i][j] = NULL; } }
char words[5][20] = { {'C','L','A','Y','\0'}, {'G','e','o','r','g','e','\n',0}, "Apple", {'H','i','\0'}, {' ',0} }; printf("%s", words[1][0]);Prints George to the screen.
printf("%s", words[1]);
printf("%s", words[0][2]);
char words[5][20]; words[0][0] = 'C'; words[0][1] = 'L'; words[0][2] = 'A'; words[0][3] = 'Y'; words[0][4] = '\0'; words[2][0] = 'A'; words[2][1] = 'p'; words[2][2] = 'p'; words[2][3] = 'l'; words[2][4] = 'e'; words[2][5] = 0;
char *_09_03_1998 = "Today I was born."; char *_07_30_1965 = "LBJ signed Medicare into law."; char *_09_11_2001 = "Terrorists attack the World Trade Center in New York."; char* events_since_ad[4000][12][366]; events_since_ad[1998][9][3] = _09_03_1998; events_since_ad[1965][7][30] = _07_30_1965; events_since_ad[2001][9][11] = _09_11_2001; printf("%s\n",events_since_ad[1998][9][3]);Prints "Today I was born." onto the console.
int favNumbers[10] { 3, 7, 20, 21, 22, 24, 80, 88}Now when I want to access them all I have to remember is the array name favNumbers and I can quickly access any of them as I wish. Strings are similar as they are just arrays of chars.
RETURNTYPE NAME(TYPE PARAMETER,TYPE ANOTHER PARAM); // Function Prototype (usually above main or in header files. RETURNTYPE NAME(TYPE PARAMETER, TYPE ANOTHER PARAM) // function definition (usually below main function) { code; more code; return EXPRESSION; // this would be omitted if return type is void } name(argument 1, argument); // function call, with two arguments passed into it
#include <stdio.h> int main(int random, char *justForFun[]) //int main(int argc, char *argv[]) //int main(int argc, char **argv) //both are equivilent. { printf("Number of arguments: %d\n", random); //printf("Number of arguments: %d\n", argc); for (int i = 0; i < random; ++i) { //for (int i = 0; i < argc; ++i) { printf("Arugument #%d: %s\n", i, justForFun[i]); //printf("Arugument #%d: %s\n", i, argv[i]); } return 0; }./a.out one two three
Number of arguments: 4 Argument #0: ./a.out Argument #1: one Argument #2: two Argument #3: three
int x = 2; int y = 3; int answer = 3 / 2; double answer2 = 3 / 2; printf(“%d”, answer); //prints “1” to the console. printf(“%.2lf”, answer2); //prints “1.00” to the screen
int x = 2; int y = 3; int answer = (double) 3 / (double) 2; double answer2 = (double) 3 / (double) 2; double answer3 = 3 / (double) 2; double answer4 = (double) 3 / 2; printf(“%d”, answer); //prints “1” to the console. printf(“%.2lf”, answer2); //prints “1.50” to the screen printf(“%.2lf”, answer3); //prints “1.50” to the screen printf(“%.2lf”, answer4); //prints “1.50” to the screen
int -> unsigned int -> long -> unsigned long -> long long -> unsigned long long -> float -> double -> long double
char (*str)[15] = &"This is valid!";
x = 5 + 1 // valid 5 = x + 1 // invalid y = x + 5 + 1 // valid x = x + 5 + 1 // valid
union (optional structure tag) { member declaration; member declaration; ... member declaration; } (0+ variables of this union type); union human { int age; int heightFt; int heightInch; char* name; char gender; double weight; }clay;
enum tag {CONSTANT, ANOTHER CONSTANT, etc.}variableOfThisType (if any); enum days {Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday} test1; enum days test2 = Tuesday; test1 = Thursday; enum days test3 = 65; //valid, not an error printf("%d\t%d\t%d\t%d\n", test1, test2, test3, Friday); //prints 3 1 65 4
#include <stdio.h> void print_sum(int (*name)(int), int b) { int a = name(b); printf("The sum is: %d\n", a + b); } int subtract_one(int a) { return a - 1; } int main(void) { print_sum(&subtract_one, 7); return 0; } int *ptr = &a; 1^ ^2 ^3
int (*ptr)(double, char) = &a;
struct human { int age; int heightFt; int heightInch; char* name; char gender; double weight; }clay;Declaration for struct of type human:
struct human person1;Definition for struct human person1 (all the values are assigned below, but you can define whichever you want and in whatever order you want if you so choose):
person1.age = 35; person1.heightFt = 5; person1.heightInch = 10; person1.name = “Joseph”; person1.gender = ‘M’; person1.weight = 215.32;
struct (optional structure tag) { member declaration; member declaration; ... member declaration; } (0+ variables of this struct type);
#include <stdio.h> #pragma pack(1) //if included will make the structure fit in as tightly as possible, otherwise padding will be added so that everything fits nicely in powers of two in memory, not that adding this preprocessor directive can lead to slower and larger executables because it turns off compiler optimizations struct random { unsigned int random: 18; //111111111111111111 0->262143 unsigned int random2: 9; // 111111111 0->511 int random3: 4; //1111 -8->7 unsigned int random4: 6; //11111 0->63 }random; int main(void) { random.random = 262143; random.random2 = 511; random.random3 = 7; random.random4 = 63; printf("Sizeof() random struct: %zu\n", sizeof(random)); printf("random.random is: %d, random.random2 is: %d, random.random3 is: %d\n", random.random, random.random2, random.random3); return 0; }
char arr[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '\0' }; char arr[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0 }; char arr[] = { 'h', 'e', 'l', 'l', 'o', '\0', 'w', 'o', 'r', 'l', 'd', 0 }; //technically contains two strings char arr[12] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0 }; static char arr[12] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd' }; //static variables are always initialized to zero so this is NULL terminated char arr[] = “double quotes adds null if size permits”; char arr[] = "a"; char arr[] = {67, 108, 97, 121, 0}; char arr[5] = “Clay”;
char arr[] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'}; char arr[11] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', 0}; char arr[12] = { 'h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd'}; char arr[] = ‘a’; char arr[] = { 67, 108, 97, 121}; char arr[4] = “Clay”;
// This is a single line comment NOT COMMENTED OUT printf("NOT COMMENTED OUT\n"); //This is commented out, but the printf function was not. NOT COMMENTED OUT /* This is commented out this line is commented out. so is this line. this is commented out. */ NOT COMMENTED OUT NOT COMMENTED OUT
printf(“%d”, 1);is equivalent to:
printf ( “%d” , y ) ;
int func1(int a, int b) { return a + b; }
int sum2Nums = func1(3, 7);
short x; printf("Enter a number less than 10: "); scanf("%hi", &x); if (x > 10) { fprintf(stderr, "ERROR: the number you gave me was greater than 10.\n"); exit(); //crashes program } printf("Thank you for giving me a number less than 10!\n");
short age; printf("Enter your age: "); scanf("%hi", &age); if (age < 0) { printf("You're not even born yet.\n"); }else if (age < 13) { printf("You're a young child.\n"); } else if ( age < 18 ) { printf("You're a teenager.\n"); } else if (age < 26) { printf("You're a young adult.\n"); } else if (age < 35) { printf("You're starting to get old.\n"); } else if (age < 42) { printf("You're middle aged and officially old.\n"); } else { printf("You're ANCIENT! Your a really old geaser!\n"); }
#include <stdio.h> #include <stdlib.h> #include <time.h> srand(time(0)); int win = rand() % 1000; long long num = 0; while (num != win) { printf("Enter guess: "); scanf("%lld", &num); if (num > win) { printf("lower\n"); } else if (num < win) { printf("higher\n"); } }
#define TIMESTOPRINT 20 char name[20]; printf("Enter your name: "); scanf("%19s", name); for (int i = 0; i < TIMESTOPRINT; ++i) { printf("%s\n", name); }
short num; do{ printf("Enter a number greater than ten but less than 100: "); scanf("%hi", &num); } while (num > 10 && num < 100);
#define LENGTH 11 for (int i = 0; i < LENGTH; ++i) { if ( i % 2 ) { printf("%i", i); continue; } printf("_"); }
#define LENGTH 11 for (int i = 0; i < LENGTH; ++i) { if ( i % 2 ) { printf("%i", i); } printf("_"); break; }
#include <stdio.h> void add3(double a, double b, double c) { printf("%lf", a + b + c); } void subtract3(double a, double b, double c) { printf("%lf", a - b - c); } void multiply3(double a, double b, double c) { printf("%lf", a * b * c); } void divide3(double a, double b, double c) { printf("%lf", a / b / c); } int main(void) { int one, two, three; char userInput; printf("Give me 3 numbers separated by commas: "); scanf(" %d, %d, %d", &one, &two, &three); INPUT: printf("Type the character corresponding to the operation you want to perform.\n"); printf("ADD: + or A/a, Subtract: - or s/S, " "Multiply: * or m/M or x/X, Divide: / or d/D\n"); scanf(" %c", &userInput); switch (userInput) { case '+': case 'A': case 'a': add3(one, two, three); break; case '-': case 's': case 'S': subtract3(one, two, three); break; case '*': case 'm': case 'M': case 'x': case 'X': multiply3(one, two, three); break; case '/': case 'd': case 'D': divide3(one,two,three); break; default: printf("You entered an invalid operation, please try again!\n"); goto INPUT; } return 0; }
#include <stdio.h> void newfun(int a) { a--; if (a >= 1) newfun(a); printf("%d",a); } int main(void) { newfun(7); return 0; }
#include <stdio.h> int set_array_to_zero(int two_dimensional_array[], int width, height) { if (width > 0 ) { if (height > 0 ) { //nested if statement, only gets executed if the first if statement conditional was true for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j { //this for loop is nested within the other for loop and thus runs in its entirety each time the parent loop runs through a single iteration thus O^2 two_dimensional_array[i][j] = 0; } } } } } int main(void) { //run code in main function func1(1,2); //nested function call, func1 will run and then when it is done main function will continue //continue main int a = 6; printf("%d\n",a); //prints 6 { //nested block statment, this block is the child of the main functions block, inherits parents data, and can manipulate parents data, but new data created here such as variables only live until the end of the block (unless static keyword is used) . int b = 3; printf("%d,%d\n",a,b); //prints 6,3 a = 4; } //printf("%d\n",b); //compiler error, b is not defined here printf("%d\n",a); //prints 4 }
#define REALLY_BIG_NUMBER 123456789In the example above anywhere in the code before compilation, in the preprocessor step, the preprocessor will look for every instance of the word REALLY_BIG_NUMBER that is not held within a string literal and replaces it with 123456789. So if I had somewhere in my code that looked like this: sum = 23 + REALLY_BIG_NUMBER; after the preprocessor step in compilation is done, that same line will look like: sum = 23 + 123456789;. Function like macros work mostly the same way. In order to call a function like macro you need to include parentheses and names for parameters you want if any passed into the macro like so:
#include <stdio.h> #define MACRO(A,Z,F) printf("%lf\n", A + Z + F) int main(void) { double num = 1.1; MACRO(32.0,7,num); return 0; }
int pid = fork(); if (pid = -1) { //check if the fork failed, and if it did this code will run } if (pid == 0) { //have the child process do this simultaneously } else { //have the parent process do this simultaneously }
#include <stdio.h> #include <stdarg.h> #include <string.h> //Function Prototypes double add(int num_args, ...); void printArray(int num_args, char** types, ...); int main(void) { int v = 6, w = 3, x = 1, y = 4, z = 2; double sum; sum = add(5,v,w,x,y,z); printf("main function end: %lf\n",sum); printf("%d\n",22,v+1); //I included the above printf to show that this code is valid and will compile. //While this code does give warnings, there is no error and the program runs as if the 23 was not there. //the expression still occur, but the printf does nothing else with them char a = 'a'; short b = 69; int c = 7; long d = 3009; long long e = 4567889; float f = 3.1; double g = 6.402; char* array1[11] = { "char", "short", "int", "long", "long long", "float", "double" }; printf("%c, %hu, %d, %ld, %lld, %f, %lf\n",a,b,c,d,e,f,g); printArray(7, array1, a, b, c, d, e, f, g); return 0; } void printArray(int num_args, char** types,...) { va_list list_of_args; va_start(list_of_args, types); for (int i = 0; i < num_args; ++i) { if (!strcmp(types[i], "int")) { printf("INTEGER: %d", va_arg(list_of_args, int)); } else if (!strcmp(types[i], "long long")) { printf("LONG: %lld", va_arg(list_of_args, long long)); } else if (!strcmp(types[i], "long")) { printf("LONG LONG: %ld", va_arg(list_of_args, long)); } else if (!strcmp(types[i], "short")) { printf("SHORT: %d", va_arg(list_of_args, int)); } else if (!strcmp(types[i], "char")) { printf("CHAR: %c", va_arg(list_of_args, int)); } else if (!strcmp(types[i], "float")) { printf("FLOAT: %lf", va_arg(list_of_args, double)); } else if (!strcmp(types[i], "double")) { printf("DOUBLE: %lf", va_arg(list_of_args, double)); } else { fprintf(stderr,"ERROR"); } printf("\n"); } va_end(list_of_args); } double add(int num_args, ...) { va_list my_list; double i = 0, sum = 0; va_start(my_list, num_args); for (i = 0; i < num_args; ++i) { printf("%lf\n",sum += va_arg(my_list, int)); } va_end(my_list); return sum; }
#include <stdio.h> //printf() #include <string.h> //memcpy #include <limits.h> //INT_MAX #include <stdlib.h> //rand(), srand() #include <time.h> //time() /* (*name_of_array)[] == how to dereference a pointer to an array*/ /* int *array[10] == an array of 10 int pointers*/ /* int (*array)[10] == dereferencing a pointer to an int which is stored at element 10 of the array "array".*/ /* int one = 1;*/ /* int two = 2;*/ /* int three = 3;*/ /* int four = 4;*/ /* int five = 5;*/ /* int* my_array[5] = {&one, &two, &three, &four, &five};*/ /* printf("%d", (*my_array)[3]); //prints the value 4 to the screen*/ #define ARRAY_SIZE 30 //malloc,calloc,realloc, dynamic memory has the scope of the pointer variable that points to it, but has the lifetime unlike any other, it is neither automatic/stack or part of the stack, but belongs to its own heap/dynamic/allocated memory space. Objects created here exist from the time they are created, until they are freed using the free() function. This can span multiple blocks and functions, or could happen 3 lines later if a free() function is used. However, the pointer that points to the block of memory is of whatever scope and lifetime it was created for and if it is lost/dies/goes out of scope this is a memory leak as their is no way to free the memory now and it will just keep taking up space that is no longer usable for future calls on heap memory (memory leak) int main(void) { srand(time(NULL)); int static_array[ARRAY_SIZE]; //fill static array with random numbers 0-9 for (int i = 0; i < ARRAY_SIZE; ++i) { static_array[i] = rand() % 9; } //print array for (int i = 0; i < ARRAY_SIZE; ++i) { printf("%d ", static_array[i]); } printf("\n\n"); //dynamically create another array of twice the size and then copy over the contents // casts are not needed, but are often used to help other readers know whats going on, void pointer will be converted to whatever type the variable that is assigneed to the malloc is anyways even without cast /* int* heap_array = (int*) calloc(2, ARRAY_SIZE * sizeof(int)); //same as below but regardless of implementation it initializes all of the space to 0 */ if ( int* heap_array = (int*) malloc(ARRAY_SIZE * 2 * sizeof(int)) == NULL) { fprintf(stderr, "Memory allocation failed\n"); exit(-1); } memcpy(heap_array, static_array, ARRAY_SIZE * sizeof(int)); //print out the new dynamically allocated array with the contents copied over for (int i = 0; i < ARRAY_SIZE * 2; ++i) { printf("%d ", heap_array[i]); } printf("\n\n"); //I don't actually need it to be twice the size so truncate it to the original size + 3 //realloc does not change the size of th ptr you pass to it, but rather finds a block of memory of the size you want it to be and then copies over all the contents as if they were always stored in that size and frees the previous block of memory // if realloc is smaller than original than it truncates, and if it is larger the values of the positions in the array past the ones defined before are undefined (on my mac using clang it always initializes everything to 0 though (implementation defined)) // often times you assign it to the same ptr you are changine the size of but technically you can just assign it to another ptr and then both the original and the new block will exist and both need to be freed in order to not have memory leaks, this is uncommon though but I guess is one way to copy memory from one to another, but is mroe cumbersome and confusing for others reading your code if ( int* reallocated_array = realloc(heap_array, ARRAY_SIZE * sizeof(int) + (3 * sizeof(int))) == NULL) { fprintf(stderr, "Memory re-allocation failed\n"); //old malloc is still find, this just doesnt create the new space if it fails, old malloc remains untouched } //attempt to print it out as if I did not truncate it with realloc for (int i = 0; i < ARRAY_SIZE * 2; ++i) { //Implementation defined behavior going past array could all be initialized to 0, could segfault for going out of bounds, or could just return garbage printf("%d ", reallocated_array[i]); } printf("\n"); free(reallocated_array); heap_array = NULL; free(heap_array); heap_array = NULL; free(heap_array); heap_array = NULL; //this line is just for educational purposes return 0; }
#include <stdio.h> #include <stdlib.h> #define ARR_SIZE 100 int main(void) { char array[ARR_SIZE]; while (1) { printf("Enter: "); fgets(array, ARR_SIZE, stdin); //safely reads up to 99 characters into buffer array //fgets(array, 101, stdin); //UNSAFE: might attempt to read and write past end of array fscanf(stdin, "%99[^\n]", array); //safely reads up to 99 characters into buffer array //fscanf(stdin, "%[^\n]", array); //UNSAFE: might attempt to read and write past end of array fread((void*) array, sizeof(char), ARR_SIZE - 1, stdin); array[ARR_SIZE - 1] = '\0'; //safely reads into buffer and null terminates the string //fread((void*) array, sizeof(char), ARR_SIZE + 1, stdin); //UNSAFE CAN READ PAST AND ATTEMPT TO STORE PAST BUFFER // UNSAFE: unlike example above because this does not null-terminate the array of chars and thus is not a string printf("%s",array); } return 0; }
#include <stdio.h> #include <string.h> #include <stdlib.h> int main(void) { char* buffer = (char*) malloc(298172 * sizeof(char)); char* buffer2 = (char*) malloc(298172 * sizeof(char)); FILE *my_fptr = fopen("file_operations_test.txt", "r+"); if (my_fptr == NULL) { fprintf(stderr, "ERROR: Failed to find and open file.\n"); } else { fread((void*) buffer, sizeof(char), 298170, my_fptr); char* location = strstr(buffer, "18"); memcpy(buffer2, buffer, location - buffer); strcat(buffer2, "2"); strcat(buffer2, buffer + (location - buffer + 2)); fseek(my_fptr,SEEK_SET, 0); fprintf(my_fptr,"%s", buffer2); // printf("buffer is: \n%s\n\nlocation of substring \"1\" is: %ld\n",buffer, location - buffer); } free(buffer); buffer = NULL; fclose(my_fptr); return 0; }
??= becomes # ??( becomes [ ??< becomes { ??/ becomes \ ??) becomes ] ??> becomes } ??’ becomes ˆ ??! becomes | ??- becomes ∼ <% becomes { %> becomes } <: becomes [ :> becomes ] %: becomes #