Viele Eigenschaften der Programmiersprache C basieren aufgrund der Nähe zu Assembly. Siehe auch C++/C#.
// testValue unsigned long long testValue = 0xFFFFFFFFFFFFFFFF; // 18446744073709551615 // 1 byte -> [0-255] or [0x00-0xFF] unsigned char numberChar = testValue; // 255 // 2 bytes -> [0-65535] or [0x0000-0xFFFF] unsigned short numberShort = testValue; // 65535 // 4 bytes -> [0-4294967295] or [0x00000000-0xFFFFFFFF] unsigned int numberInt = testValue; // 4294967295 // 4 bytes -> [0-4294967295] or [0x00000000-0xFFFFFFFF] unsigned long numberLong = testvalue; // 8 bytes -> [0-18446744073709551615] or [0x0000000000000000-0xFFFFFFFFFFFFFFFF] unsigned long long numberLongLong = testValue; // 18446744073709551615 printf("%u %d %u %lu %llu", numberChar, numberShort, numberInt, numberLong, numberLongLong);
#include <string.h> int main() { char buf[] = "Hello world, how are you?"; char *token = strtok(buf, " "); while(token != NULL) { printf("token: %s\n", token); token = strtok(NULL, " "); } }
Nested strtok_r: https://stackoverflow.com/questions/4693884/nested-strtok-function-problem-in-c
// Eine statische Variable innerhalb einer Funktion behält ihren Wert auch zwischen mehreren Aufrufen. void foo() { int a = 10; static int sa = 10; a += 5; sa += 5; printf("a = %d, sa = %d\n", a, sa); } int main() { int i; for (i = 0; i < 10; ++i) foo(); }
Siehe Pointer in C.
int array[5]; // Declares 5 contiguous integers int *ptr = array; // Arrays can be used as pointers ptr[0] = 1; // Pointers can be indexed with array syntax *(array + 1) = 2; // Arrays can be dereferenced with pointer syntax *(1 + array) = 3; // Pointer addition is commutative 2[array] = 4; // Subscript operator is commutative char a, b; // 2 chars = 2 bytes char *zeiger; // einen (char) zeiger zeiger = &a; // zeiger beinhaltet adresse von a *zeiger = 'A'; // schreibe ein 'A' an die im Zeiger gespeicherte Adresse von a printf("Kapitel %c\n", a); zeiger = &b; // zeiger beinhaltet adresse von b *zeiger = 'B'; // schreibe ein 'B' an die im Zeiger gespeicherte Adresse von b printf("Kapitel %c\n", b); // Pointer auf eine Funktion void func(int *i) { (*i)++; // *i++ geht nicht! Siehe Pointer Arithmetik } int main() { void (*func_ptr)(int*) = &func; int i = 0; (*func_ptr)(&i); printf("%d", i); }
// pass a pointer void modify(char *s){ s[0] = 'g'; } int main(){ char name[] = "New Holland"; char *p_name = name; modify(p_name); printf("%s\n", name); }
// pass the address of a pointer void modify(char **s){ char *new_name = "Old Holland"; *s = new_name; } int main(){ char name[] = "New Holland"; char *p_name = name; modify(&p_name); printf("%s\n", name); }
In compiled code there are several segments.
Every segment has a read only region where constants are stored. The compiler - and only the compiler - has to decide in which segment a variable get stored. And then, if the variable is a const it is stored in the r/o region of that specific segment.
#include <stdio.h> int main() { const int a = 10; int b = 20; const int *ptr = &a; printf("ptr: %d\n", *ptr); // error!!! *ptr = b; ptr = &b; printf("ptr: %d\n", *ptr); }
See also constants in CPP
void print(int n) { for (int i = 0; i < 8; i++) { printf("%d", !!((n << i) & 0x80)); } } int main() { unsigned int a = 44; /* 0010 1100 */ unsigned int b = 13; /* 0000 1101 */ print(a); printf(" => a\n"); print(b); printf(" => b\n--------\n"); int c = 0; c = a & b; print(c); printf(" => a & b\n"); c = a | b; print(c); printf(" => a | b\n"); c = a ^ b; print(c); printf(" => a ^ b\n"); c = ~a; print(c); printf(" => ~a\n"); c = a << 2; print(c); printf(" => a << 2\n"); c = a >> 2; print(c); printf(" => a >> 2"); }
& (AND) 1 & 1 == 1 1 & 0 == 0 0 & 1 == 0 0 & 0 == 0 00110010 - b & 00010000 - & 0x10 ---------- 00010000 - result | (OR) 1 | 1 == 1 1 | 0 == 1 0 | 1 == 1 0 | 0 == 0 00110010 - b | 00000100 - | 0x04 ---------- 00110110 - result ^ (XOR) 1 ^ 1 == 0 1 ^ 0 == 1 0 ^ 1 == 1 0 ^ 0 == 0 00110010 - b ^ 00011000 - ^ 0x18 ---------- 00101010 - result 00101010 - b ^ 00011000 - ^ 0x18 ---------- 00110010 - result ~ (Inversion, One complement) 00000011 - 0x03 11111100 - ~0x03 b << >> (Bit shifting) 00001100 - b 00110000 - b << 2 00000011 - b >> 2
Initialisieren
int main() { char str[20]; // Setzen aller Elemente des Arrays auf 'A' memset(str, 'A', sizeof(str)); printf("Initialized string: %s\n", str); return 0; }
Kopieren
int main() { char source[] = "Hello, World!"; char destination[20]; // Kopieren des Inhalts von source nach destination memcpy(destination, source, sizeof(source)); printf("Copied string: %s\n", destination); return 0; }
Vergleichen
int main() { char str1[] = "abc"; char str2[] = "abd"; // Vergleichen der beiden Strings int result = memcmp(str1, str2, sizeof(str1)); if (result == 0) { printf("Strings are equal.\n"); } else if (result < 0) { printf("String 1 is less than String 2.\n"); } else { printf("String 1 is greater than String 2.\n"); } return 0; }
malloc
and calloc
are almost the same except calloc
zerores out the block. malloc takes only the size as arg, calloc
need size and type. realloc
is king.
int main() { char *ptr = (char *)malloc(1024 * sizeof(char)); char buf1[1024] = {'a'}; strcat(ptr, buf1); ptr = realloc(ptr, 1024 * sizeof(char)); char buf2[1024] = {'B'}; strcat(ptr, buf2); printf("%s", ptr); free(ptr); }
#include <stdio.h> #include <string.h> #define SIZE 64 unsigned char memory[SIZE]; void print_memory() { printf("\n\t00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15"); for(int i = 0; i < SIZE; i++) { if(i % 16 == 0) printf("\n%04d:\t", i); printf("%02x ", memory[i]); } printf("\n"); } int main() { int offset = 0; memset(memory, SIZE, 0); char str[] = "Hello world"; memcpy(memory + offset, &str, strlen(str)); offset += strlen(str); print_memory(); float f = 3.14159f; memcpy(memory + offset, &f, sizeof(float)); //offset += sizeof(float); print_memory(); float tmp; memcpy(&tmp, &memory[offset], sizeof(float)); printf("%f", tmp); return 1; }
FILE *f; f = fopen("test.txt", "w"); char msg[] = "Hello world"; fwrite(msg, sizeof(msg), 1, f); fclose(f); f = fopen("test.txt", "r"); fseek(f, 0L, SEEK_END); int len = ftell(f); rewind(f); char c, buffer[len]; int i = 0; while( fread(&c, sizeof(char), 1, f) > 0 ) buffer[i++] = c; fclose(f); buffer[i] = '\0'; printf("%s", buffer); f = fopen("test.txt", "r"); char ch; while((ch = fgetc(f)) != EOF) printf("%c", ch); fclose(f); f = fopen("test.txt", "r"); char *line = NULL, read; size_t len = 0; while((read = getline(&line, &len, f)) > -1) printf("(%d) %s", read, line); std::ifstream f("test.txt"); std::string data, line; while(std::getline(f, line)) data += line; std::cout << data;
Read 4 chars as a single int
FILE *f = fopen("test.txt", "rw"); char msg[] = {0x41,0x42,0x43,0x44}; fwrite(&msg, 1, sizeof(char), f); int *buffer; fread(&buffer, sizeof(int), 1, f); fclose(f); printf("%d", buffer); // 0x41424344 = 1145258561
Piping in windows
#include <stdio.h> #include <stdlib.h> int main(void){ char psBuffer[128]; FILE *pPipe; if((pPipe = _popen("curl https://orf1.mdn.ors.at/out/u/orf1/q4a/manifest.m3u8", "rt")) == NULL ) exit(1); while(fgets(psBuffer, 128, pPipe)) { printf(psBuffer); } if (feof( pPipe)) printf("\nreturn %d\n", _pclose(pPipe)); else printf( "Failed\n"); }
#include <stdio.h> int main() { // Erstellen eines Arrays mit 5 Elementen vom Typ int int array[5] = {1, 2, 3, 4, 5}; // Zugriff auf Elemente des Arrays printf("Element 0: %d\n", array[0]); printf("Element 3: %d\n", array[3]); return 0; }
struct Data { int i; float f; char *str; }; int main( ) { // like this struct Data data = {10, 2.5}; // or like this struct Data data; data.i = 10; data.f = 2.5; data.str = "Hello world"; printf( "data.i : %d\n", data.i); printf( "data.f : %f\n", data.f); printf( "data.str : %s\n", data.str); }
Recursive Structure
typedef struct Node { char *value; struct Node* left; struct Node* right; } Node;
Structure in anderer Structure
struct Details { char *name; }; struct Entry { int id; struct Details details; }; int main() { struct Entry entry = {1, "Manuel"}; printf("id: %d\n", entry.id); printf("name: %s\n", entry.details.name); }
Structures mit void* Pointern
typedef void (*Callback)(); struct Table { int id; char *type; void *val; Callback callback; }; void myFunction(const char *s) { printf("%s", s); } int main() { struct Table *t = malloc(sizeof(struct Table)); t->id = 1; t->type = "string"; char s[] = "Hello world, heheh"; t->val = &s; t->callback = myFunction; t->callback(t->val); }
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <stdbool.h> struct node { int data; int key; char *c; struct node *next; }; struct node *head = NULL; struct node *current = NULL; //display the list void printList() { struct node *ptr = head; printf("\n[ "); //start from the beginning while(ptr != NULL) { printf("(%d,%d) ",ptr->key,ptr->data); ptr = ptr->next; } printf(" ]"); } //insert link at the first location void insertFirst(int key, int data) { //create a link struct node *link = (struct node*) malloc(sizeof(struct node)); link->key = key; link->data = data; //point it to old first node link->next = head; //point first to new first node head = link; } //delete first item struct node* deleteFirst() { //save reference to first link struct node *tempLink = head; //mark next to first link as first head = head->next; //return the deleted link return tempLink; } //is list empty bool isEmpty() { return head == NULL; } int length() { int length = 0; struct node *current; for(current = head; current != NULL; current = current->next) { length++; } return length; } //find a link with given key struct node* find(int key) { //start from the first link struct node* current = head; //if list is empty if(head == NULL) { return NULL; } //navigate through list while(current->key != key) { //if it is last node if(current->next == NULL) { return NULL; } else { //go to next link current = current->next; } } //if data found, return the current Link return current; } //delete a link with given key struct node* delete(int key) { //start from the first link struct node* current = head; struct node* previous = NULL; //if list is empty if(head == NULL) { return NULL; } //navigate through list while(current->key != key) { //if it is last node if(current->next == NULL) { return NULL; } else { //store reference to current link previous = current; //move to next link current = current->next; } } //found a match, update the link if(current == head) { //change first to point to next link head = head->next; } else { //bypass the current link previous->next = current->next; } return current; } void sort() { int i, j, k, tempKey, tempData; struct node *current; struct node *next; int size = length(); k = size ; for ( i = 0 ; i < size - 1 ; i++, k-- ) { current = head; next = head->next; for ( j = 1 ; j < k ; j++ ) { if ( current->data > next->data ) { tempData = current->data; current->data = next->data; next->data = tempData; tempKey = current->key; current->key = next->key; next->key = tempKey; } current = current->next; next = next->next; } } } void reverse(struct node** head_ref) { struct node* prev = NULL; struct node* current = *head_ref; struct node* next; while (current != NULL) { next = current->next; current->next = prev; prev = current; current = next; } *head_ref = prev; } void main() { insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("Original List: "); //print list printList(); while(!isEmpty()) { struct node *temp = deleteFirst(); printf("\nDeleted value:"); printf("(%d,%d) ",temp->key,temp->data); } printf("\nList after deleting all items: "); printList(); insertFirst(1,10); insertFirst(2,20); insertFirst(3,30); insertFirst(4,1); insertFirst(5,40); insertFirst(6,56); printf("\nRestored List: "); printList(); printf("\n"); struct node *foundLink = find(4); if(foundLink != NULL) { printf("Element found: "); printf("(%d,%d) ",foundLink->key,foundLink->data); printf("\n"); } else { printf("Element not found."); } delete(4); printf("List after deleting an item: "); printList(); printf("\n"); foundLink = find(4); if(foundLink != NULL) { printf("Element found: "); printf("(%d,%d) ",foundLink->key,foundLink->data); printf("\n"); } else { printf("Element not found."); } printf("\n"); sort(); printf("List after sorting the data: "); printList(); reverse(&head); printf("\nList after reversing the data: "); printList(); }
#include <stdio.h> #include <stdlib.h> #define SIZE 10 struct Node { int key; int value; struct Node* next; }; struct Node* hashTable[SIZE]; int hashFunction(int key) { return key % SIZE; } void insert(int key, int value) { struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); newNode->key = key; newNode->value = value; newNode->next = NULL; int index = hashFunction(key); if (hashTable[index] == NULL) { hashTable[index] = newNode; } else { struct Node* current = hashTable[index]; while (current->next != NULL) { current = current->next; } current->next = newNode; } } int search(int key) { int index = hashFunction(key); struct Node* current = hashTable[index]; while (current != NULL) { if (current->key == key) { return current->value; } current = current->next; } return -1; } int main() { // Initialisierung der Hash-Tabelle for (int i = 0; i < SIZE; i++) { hashTable[i] = NULL; } // Einfügen von Elementen insert(1, 10); insert(2, 20); insert(11, 30); // Suche nach einem Schlüssel int value = search(2); if (value != -1) { printf("Value found: %d\n", value); } else { printf("Value not found.\n"); } return 0; }
#include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 struct Stack { int items[MAX_SIZE]; int top; }; void initialize(struct Stack* stack) { stack->top = -1; } int isEmpty(struct Stack* stack) { return stack->top == -1; } int isFull(struct Stack* stack) { return stack->top == MAX_SIZE - 1; } void push(struct Stack* stack, int item) { if (isFull(stack)) { printf("Stack overflow!\n"); return; } stack->items[++stack->top] = item; } int pop(struct Stack* stack) { if (isEmpty(stack)) { printf("Stack underflow!\n"); return -1; } return stack->items[stack->top--]; } int main() { struct Stack stack; initialize(&stack); push(&stack, 1); push(&stack, 2); push(&stack, 3); printf("Popped: %d\n", pop(&stack)); printf("Popped: %d\n", pop(&stack)); printf("Popped: %d\n", pop(&stack)); return 0; }
#include <stdio.h> #include <stdlib.h> #define MAX_SIZE 100 struct Queue { int items[MAX_SIZE]; int front; int rear; }; void initialize(struct Queue* queue) { queue->front = -1; queue->rear = -1; } int isEmpty(struct Queue* queue) { return queue->front == -1; } int isFull(struct Queue* queue) { return (queue->rear + 1) % MAX_SIZE == queue->front; } void enqueue(struct Queue* queue, int item) { if (isFull(queue)) { printf("Queue overflow!\n"); return; } if (isEmpty(queue)) { queue->front = 0; queue->rear = 0; } else { queue->rear = (queue->rear + 1) % MAX_SIZE; } queue->items[queue->rear] = item; } int dequeue(struct Queue* queue) { if (isEmpty(queue)) { printf("Queue underflow!\n"); return -1; } int item = queue->items[queue->front]; if (queue->front == queue->rear) { queue->front = -1; queue->rear = -1; } else { queue->front = (queue->front + 1) % MAX_SIZE; } return item; } int main() { struct Queue queue; initialize(&queue); enqueue(&queue, 1); enqueue(&queue, 2); enqueue(&queue, 3); printf("Dequeued: %d\n", dequeue(&queue)); printf("Dequeued: %d\n", dequeue(&queue)); printf("Dequeued: %d\n", dequeue(&queue)); return 0; }
By default an (ANSI C) integer is signed.
int a = 5; int b = -10; (a>b) ? puts("a>b") : puts("-"); unsigned int c = 5; int d = -10; (c>d) ? puts("c>d") : puts("-"); printf("%08x %08x %08x %08x", a,b,c,d);
#define f(a,b) a##b // strcat #define h(a) g(a) // exec #define g(a) #a // stringify int main() { printf("%s\n",h(f(1,2))); printf("%s\n",g(f(1,2))); return 0; }
Gilt auch für CPP. Compileranweisungen vor dem eigentlichen Kompilierung ausführen. Dabei werden z.B makros durch den eigentlichen Code ersetzt.
Das folgende Programm mit gcc -E
vorkompiliert
#define DEFINE_LL_NODE(CONCRETE_TYPE) \ struct node_of_ ## CONCRETE_TYPE { \ CONCRETE_TYPE data; struct node_of_ ## CONCRETE_TYPE *next; \ }; \ #define DECLARE_LL_NODE(CONCRETE_TYPE, VARIABLE_NAME) \ struct node_of_ ## CONCRETE_TYPE VARIABLE_NAME; /* Declarations for types int and char */ DEFINE_LL_NODE(int) DEFINE_LL_NODE(char) int main (void) { /* Declaration of instances of each type. */ DECLARE_LL_NODE (int, foo) DECLARE_LL_NODE (char, bar) /* And you can then use these instances. */ foo.data = 1; foo.next = NULL; bar.data = 'c'; bar.next = NULL; }
erzeugt ein Object file das so aussieht.
# 1 "main.c" # 1 "<built-in>" # 1 "<command-line>" # 1 "main.c" # 10 "main.c" struct node_of_int { int data; struct node_of_int *next; }; struct node_of_char { char data; struct node_of_char *next; }; int main (void) { struct node_of_int foo; struct node_of_char bar; foo.data = 1; foo.next = NULL; bar.data = 'c'; bar.next = NULL; }
Pass multiple (unknown at runtime) parameters to a function.
#include <stdarg.h> // define known parameters, everything after ",..." must be the same Datatype!!! void myfunc(const char *str, ...) { va_list list; va_start(list, str); while(str) { printf("%s", str); str = va_arg(list, const char *); } va_end(list); } int main() { char *a = "a"; char *b = "b"; myfunc(a,b,NULL); }
typedef struct Class Class; struct Class { double width, height; /* Variables */ double (*area)(Class *_class); /* Function pointer */ }; /* Function */ double calc(Class *_class) { return _class->width * _class->height; } /* Constructor */ Class _Class() { Class s; s.width = 1; s.height = 1; s.area = calc; return s; } int main() { Class s1 = _Class(); s1.width = 4; s1.height = 5; printf("width = %f\n", s1.width); printf("height = %f\n", s1.height); printf("area = %f\n", s1.area(&s1)); };
#include <stdio.h> typedef struct { void (*someMethod)(void); } Test; void hello(void) { printf("hello"); } void world(void) { printf("world"); } int main(void) { Test test; test.someMethod = "hello"; test.someMethod(); test.someMethod = "world"; test.someMethod(); }
See also classes in CPP
GCC
#include <stdio.h> int main() { int a = 5, b = 10, result; asm volatile ( "movl %1, %%eax;" // Move a into EAX register "movl %2, %%ebx;" // Move b into EBX register "addl %%ebx, %%eax;" // Add EBX to EAX "movl %%eax, %0;" // Move the result back to variable result : "=r" (result) // Output operand : "r" (a), "r" (b) // Input operands : "%eax", "%ebx" // Clobbered registers ); printf("Result: %d\n", result); return 0; }
Visual C++
#include <stdio.h> int main() { int a = 5, b = 10, result; __asm { mov eax, a // Move a into EAX register mov ebx, b // Move b into EBX register add eax, ebx // Add EBX to EAX mov result, eax // Move the result back to variable result } printf("Result: %d\n", result); return 0; }
Datei resource.rc erstellen
#ifndef RESOURCE_RC_INCLUDED #define RESOURCE_RC_INCLUDED MAINICON ICON "icon.ico" #endif
und
windres resource.rc resource.o
aufrufen.
Optional, in C/CPP nochmal definieren
#define MAINICON 101
Danach kann man das Programm wie üblich kompilieren.
gcc prog.c resource.o -o prog.exe
#include <stdio.h> int main(int argc, char *argv[]) { FILE *fp = popen("ipconfig", "w"); int i = 0; char line[1024]; while (fgets(line, sizeof(line), fp) != NULL) { printf("%s\n", line); } pclose(fp); return 0; }
#include <signal.h> void catch_function(int sig) { exit(EXIT_FAILURE); } signal(SIGINT, catch_function);
extern "C" { __declspec(dllexport) int add(int a,int b) { return a+b; } __declspec(dllexport) int subtract(int a,int b) { return a-b; } }
// windows __declspec(dllexport) char *myfunc() { return "myfunc called"; } // linux __attribute__ ((visibility ("default"))) char *myfunc() { return "myfunc called"; }
Diese Library Datei kompiliert man mit dem -c Parameter.
// -fPIC für positionsunabhängigen Code // Windows dynamic gcc -c test.c -o test.o gcc -shared test.o -o test.dll gcc main.c -o main -L. -ljail // Windows static gcc -c -static test.c ar rcs test.a test.o gcc main.c -o main test.a // Linux dynamic gcc -c test.c gcc -shared test.o -o libTest.so // with lib prefix gcc main.c -o main -L. -lTest // without lib prefix // Linux static gcc -c test.c -o test.o ar crf libTest.a test.o // with lib prefix gcc main.c -o main -L. -lTest // without lib prefix
#include <stdio.h> #include <string.h> #ifdef _WIN32 #include <windows.h> #else #include <dlfcn.h> #endif #ifdef _WIN32 typedef HANDLE lib_t; #else typedef void* lib_t; #endif lib_t MyLoadLib(const char* lib) { #ifdef _WIN32 return LoadLibraryA(lib); #else return dlopen(lib, RTLD_LAZY); #endif } void MyUnloadLib(lib_t lib) { #ifdef _WIN32 FreeLibrary(lib); #else dlclose(lib); #endif } void* MyLoadProc(lib_t lib, const char* proc) { #ifdef _WIN32 return GetProcAddress(lib, proc); #else return dlsym(lib, proc); #endif } int main(int argc, char **argv) { lib_t myLib = NULL; myLib = MyLoadLib("./myLib.so"); void *funcname; funcname = "init"; void *(*func_ptr)() = MyLoadProc(myLib, funcname); char *result; result = (*func_ptr)(); printf("%s", result); MyUnloadLib(myLib); return 0; }