12.16 Points
Global Variables
- A variable declared outside all functions, at the top level, is global.
- A global variable can be read and modified by any function in the program.
- Here,
a is global, andb is local tomain(). - Global variables can be used to pass information between functions of a program.
- Their use is however strongly discouraged, as they lead to high coupling (dependency) between functions.
- Typically, it is significantly more convenient to communicate functions through arguments/parameters and return values.
#include <stdio.h>
int a = 33; // global variable
int main() {
int b = 1 + a;
a = a + 1;
printf("%d %d\n", a, b);
return 0;
}
Abstraction by Parameterization
- Abstraction is crucial for dealing with complexity in software development.
- Functions and procedures allow us to better decompose problems into subproblems, and programs into subprograms, exploiting a form of abstraction known as abstraction by specification.
- Each function hides its implementation details from its users/clients, which can use the function by just concentrating on what it does, rather than on how it does it.
- The effective definition of functions requires the use of abstraction by parameterization.
- Abstraction by parameterization abstracts from the concrete identity of the data a function operates on, replacing it by parameters.
- For better exploiting abstraction by parameterization, we need to be able to parameterize any kind of data, not limited to simple data types.
Arrays as Function Parameters: Example
- Programming languages generally allow us to define parameters of functions/procedures, even if these are of structured types.
- In C, in particular, we can have array parameters.
int sum(int array[], int size) {
int result = 0;
for (int i = 0; i < size; i++) {
result = result + array[i];
}
return result;
}
Arrays as Function Parameters 1/2
- The specific mechanism for array parameters in C is subtle.
- When an array is passed as an argument to a function, the address of the array is passed.
- It maintains the “pass by value” approach of C, but the address of the array is passed by value, not the whole array information.
- The array elements themselves are not copied.
- The function can still access the array elements with the
a[i]notation.
Arrays as Function Parameters 2/2
- In C, arrays are simply contiguous blocks of memory. A function cannot know the size of an array just from the array variable itself.
- Typically, when having array parameters in functions, the size of the arrays has to be passed as additional parameters.
Calling a Function with an Array Parameter 1/2
- Suppose
main() declares an arrayvof size 100. - The usual way to call
sum() frommain with arrayvto sum 100 elements is:
sum(v, 100);
- Note that we pass the name
v alone, without[]notation. - This is because we do not pass an element of
v (v[1]), we pass the address ofv.
Calling a function with an array parameter 2/2
- The size parameter that is typically defined together with an array parameter can be instantiated in different ways, giving alternative ways of calling functions on arrays in C.
- The following table illustrates some possibilities to call function
sum() frommain() with thevparameter:
| Call | Description |
|---|---|
sum(v, 100) |
v[0] + v[1] + ... + v[99] |
sum(v, 88) |
v[0] + v[1] + ... + v[87] |
sum(&v[7], k-7) |
v[7] + v[8] + ... + v[k-1] |
Const in array parameters
- While the array address is passed by value, the array itself can be considered to be passed “by reference”.
- Thus, one may (accidentally or not) modify the contents of an array parameter.
- The use of the type qualifier
"const"before a parameter in the parameter list can prevent the modification of the parameter. - For arrays, it prevents us from modifying the contents of a parameter array. For instance, this function copies n elements from
src[] intodst[]:
void copy(const int src[], int dst[], int n)
Strings
- Strings in C are just arrays of
charelements. - By convention, a string is terminated by the end-of-string sentinel
\0, or null character. The null character's decimal value is zero. - To be more explicit, we call such strings zero-terminated strings.
- Zero-terminated strings enable functions to take a string parameter without a size, and to process them until a zero is met.
- For instance:
printf("This is a quite long string and I can handle it");
printf("This one too.");
Example
int strlen(char s[]) {
int i = 0;
while (s[i] != '\0') {
i++;
}
return i;
}
String Literals
- String constants are written between double quotes.
- For example,
"abc" is a character array of size 4; the last element being the null character\0. -
String constants are different from character constants.
-
"a" and'a'are not the same. - Array
"a" has two elements, the first with value'a' and the second with value\0.
String Initialization
- Character arrays have an alternate notation:
char s[] = "abc";
is equivalent to:
char s[] = {'a', 'b', 'c', '\0'};
Example: Input String Stored in Array
-
gets() lets the user type a string in the standard input of the program, and stores it (as zero-terminated string) into the array given to it as parameter (str) -
gets()cannot know the size of str, so a long input string can go out of bounds! -
for "real" programs,
gets()is not recommended, the alternative is: -
fgets(str, 1000, stdin);
stdin means standard input,fgetswill ignore the character if the number is overflowed the size.
int main() {
char str[1000];
printf("Input your name:\n");
gets(str);
printf("Your name is: %s\n", str);
return 0;
}
Variable-Length Arrays
- Arrays can be created based on a parameter size.
- In this way, the actual size of the array will be determined at run time.
- The size of the array does not change during an execution, but for different executions we may have different sizes for the array.
Variable-Length Array Example
#include <stdio.h>
#include <assert.h>
int fib(int n) {
assert(n >= 0);
if (n == 0) {
return 1;
} else {
int fibs[n+1];
fibs[0] = 1;
fibs[1] = 1;
for (int i = 2; i <= n; i++) {
fibs[i] = fibs[i-1] + fibs[i-2];
}
return fibs[n];
}
}
int main() {
printf("fib(%d) is %d\n", 10, fib(10));
printf("fib(%d) is %d\n", 100, fib(100));
return 0;
}
Pointers, a short overview 1/2
- A variable is stored at a particular memory location, or address, in the computer.
- If
v is a variable, then&vis the location, or address, in memory of its stored value. - The declaration:
int *p orint * p
declares p to be of type pointer to int. It’s a variable that holds a memory address where an integer is stored.
- p = &i; means that we store in p the address of variable i.
Pointers, a short overview 2/2
- Operator
&(reference, direction) gets the address of some variable. - Operator
*(dereference, indirection) gets the value pointed by a pointer. - So,
(*p) evaluates to the value stored in variablei, assumingp has the memory address ofi.
int i = 5;
int *p = &i;
Then we have (*p) is equal to &i
Arguments of main()
-
argcprovides a count of the number of command line arguments.
argc--- argument count
- Second argument, argv, is an array of pointers to char, but think of it as an array of zero-terminated strings. These strings are the words that make up the command line.
argv--- argument value
- Now, our programs can read their command line parameters!
int main(int argc, char *argv[])
{
int i;
printf("argc = %d\n", argc);
for (i = 0; i < argc; ++i)
printf("argv[%d] = %s\n", i, argv[i]);
return 0;
}
- We can use
atoi(argv[1]) to get the integer from string. We need to import thestdlib.h
Also we can use atof(argv[2]) to get the float. Such as atol(argv[3]), atoll(argv[4])
In general means argument to (type)
- How to get
'c'character from argument of a string?
For example, argv[1] = "c", then we can argv[1][0] = 'c'
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
if(argc < 4) {
printf("Incorrect number of arguments\n");
return 1;
}
int firstNumber = atoi(argv[1]);
float secondNumber = atof(argv[2]);
char character = argv[3][0];
printf("Integer number %d \n Float number %f \n Character %c",
firstNumber, secondNumber, character);
return 0;
}