C Programing

0.0(0)
studied byStudied by 0 people
learnLearn
examPractice Test
spaced repetitionSpaced Repetition
heart puzzleMatch
flashcardsFlashcards
Card Sorting

1/40

encourage image

There's no tags or description

Looks like no tags are added yet.

Study Analytics
Name
Mastery
Learn
Test
Matching
Spaced

No study sessions yet.

41 Terms

1
New cards

C program structure

Preprocessor directives: Lines beginning with # used for including libraries or defining macros.

Function definitions: Including the main function and any other functions.

Statements and expressions: the actual code that performs operations.

2
New cards

What is C #include Preprocessor Directive?

Used to include the contents of a file within another file before the compilation begins. These header files usualy contain prototypes, macros and type definitions.

example:
#include <stdio.h>
or
#include “myheader.h”

3
New cards

How does #include work?

Preprocessing Stage: When the preprocessor encounters the include, it replaces that directive with the contents of the specified file. This happens before compilation.

Inclusion of Content: The compiler then processes this content as if it were part of the original source file, including prototypes, macro definitions, and type definitions.

Avoiding Multiple Inclusions: Since the included files are copied into the source file; we need to prevent including more than once, we use guards to do this.

4
New cards

How do we avoid Multiple Inclusions?

// checks if the file has not been defined
#ifndef MYHEADER_H
#define MYHEADER_H
// declarations
#endif

5
New cards

What is the “main” function?

Entry point of the program, when executed, main is the first function called.

It has two prototypes:
int main(int args, char* argv[]);
and
int main();

The first accepts command line arguements. In both cases, the function returns an int at the end of program execution. Returning a 0 means the program terminated successfully, any other indicates an error.

6
New cards

“Main” function example

#include <stdio.h>

int main() {
printf(“Hello World.\n”);

return 0;

}

7
New cards

What are escape sequences?

Escape sequences are a combination of a backslash (\) and another character.

\n moves the cursor to the begining of the next line.
\t moves the cursor to the next horizontal tab stop

\a produces an alert without changing the cursor position
\\ to input the backslash character in a string

\” to input the double quote character in a string

8
New cards

Variables

Must be declared before they are used, can be placed anywhere in the code before first use. C is case sensitive with variable names. They can be initialized at the same time.`

int index; // integers

char letter; // single chars

double distance // double precision floating point #

float temp; // single precision floating point #

9
New cards

Variable Scope and Lifetime

Global: declared outside any function or block, visible through the entire file.

Local: declared inside a function or block (eg. loops, conditional statements), limited to the function or block. only exists during the execution of the function or block, allocated when entered and deallocated when exited.

10
New cards

Data Types

int (Integer): 4 bytes (32 bits), represent whole numbers

char (Character): 1 byte (8 bits), represents a single character

float (single precision): 4 bytes (32 bits), represents real numbers with a fractional part

double (double precision): 8 bytes (64 bits), more precision than float.

11
New cards

Derived Data Types

void: absence of type, used for functions that do not return a value

array: a collection of elements of the same type
int numbers[5] = {1, 2, 3, 4, 5}

pointer: holds the memory address of another variable, typically 4 bytes on 32-bit system and 8 bytes on a 64bit system.
int value = 10;
int *ptr = &value;

signed and unsigned: modifiers that affect the range of values. Unsigned only allows positive numbers.
unsigned int positiveNumber = 10;

short and long: modifiers that adjust the size of the int type, short uses 2 bytes and long can use 8 bytes.

const keyword: defines a variable that cannot be changed after initialization.

12
New cards

What is a Macro?

The #define directive is used to define macros or constants at the preprocessing stage. I performs a search and replace in the code before the compilation begins.
#define NAME value
#define NUM_STUDENTS 500
does not occupy space in memory, just a literal with no type associated.

13
New cards

scanf function

Reads input from the standard input (keyboard), and stores the values in the provided variables. The format string controls how the input is parsed and interpreted
scanf(“control string”, &var1, &var2, …)

eg:
int marks;
float term;
scanf("%d:%f", &marks, &term);

char str[50];
scanf("%s", str);

any leftover characters or numbers not specified to match the type of the control string are still in the buffer.

14
New cards

printf function

outputs formatted data to the standard output (console). The format string specifies how the data should be formated and displayed.
printf(“control string”, var1, var2, …)

eg:
float flo = 3.14159;
printf("%f", flo);

%4d means field width of 4, right justified, padded with spaces

%4.1f means field width 4, 1 digit after the decimal point

%04d means field width of 4, padded with 0’s

(-) for left alignment

15
New cards

Control flow: Conditionals

if statement: checks whether condition is true or not.
else statement: if the condition in if is false, execute the code.
syntax:

if(<condition>) {
<code>
} else if(<another condition>) {

<code>

} else {
<code>
}

alternatively, switch case to select from mutually exclusive conditions:
syntax:

switch (<expression>) {

case const-expr: statements; break;
case const-expr: statements; break;

default: statements; break;

16
New cards

Control flow: Iteration

loops are used to repeat a block of code multiple times.

for loops used when number of iterations known.

while loops repeats while a condition is true.

do while loops guarantees one pass of the code block before checking the condition.
syntax:
for (i = 0; i < num; i++) {

<code>
}

while (!exitCondition) {
<code>
}

do {
<code>
} while (!exitCondition);

17
New cards

Logical operators

usually used in conditional statements
&& : logical AND
II : logical OR

! : logical NOT

relational operators:
== : equal
< : less than
> : greater than
!= : not equal
<= : less than or equal
>= : greater than or equal

18
New cards

Ternary operator

shortcut for an if-else statement:
<variable>= condition ? <if true code> : <if false code>;

19
New cards

Functions

The building blocks of code, used to break larger code into small pieces so that each can be maintained seperately, have reusable and readable code.
syntax:

<return type> functionName (arguments) {

}

the function declaration, known also as a function prototype, specifies the parameters without providing the implementation. It is best practice to include function prototypes at the start of the file.

20
New cards

Function Prototypes - Mixed Type Expressions

Arithmetic conversions in mixed-type expressions:
- if any operand is of type long double, all operands are converted to this type.
- next if any are of type double, all are converted to double.
- integer promotion ensures that smaller integer types (char and short) are promoted to int before evaluation

21
New cards

Arrays

fundemental data structure, used to store a collection of elements of the same type.

syntax:
int numbers[5];

int numbers[5] = {1, 2 ,3 ,4 ,5};

int numbers[] = {1, 2 ,3 ,4 ,5}; // size is inferred as 5

When you define an array in C, you reserve space for the array and its elements. the variable for the array itself is a pointer to the start of the array. (4 or 8 bytes, depending on architecture 32bit or 64bit)
it then allocates space for array elements equal to the number of elements times the size of one element.

In memory, arrays are contiguous blocks.

22
New cards

Variable Length Arrays (VLAs)

arrays are declared using a variable to specify the size of the array. syntax:
int n = 5;
int arr[n];

they can also be used as function parameters:
void processArray(int size, int arr[size])
{ // Process array arr with size
}
int main() {
int n = 10;
int arr[n];
processArray(n, arr);
return 0;
}

They are dynamically sized, and determined at runtime. They are memory efficient, and they are flexible.

VLAs only appear in C99 standard or later. they are allocated on the stack, which can lead to stack overflow if the arrays are too large. The sizes aren’t checked at compile time, which means errors related to out-of-bounds access are tricky.

23
New cards

Char Array

Character arrays can be initialized with individual character constants:
char string1[] = {'f', 'i', 'r', 's', 't', '\0'}; // Equivalent to "first“
char string1[] = "first"; // Automatically adds '\0' at the end

A string is just an array of characters.

24
New cards

fgets (handling special characters)

scanf stops reading at whitespace (space, tab, newline). fgets is used to read from a file or stdin safely. syntax:
char *fgets(char *str, int n, FILE *stream);

*str: pointer to the character array where the string will be stored

n: maximum number of characters to read, including null terminator. (n-1 characters read)

stream: the input file stream to read from, usually stdin

returns the str pointer if a string is successfully read. returns NULL otherwise.

25
New cards

Multi-Dimensional Arrays

int matrix[2][3] = { // 2 rows and 3 columns
{1, 2, 3},
{4, 5, 6}
};
int value = matrix[1][2]; // Gets the value 6

26
New cards

Stack

The stack is used for static memory allocation, which includes function call management, local variables and function parameters.

Memory is allocated and deallocated automatically as functions are called and return.

Fixed size, determined by system or compiler settings. The memory is automatically managed.

Fast access (push/pop)

Limitation is that the stack has a limited size, and deep recursion or large local variables can lead to stack overflow.

27
New cards

Heap

Used for dynamic memory allocation, which allows you to allocate memory during runtime. Memory in C on the heap must be explicitly allocated and deallocated using functions like malloc, calloc, realloc and free.

Failure to free allocated memory leads to memory leaks.

Slower Access

Memory allocated on the heap is accessible from anywhere in the program provided you have a pointer to it.

int *ptr = (int *)malloc(sizeof(int)); // Allocate memory on the heap
if (ptr != NULL)
{
*ptr = 10; // Use the allocated memory
free(ptr); // Free the allocated memory
}

28
New cards

Stack Frames

The Stack is last in, first out (LIFO).

Each time a function is called, a stack frame is created and pushed onto the stack. the stack frame contains return address and local variables.

When a function completes, its frame is popped off, and control transfers to the address stored in that frame.

The stack has a finite size, meaning there is a limit to the number of how many stack frames can exist simultaneously.

29
New cards

Heap Allocation

As you implicitly or explicitly allocate memory, you are given the pointer to the best chunk (closest in size), and the heap table is updated.

If the amount needed matches an existing free chunk, it is returned to you and the chunk is marked as in use.

Otherwise, a bit of an existing free chunk is split off as a new chunk, this new chunk’s address is returned to you and is marked in use.

30
New cards

Heap Freeing (Deallocation)

When you free the allocated memory, the chunk in the heap table is marked as free.

Then if the location is adjacent to another free chunk, the location and size of both chunks are merged to create one large chunk. If there is no adjacent free chunk, it is left as is.

There is no Java-style garbage collection.

31
New cards

Stack Pitfalls

Data overruns are a risk. C will let you write data beyond the end of any array. You can then overwrite the return address of a function, which is a stack clobber error.

Stack overflow is a possibility. Endless recursion will consume all memory, or cause the stack pointer to enter an allocated chunk.

Stack/Heap collision, since they start on two ends of memory addresses.

32
New cards

Heap Pitfalls

You are responsible for freeing all the memory allocated. Memory leaks are a problem, requiring discipline and comments.

Fragmentation is a possibility. You can riddle the heap with alternating sequences of free and in-use chunks, so even though the sum of free chunks is enough, there are not enough adjacent free chunks.

Data overruns are a risk, C will let you write data beyond the end of your allocated chunk, corrupting data in the adjacent chunk. Very hard to debug.

33
New cards

malloc()

allocates a specified number of bytes of memory and returns a pointer to the beginning of the block, or Null if the allocation fails.
the parameter: size - number of bytes to allocate
returns: a pointer to the allocated memory or NULL

int *arr = (int *)malloc(5 * sizeof(int)); //Allocate memory for 5 integers
if (arr == NULL)
{
// Handle memory allocation failure
}

34
New cards

calloc()

allocates a specified number of bytes in memory and returns a pointer to the begining of the block, also initializes all memory elements to a value of zero.
the parameters: num - number of elements to allocate
size - size of each element in bytes

returns: a pointer to the allocated memory or NULL

int *arr = (int *)calloc(5, sizeof(int));
// Allocate memory for 5 integers initialized to 0
if (arr == NULL)
{
// Handle memory allocation failure
}

35
New cards

realloc()

changes the size of a previously allocated memory block.
parameters: *ptr - pointer to the previously allocated memory block
size - new size in bytes
return: a pointer to the newly allocated memory or NULL

arr = (int *)realloc(arr, 10 * sizeof(int)); /*Resize memory to hold 10 integers*/
if (arr == NULL) {
	/*Handle memory reallocation failure*/
}

36
New cards

free()

Deallocates memory that was allocated.
parameters: *ptr - pointer to the memory to be freed
returns: nothing

free(arr);
arr = NULL; // set the pointer to NULL since there is no memory here anymore

37
New cards

Pointers

Pointers are a powerful feature that allows you to directly manipulate memory addresses. A pointer is a variable that stores the address of another variable. the type of pointer corresponds to the type of variable it points to.

To declare a pointer, use an asterisk (*).
int *ptr; // pointer to an int

You can initialize a pointer to point to a variable, (&) returns the memory address of a variable:
int var = 5;
int *ptr = &var;

Derefferencing, you can access the value stored in the address of the pointer by dereferrencing the pointer with an asterisk:
int value = *ptr; // value is now 5

38
New cards

Pointer Arithmetic

You can perform arithmetic on pointers. for example if ptr points to an integer, incrementing ptr will move it to point to the next integer in memory.

You can have NULL pointers (not assigned an address), best practice to assign any freed or not immediately assigned pointers to NULL.

You can have pointers to pointers, and const pointers.

39
New cards

Pointers vs Arrays

Both pointers and arrays can be used to access elements in memory. however arrays cannot be incremented or decremented.

An array is of fixed size at compile time, but a pointer can point to any memory address and can be reassigned.

The distinction between array and pointer is a semantic one, and pointers can be used to represent arrays.

40
New cards

Passing by Reference

Passing memory location between functions removes the need to maintain multiple copies of the same data, and allows it to be manipulated within other functions.

passing by reference can improve performance for large data structures, copying large arrays is time consuming, while passing a pointer is constant time O(1).

You can directly modify data of a passed pointer, meaning you don’t need to return values or copy data back.

41
New cards

Arrays of Pointers