Skip to content

Instantly share code, notes, and snippets.

@datduyng
Forked from cbourke/functions-H.md
Created October 12, 2018 05:08
Show Gist options
  • Select an option

  • Save datduyng/be26ad321c4e2fda8f43914c9bd71c10 to your computer and use it in GitHub Desktop.

Select an option

Save datduyng/be26ad321c4e2fda8f43914c9bd71c10 to your computer and use it in GitHub Desktop.
auto-posted gist

CSCE 155H - Computer Science I Honors

Functions & Methods

  • A function is a reusable unit of code that may take input(s) and may produce an output
  • Already familiar with functions: main(), printf(), sqrt(), etc.
  • Functions facilitate code reuse, you don't have to copy-pasta the same code over and over
  • Procedural abstraction: functions allow us to ignore the small details of how a certain block of code or algorithm works
  • Functions encapsulate functionality into reusable abstract code blocks
  • Standard libraries and functions have a lot of design, optimization, testing, debugging, etc. behind them, USE them
  • The first question you should ask in problems solving is "is this problem already solved?" that is, does a function already exist to solve my problem?

Functions in C

  • As with variables, functions must be declared before they can be used
  • IN C, you "declare" a function using a prototype
  • IN a prototype, you declare a function's signature
    • The name of the function (its "identifier")
    • a list of its parameters (or "arguments", ie its inputs)
    • the return type: the type of variable value that it returns
/**
 * This function computes the Euclidean distance between
 * two points defined by (x1, y1) and (x2, y2)
 */
double euclideanDistance(double x1, double y1, double x2, double y2);
  • Syntax notes: a prototype ends with a semicolon!
  • In C, comments are generally attached to the prototype, not the definition; DRY = Don't Repeat Yourself
  • Later in the code, you provide a function definition: the code that actually executes when you "call" or "invoke" the function
  • It contains the same signature, but instead of a semicolon, has a body denoted with curly brackets
double euclideanDistance(double x1, double y1, double x2, double y2) {
  return sqrt(pow(x1 - x2, 2) + pow(y1 - y2, 2));

}
  • Every function in C should be documented with doc-style comments on the prototype, not the definition
  • In the original version, we declared a variable called result
  • Such a variable is called local: it exists only within the function (ie its scope is the function itself)
  • Likewise the 4 parameter variables are also local to the function
  • In general you can declare as many local variables as you want

Methods in Java

  • In Java, functions are part of classes so we call them "methods"
  • There are no prototypes in Java, only definitions
  • You place methods within a class and they "belong" to the class
  • For now, all our methods will be static: the belong to the class not to instances of the class
public class DistanceUtils {

  public static double euclideanDistance(double x1, double y1, double x2, double y2) {
    return Math.sqrt(Math.pow(x1 - x2, 2) + Math.pow(y1 - y2, 2));
  }
}
  • To invoke or call a static method in Java use the class name + a period and provide the inputs
  • Example: DistanceUtils.euclideanDistance(0, 0, 10, 10)

Observe the differences:

  • Each method belongs to a class, in this case, DistanceUtils
  • The public keyword makes the method available to any piece of code
    • private would make it so only the class itself can "see" the method
    • protected would make it so only the class and its subclasses can "see"
    • The lack of a keyword modifier means it is "package protected": any class in the same package can "see" the method
  • The static keyword makes it so that the method belongs to the class itself and not to instances of the class

Other Issues

  • New keyword: void
    • A function that does not return a value is a "void" function and you use the keyword void to indicate its return type
    • A function that does not take any input (ie no parameters) can have a "void" parameter: void foo(void);
    • Alternatively (and arguably better practice): leave it blank void foo()

Function Overloading

  • Recall how to compute the absolute value in Java: Math.abs(); this works for all numerical types (double, int, etc.)
  • In C, there are several functions, one for each type of variable: fabs() is for floating point numbers, abs() is for int types, etc.
  • Java only has "one" absolute value function that can be used for any type of number, but C has to have several all with different names
  • Java supports function overloading: you can have multiple versions of the same function with the same name but with different parameter types
  • C does NOT support function overloading, meaning we have to name each version of the absolute value function a different name!
  • You can easily "pollute the name space" by creating too many functions with different names; since you can only use a name once, once a function is defined, then no other function can use that name!

How do functions actually work?

  • Motivating example: let's write a function to swap two values
  • Each time a function is called, a new stack frame is created which stores the function's local variables and parameters
  • The parameters are separate variables than those in the original function,
  • Only the values of the variables are passed to a function, not the variables themselves, ie COPIES of their values are passed
  • Changes to the copies have no effect in the original "calling function"
  • Therefore swapping two values using "pass by value" is impossible
  • In C, you can "solve" this problem by using pointers and pass-by-reference
  • In Java, all variables are pass by value, there is NO pass by reference

Modularity

  • IN both languages, code can quickly become complex with dozens or hundreds or thousands of different functions
  • You need a way to organize code when it gets too big
  • IN Java: you generally place related functions into classes
  • Organize classes into packages: a package is an organized hierarchy of folders (or directories)
  • Example: package unl.cse is a package such that code is located in a directory called cse which is a subdirectory of a directory called unl

In C

  • In C, functions are separated out into separate files
  • A header file contains all the prototypes and documentation
  • A source file contains all the function definitions
  • In general, header files end with a .h and source files end with a .c

Demonstration: write a general "distance library" of distance functions in separate header/source files

  1. You place prototypes AND documentation into a header file, distance.h
  2. You place function definitions into a source file, distance.c
    • You use #include "distance.h" in the source file to include the prototypes
  3. In a separate driver source file you have:
    • Another #include "distance.h"
    • The main function and
    • You can now use your library functions
  4. To compile (but not link) your library, use the -c flag: gcc -c distance.c which produces an object file, distance.o
  5. To compile the driver program, use gcc distance.o distanceDriver.c produces the a.out executable
  • IN general, you would want to create a makefile to specify how more complex projects are built

  • How to use makefiles: read a tutorial!

  • Java: you would use Ant or Maven or JenkinsCI

Pointers in C

  • Every piece of data in a computer is stored in memory
  • Memory consists of both an address (location) and contents: the data actually stored at a memory address
  • In C, you can create a pointer variable which represents not the contents of memory, but hte address itself
  • To create a pointer variable use the star, *
int a = 10; //normal variable
int *ptrA; //pointer variable
  • ptrA is a pointer variable that can point to any memory location that stores an integer
  • In general, it is best practice to initialize your pointer variables
    • If you want them to point to something right away, do it.
    • If you don't know right away what you want it to point to, then point it to NULL (case sensitive, all upper case in C)
int *ptrA = NULL;

//you can then make null pointer checks:
if(ptrA == NULL) {
  printf("uninitialized pointer!\n");
}
  • How can we make a pointer point to an actual memory address?
  • To get the memory of any regular variable, use &
int a = 10;
int *ptrA = &a; //makes ptrA point to A

//another example: make a double pointer
double b = 3.14;
double ptrB = NULL;

ptrB = &b;

//wrong ways:
ptrB = b; //this sets it to some other memory address that may not belong to our program
ptrB = -10;//this set it to a nonexistent memory address
  • How do we manipulate the contents of memory using pointers?
  • You can set what a pointer points to, but to change the contents of a memory location, you need to change the pointer into a "regular variable"
  • You can use the dereferencing operator to change a pointer into a regular variable
  • The dereferencing operator is simply the asterisk (star): *
int a = 42;
int *ptrA = &a;

int c = 10 + a; //value of 52
//doing it via its pointer:
c = 10 + *ptrA; //*ptrA makes ptrA into a regular old variable, accessing its contents, also has a value of 52

//You can also indirectly modify the contents via a pointer:
*ptrA = 35;

Pointers in Java?

  • There are no direct pointers in Java
  • However, Java does have references
int a = 10; //this is a primitive variable type,
//no pointer access, there is *no* way to get its memory location

//the following are both objects and their variables
//s, x are references!
String s = "Hello";
String t = "Goodbye";
Integer x = 10;

String u = s;
s = "hello";
System.out.println(s);
System.out.println(u);
  • Most built-in types are immutable (String, Double, Integer): once created, their contents cannot be changed
  • In general, immutability is a Very Good Thing: provides inherent thread safety

Review

  • Recall: you used scanf("%lf", &b) to read in data from the standard input
  • That ampersand is passing b by reference!
  • Passing by reference: passes the memory location of a variable instead
  • A memory location is kind of a shared resource or "bucket" that both functions can access and manipulate
  • If you only passed by value, then the function would only ever be able to return a single value and would never be able to make changes to your variables

Summary

  • In C, you can change a regular variable into a reference (a pointer or memory location) using the referencing operator, &
  • If you have a pointer variable, you can dereference it using the * (star or dereferencing operator)
  • Pointers allow you to pass by reference so that functions can make changes to variables that are "seen" or "realized" in the calling function
  • Passing by reference also allows you to "return" multiple values














Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment