C++


C/C++: Full example using a linked list with custom struct

The following code is an example that presents some basic functionality on simply linked lists. Specifically, it presents how to add an element to an empty list and then how to add more elements either to the start (prepend) or to the end (append) of the list.

[download id=”2444″]

We assume that our structure holds an integer and a dynamically created string, which we free after pop.

[download id=”2444″]

 

Source file (list_helpers.c)

#include <malloc.h>
#include "list_helpers.h"

void append(node_t **head, element_t *element) {

  struct node_t *new = malloc(sizeof(node_t));
  new->element = element;
  new->next = NULL;

  if (*head == NULL) {
    *head = new;
    return;
  }

  struct node_t *current = *head;

  while (current->next != NULL) {
    current = current->next;
  }

  current->next = new;
  return;
}

void prepend(node_t **head, element_t *element) {
  struct node_t *new = malloc(sizeof(node_t));

  new->element = element;
  new->next = *head;
  *head = new;
}

element_t *pop(node_t **head) {

  node_t *next = NULL;

  if (*head == NULL) {
    return NULL;
  }

  next = (*head)->next;
  element_t *element = (*head)->element;
  free(*head);
  *head = next;

  return element;
}

void clear(node_t **head) {
  element_t *current = pop(head);
  while (current != NULL) {
    free(current->username);
    free(current);
    current = pop(head);
  }
}

Header file (list_helpers.h)

#ifndef GM_S_LITTLE_HELPERS_LIST_HELPERS_H
#define GM_S_LITTLE_HELPERS_LIST_HELPERS_H

#ifdef __cplusplus
extern "C" {
#endif

typedef struct element_t element_t;
struct element_t {
  //We add random members to the element struct for the sake of the example
  char *username;
  unsigned int server;
};

typedef struct node_t node_t;
struct node_t {
  element_t *element;
  node_t *next;
};

void append(node_t **head, element_t *element);

void prepend(node_t **head, element_t *element);

element_t *pop(node_t **head);

void clear(node_t **head);

#ifdef __cplusplus
}
#endif

#endif //GM_S_LITTLE_HELPERS_LIST_HELPERS_H

Usage example (main.cpp)

#include <iostream>
#include "list_helpers.h"

element_t *create_user(const unsigned int server, const char *username) {

  element_t *user = (element_t *) malloc(sizeof(element_t));
  user->server = server;

  //For the sake of the example we used snprintf.
  //Upon successful return, snprintf returns the number of characters printed (excluding the null byte used to end output to strings).
  //For that reason we add one at the end of the length.
  const int length = snprintf(NULL, 0, "%s", username) + 1;
  user->username = (char *) malloc((sizeof(char) * length));
  snprintf(user->username, (size_t) length, "%s", username);
  return user;
}

int main(int argc, char *argv[]) {

  node_t *head = NULL;

  //Add the first element to the linked list
  append(&head, create_user(10, "xeirwn"));

  //Add the second element to the end of the linked list
  append(&head, create_user(12, "test"));

  //Add the third element to the end of the linked list
  append(&head, create_user(14, "banana"));

  //Add the fourth element to the beginning of the linked list
  prepend(&head, create_user(8, "apple"));

  //Popping each one to process it and then free it
  //Clearing the list
  element_t *current = pop(&head);
  while (current != NULL) {

    printf("%s\t%u\n", current->username, current->server);
    free(current->username);
    free(current);
    current = pop(&head);
  }

  //Safely clear the list. In this specific scenario it will have 0 side effects as the list was cleared above
  clear(&head);
  return 0;
}

[download id=”2444″]


C/C++: Full example of using C code in a C++ project

The following set of code present a fully functioning example of using a simple C library as part of a CPP based project to print on screen.

[download id=”2434″]

The trick relies on encapsulating the C header definitions in the extern "C" declaration. extern "C" will make all function and variable names in C++ have C linkage. What this means at the compiler level is that the compiler will not modify the names so that the C code can link to them and use them using a C compatible header file containing just the declarations of your functions and variables.

[download id=”2434″]

main.c

#include "cpp_library.h"
#include "c_library.h"

extern "C" void c_hello_world();

int main() {

    cpp_hello_world();
    c_hello_world();
    return 0;
}

cpp_library.h

#ifndef CPP_BASE_CPP_LIBRARY_H
#define CPP_BASE_CPP_LIBRARY_H

void cpp_hello_world();

#endif //CPP_BASE_CPP_LIBRARY_H

cpp_library.cpp

#include <iostream>
#include "cpp_library.h"

void cpp_hello_world() {

    std::cout << "Hello, World!" << std::endl;
}

c_library.h

#ifndef CPP_BASE_C_LIBRARY_H
#define CPP_BASE_C_LIBRARY_H

#ifdef __cplusplus
extern "C" {
#endif

void c_hello_world();

#ifdef __cplusplus
}
#endif

#endif //CPP_BASE_C_LIBRARY_H

c_library.c

#include <stdio.h>
#include "c_library.h"

void c_hello_world() {

    printf("Hello, World!\n");
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.6)
project(CPP_Base)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(SOURCE_FILES main.cpp cpp_library.cpp cpp_library.h c_library.c c_library.h)
add_executable(CPP_Base ${SOURCE_FILES})

[download id=”2434″]


C/C++: Full example of using C++ code in a C project

The following set of code present a fully functioning example of using a simple CPP library as part of a C based project to print on screen.

[download id=”2428″]

The trick relies on encapsulating the CPP header definitions in the extern "C" declaration. extern "C" will make all function and variable names in C++ have C linkage. What this means at the compiler level is that the compiler will not modify the names so that the C code can link to them and use them using a C compatible header file containing just the declarations of your functions and variables.

[download id=”2428″]

 

main.c

#include "cpp_library.h"
#include "c_library.h"

int main() {

    cpp_hello_world();
    c_hello_world();
    return 0;
}

cpp_library.h

#ifndef C_BASE_CPP_LIBRARY_H
#define C_BASE_CPP_LIBRARY_H

#ifdef __cplusplus
extern "C" {
#endif

void cpp_hello_world();

#ifdef __cplusplus
}
#endif

#endif //C_BASE_CPP_LIBRARY_H

cpp_library.cpp

#include <iostream>
#include "cpp_library.h"

void cpp_hello_world() {

    std::cout << "Hello, World!" << std::endl;
}

c_library.h

#ifndef C_BASE_C_LIBRARY_H
#define C_BASE_C_LIBRARY_H

void c_hello_world();

#endif //C_BASE_C_LIBRARY_H

c_library.c

#include <stdio.h>
#include "c_library.h"

void c_hello_world() {

    printf("Hello, World!\n");
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.6)
project(C_Base)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")

set(SOURCE_FILES main.c cpp_library.cpp cpp_library.h c_library.c c_library.h)
add_executable(C_Base ${SOURCE_FILES})

[download id=”2428″]


C/C++: Get the size of a file in bytes

The following function accepts the name of a file as a string and returns the size of the file in bytes. If for any reason it cannot get the file information, it will return the value -1.

[download id=”2417″]

In our header file, we used the following pre-processor directives around our declarations

#ifdef __cplusplus
extern "C" {
#endif
#ifdef __cplusplus
}
#endif

to allow c++ code to call our c function.

The usage example code makes three tests:

  1. Getting the size of the currently executing binary, as it will have a non-zero size
  2. Getting the size of a non-existing file, to check that it will properly return -1
  3. Getting the size of an empty file, to be sure it is empty we create it right before the test

[download id=”2417″]

Source file (file_helpers.c)

#include <sys/stat.h>
#include "file_helpers.h"

//It will return the size of the file in bytes OR -1 in case that it cannot get any status information for it
off_t get_file_size(const char *filename) {
  //Specialised struct that can hold status attributes of files.
  struct stat st;

  //Gets file attributes for filename and puts them in the stat buffer.
  // Upon successful completion, it returns 0, otherwise and errno will be set to indicate the error.
  if (stat(filename, &st) == 0) {
    //Size of file, in bytes.
    return st.st_size;
  }

  return -1;
}

Header file (file_helpers.h)


#ifndef GM_S_LITTLE_HELPERS_FILE_HELPERS_H
#define GM_S_LITTLE_HELPERS_FILE_HELPERS_H

#ifdef __cplusplus
extern "C" {
#endif

off_t get_file_size(const char *filename);

#ifdef __cplusplus
}
#endif

#endif //GM_S_LITTLE_HELPERS_FILE_HELPERS_H

Usage example (main.cpp)

#include <iostream>
#include "file_helpers.h"

void print_file_size(const char *filename) {
  const off_t size_of_file = get_file_size(filename);
  if (size_of_file > 0) {
    printf("The size of '%s' is %zd bytes\n", filename, size_of_file);
  }
  else if (size_of_file == 0) {
    printf("The file '%s' is empty\n", filename);
  }
  else {
    printf("Could not get the status information for file '%s'\n", filename);
  }
}

int main(int argc, char *argv[]) {

  //Testing a non-zero sized file
  print_file_size(argv[0]);
  //Testing for a non-existing file
  print_file_size("some file that does not exist...");
  const char * filename = "/tmp/some_empty_file";
  //Creating an empty file
  FILE * fout = fopen(filename, "w");
  fclose(fout);
  //Testing for an empty file
  print_file_size(filename);

  return 0;
}

[download id=”2417″]