Will this code run on embedded systems?

Thread Starter

xox

Joined Sep 8, 2017
838
I've almost completed this array library I've been working on. Now I'm starting to wonder about portability. It's written in ANSI C and only includes two headers, 'stdlib.h' and 'memory.h', so theoretically at least it should be pretty easy to port to embedded systems. Is that a reasonable assessment or are things more problematic in practice?
 

BobaMosfet

Joined Jul 1, 2009
2,113
I've almost completed this array library I've been working on. Now I'm starting to wonder about portability. It's written in ANSI C and only includes two headers, 'stdlib.h' and 'memory.h', so theoretically at least it should be pretty easy to port to embedded systems. Is that a reasonable assessment or are things more problematic in practice?
@xox

In practice, you usually use #ifdef and #ifndef statements to configure your compilation for different platforms, so you can use the same code. This can be used for different architectures, endianisms, etc. I've written single code-bases that will execute on 4 foundational platforms: embedded, windows, DOS, and Mac. Same C-code, for all.

I don't mean this to be harsh, I'm just not sugar-coating it (I appreciate what you're trying to do... but)-- I took a look at your code- you're doing it the hard way. Do you know the difference between a function, procedure, and a macro? And frankly, it's kinda clumsy IMHO. I'm not sure you know enough about the language or the compiler, or you would typedef your struct differently, and you would be passing addresses, not objects. I'm not sure you have any clue how a stack-frame works. This is like an attempt to turn C into C++ without having enough knowledge to so so elegantly, efficiently, and correctly (or your trying to solve a problem that doesn't really exist only because you have insufficient knowledge and experience using the language).

If you haven't learned and gotten good with assembly language, do so (PLEASE) before trying to provide 'tools' for other people to use. Otherwise you're not helping, you're just providing bad tools and perpetuating a growing problem of bad code that is getting worse. IMHO.

Looking at other algorithms may spark your creativity and knowledge in the right direction:

Title: Algorithms in C, 3rd Ed. [Parts 1-4, Fundamentals, Data Structures, Sorting, Searching]
Author: Robert Sedgewick
ISBN: 0-201-31452-5

Title: Standard C [Quick Ref]
Author(s): P.J.Plauger, Jim Brodie
ISBN: 1-55615-158-6

Title: C: A Reference Manual, 4th Ed.
Author: Samuel P. Harbison & Guy L. Steel, Jr.
ISBN: 0-13-326224-3
 
Last edited:

Thread Starter

xox

Joined Sep 8, 2017
838
In practice, you usually use #ifdef and #ifndef statements to configure your compilation for different platforms, so you can use the same code. This can be used for different architectures, endianisms, etc. I've written single code-bases that will execute on 4 foundational platforms: embedded, windows, DOS, and Mac. Same C-code, for all.
The library is endian-safe and compiles/runs on any modern operating system. No ifdef's/ifndef's are needed in any case. The only issue is with say embedded systems which don't have a stdlib.h file to include in the first place. Those systems are what I was asking about, and in fact they are actually quite rare.

I don't mean this to be harsh, I'm just not sugar-coating it (I appreciate what you're trying to do... but)-- I took a look at your code- you're doing it the hard way. Do you know the difference between a function, procedure, and a macro?
Procedures? Is that supposed to be some kind of C construct? It *has* to be implemented as macros to achieve that particular interface. Otherwise, how could you possibly use a custom datatype without any previous declarations? As far as rapid prototyping goes this library works very well.

Sure, you could define it like this instead perhaps:

Code:
#include <stdlib.h>

#define blox_define(TYPE)             \
  typedef struct {                    \
    TYPE data;                        \
    size_t length;                    \
    size_t capacity;                  \
  } blox_##TYPE;                      \
                                      \
  blox_##TYPE blox_##TYPE##_nil(void) { \
    blox_##TYPE nil = {0};            \
    return nil;                       \
  }

// ...then...

blox_define(int);

int main() {
  blox_int bi = blox_int_nil();
}
That did cross my mind and I may eventually take it in that direction.

And frankly, it's kinda clumsy IMHO. I'm not sure you know enough about the language or the compiler, or you would typedef your struct differently, and you would be passing addresses, not objects. I'm not sure you have any clue how a stack-frame works.
Temporaries are not a major issue with this library. As most "functions" are implemented as macros, there is no "pass by value" because the code is expanded inline.

This is like an attempt to turn C into C++ without having enough knowledge to so so elegantly, efficiently, and correctly (or your trying to solve a problem that doesn't really exist only because you have insufficient knowledge and experience using the language).
Alright then.

Code:
#include <stdio.h>
#include "blox/blox.h"

typedef struct {
  blox name;
  blox hobbies;
} user;

int free_user(user* usr) {
  blox_free(usr->name);
  blox_free(usr->hobbies);
}

int print(user* usr) {
  printf("User:    %s (%zu characters)\n", blox_data(char, usr->name), blox_length(usr->name));
  printf("Hobbies: %s (%zu characters)\n", blox_data(char, usr->hobbies), blox_length(usr->hobbies));
}

int compare(user* lhs, user* rhs) {
  return strcmp(blox_begin(char, lhs->name), blox_begin(char, rhs->name));
}

blox get_input(const char* prompt) {
  static char buf[1024];
  static blox nil = {0};
  printf("%s > ", prompt);
  if (!fgets(buf, sizeof(buf), stdin))
    return nil;
  size_t len = strlen(buf);
  if (!len)
    return nil;
  char* lst = &buf[len - 1];
  if (*lst = '\n') {
    *lst = 0;
    --len;
  }
  return blox_use(buf, len);
}

int main() {
  blox lst = {0};
  user usr = {0};
  for (;;) {
    blox nam = get_input("User name to add");
    if (blox_empty(nam))
      break;
    usr.name = blox_clone(char, nam);
    blox hob = get_input("Hobbies of interest");
    if (blox_empty(hob))
      usr.hobbies = blox_from_string(char, "None");
    else
      usr.hobbies = blox_clone(char, hob);
    user* fnd = blox_search(user, lst, usr, compare);
    if (fnd) {
      puts("\nError (entry already exists):");
      print(fnd);
      puts("");
      continue;
    }
    blox_push(user, lst, usr);
    blox_sort(user, lst, compare);
    puts("\n- Users -");
    blox_for_each(user, lst, print);
    puts("");
  }
  blox_for_each(user, lst, free_user);
  blox_free(lst);
}
Sample output:

User name to add > Sarah
Hobbies of interest > Oil painting

- Users -
User: Sarah (5 characters)
Hobbies: Oil painting (12 characters)

User name to add > Andre
Hobbies of interest > Culinary arts

- Users -
User: Andre (5 characters)
Hobbies: Culinary arts (13 characters)
User: Sarah (5 characters)
Hobbies: Oil painting (12 characters)

User name to add > Sarah
Hobbies of interest > Sewing

Error (entry already exists):
User: Sarah (5 characters)
Hobbies: Oil painting (12 characters)

User name to add > Larry
Hobbies of interest > Collects used toothpicks

- Users -
User: Andre (5 characters)
Hobbies: Culinary arts (13 characters)
User: Larry (5 characters)
Hobbies: Collects used toothpicks (24 characters)
User: Sarah (5 characters)
Hobbies: Oil painting (12 characters)

User name to add > Bill
Hobbies of interest >

- Users -
User: Andre (5 characters)
Hobbies: Culinary arts (13 characters)
User: Bill (4 characters)
Hobbies: None (4 characters)
User: Larry (5 characters)
Hobbies: Collects used toothpicks (24 characters)
User: Sarah (5 characters)
Hobbies: Oil painting (12 characters)

User name to add >
That took me a about a half hour. Now write the equivalent in plain C! Yeah...didn't think so.

If you haven't learned and gotten good with assembly language, do so (PLEASE) before trying to provide 'tools' for other people to use.
Well I have implemented a bootable "operating system" in ASM. Does that count?
 
Last edited:
Top