Last active
November 6, 2024 00:04
-
-
Save eatonphil/21b3d6569f24ad164365 to your computer and use it in GitHub Desktop.
Introduction to "Fun" C (using GCC)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This are a collection of examples for C 201. | |
* These combine concepts you may or may not be | |
* familiar with and are especially useful for | |
* students new to C. There is a lot of really | |
* cool stuff you can do in C without any cool | |
* languages. | |
* | |
* This is file in particular is an introduction | |
* to fun function usage in C. | |
*/ | |
#include <stdio.h> | |
int sum(int a, int b) { | |
return a + b; | |
} | |
int sub(int a, int b) { | |
return a - b; | |
} | |
// This function "get_operator" takes a *char expression | |
// and returns a function that takes two ints and returns | |
// an int. | |
int (*get_operator(char* expression)) (int, int) { | |
int i; | |
// char pointers are automatically given a final character '\0' | |
// to allow us to know when the char* ends. | |
for (i = 0; expression[i] != '\0'; i++) { | |
switch (expression[i]) { | |
case '+': | |
return sum; | |
case '-': | |
return sub; | |
} | |
} | |
} | |
void print_operator(char* expression) { | |
// get_operator will return a function that takes two ints | |
// and returns an int. | |
int (*operator)(int, int) = get_operator(expression); | |
// sum is automatically converted to a pointer, | |
// you could also say "operator == &sum", but that is longer. | |
if (operator == sum) { // comparing functions! | |
printf("Expression %s is a sum.\n", expression); | |
} else if (operator == sub) { // comparing functions again!! | |
printf("Expression %s is a sub.\n", expression); | |
} else { | |
printf("Expression %s has an unknown operation.\n", expression); | |
} | |
// Challenge: | |
// Instead of just printing out which operation it is, | |
// find the two operands and perform the operation on them. | |
// Then print the result of the expression instead. | |
} | |
int main() { | |
char* expression1 = "2 + 2"; | |
char* expression2 = "5 - 3"; | |
char* expression3 = "9 * 7"; | |
print_operator(expression1); | |
print_operator(expression2); | |
print_operator(expression3); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is an example of more complex function usage in C. | |
* Read structs.c before continuing. | |
*/ | |
#include <stdio.h> | |
// Good reference: | |
// http://www.dirac.org/linux/programming/tutorials/function_pointers/ | |
typedef struct { | |
int legs; | |
void (*sayName)(void); | |
} Animal; | |
void catSayName() { | |
printf("I am a cat.\n"); | |
} | |
void dogSayName() { | |
printf("I am a dog.\n"); | |
} | |
int sub(int a, int b) { | |
return a - b; | |
} | |
int sum(int a, int b) { | |
return a + b; | |
} | |
double sum_d(double a, double b) { return a + b; } // would fail if passed to operate: operate(sum_d, 1, 2) | |
int operate(int (*f)(int, int), int a, int b) { | |
return f(a, b); | |
} | |
void do_nothing(void) { | |
return; | |
} | |
int main() { | |
Animal cat; | |
cat.legs = 4; | |
cat.sayName = catSayName; | |
Animal cat1; | |
cat1.legs = 4; | |
cat1.sayName = catSayName; | |
Animal dog; | |
dog.legs = 3; | |
dog.sayName = dogSayName; | |
cat.sayName(); // I am a cat. | |
dog.sayName(); // I am a dog. | |
cat.sayLegs(cat.legs); | |
int my_sum = operate(sum, 1, 2); | |
printf("%d\n", my_sum); // Prints 3 | |
int my_sub = operate(sub, 11, 2); | |
printf("%d\n", my_sub); // Prints 9 | |
do_nothing(); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is a collection of pointer examples. | |
* It is a fun way to test yourself. I'm | |
* sorry I couldn't think of a better way | |
* to show the answers. | |
*/ | |
#include <stdio.h> | |
void print(int i) { | |
printf("%d\n", i); | |
} | |
int main() { | |
int* myInt; | |
int myIntsValue = 3; | |
myInt = &myIntsValue; // int* somePointer; *somePointer = myIntsValue; myInt = somePointer; | |
print(*myInt); // prints 3 | |
int mySecondInt = 2; | |
*myInt = mySecondInt; | |
print(*myInt); // prints 2 | |
print(mySecondInt); // prints 2 | |
print(myIntsValue); // prints 2 | |
myInt = &mySecondInt; // int* somePointer; *somePointer = mySecondInt; myInt = somePointer; | |
mySecondInt = 5; | |
print(*myInt); // prints 5 | |
myIntsValue = 7; | |
print(*myInt); // prints 5 | |
mySecondInt = myIntsValue; | |
print(*myInt); // prints 7 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is a continuation of (more complex) | |
* pointer examples. | |
*/ | |
#include <stdio.h> | |
void print(int i) { | |
printf("%d\n", i); | |
} | |
void swap1(int a, int b) { | |
int temp = b; | |
b = a; | |
a = temp; | |
} | |
void swap2(int* p_a, int* p_b) { | |
int temp = *p_b; | |
*p_b = *p_a; | |
*p_a = temp; | |
} | |
int main() { | |
int a = 1; | |
int b = 2; | |
swap1(a, b); | |
print(a); // prints 1 | |
print(b); // prints 2 | |
swap2(&a, &b); | |
print(a); // prints 2 | |
print(b); // prints 1 | |
int* c; | |
int* d; | |
c = &a; // c = some address... but *c = 2 | |
d = &b; // d = some address... but *d = 1 | |
swap1(*c, *d); | |
print(*c); // prints 2 | |
print(*d); // prints 1 | |
swap2(c, d); | |
print(*c); // prints 1 | |
print(*d); // prints 2 | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* This is a brief example of typedef-ing and structs in C. | |
*/ | |
typedef int Int; // int or Int | |
struct Person { | |
char* name; | |
Int age; | |
}; | |
typedef struct Person APerson; // struct Person or APerson | |
typedef struct Animal { | |
int legs; | |
} Animal; // struct Animal or Animal | |
typedef struct { | |
int mpg; | |
} Car; // cannot use struct Car, can only use Car... the struct is anonymous | |
int main() { | |
APerson person; // could use "struct Person person" | |
person.name = "Phil"; | |
person.age = 10; | |
Animal cat; // could use "struct Animal cat;" | |
cat.legs = 4; | |
Car car; // could not use "struct Car car;" because the struct was anonymous | |
car.mpg = 30; | |
} |
Wow, c is cool! thanks!
Good examples of function pointers. Saved.
thanks
Good examples! But there is no definition of 'sayLegs' function in functions2.c
Nice examples!
On line 24, it should be // and returns a pointer to a function that takes...
.
thanks, good example for function pointer
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Really nice writeup, thanks!