Learn C the Hard Way – inStructions

Mmmm, pun headlines. Not sorry.

So, looking at structs. The write-up for Ex 16 starts with ‘OK, do the write-up’. So, what does the #includes stuff get?

#include <stdio.h> I know about. It lets you put things in and out, so printf lives there.
#include <assert.h> apparently crashes my browser when I search for it. Which is apposite.

Apparently ‘assert’ makes the case that something exists, and then if it doesn’t, throws up a warning to stderr. I guess stderr is also controlled by stdio, as it’s a line to print to. 2/dev/null is my favourite way of stopping the screaming. So in this case it’s checking that who is not NULL. We’re not just picking up a non-entity and trying to work with it, and if who != NULL then I guess that’s the check we’ve just succeeded at what we’ve done.

#include <stdlib.h> gives us malloc() – memory allocation. We’re grabbing a chunk of memory to use for each copy of the struct. So, for obvious reasons, it also gives us free(). Once we’ve allocated, we need to be able to free that up, or our little ghost people will wander in electronic halls forever and there will be a bad Tron sequel.

#include <string.h> must let us play with strings. We have strdup() to handle our name. It also gives us NULL, which is cool, as stlib.h also seems to give that to us. It’s probably very popular at parties.

struct Person defines what a struct called person is. It’s got some attributes inside. So, when we get to struct Person *Person_create we’ve got something to look to and check. It’s sort of like defining an int and then putting a number into it. We define a Thing and then we put how to create the thing as a subsidiary part of that.

struct Person *pointer-to-whatever-our-name-is instantiates a struct and the bits underneath fill it. Note it’s in the middle of our Person_create function. So we grab the attention of the computer, shout at it until it creates a struct with a pointer of the name ‘who’ like Joe or Mat or Cthulhu, and then we go forward from there and allocate memory from that point. For extra points, we choose a bit of memory that isn’t going to write over anything else because you put Cthulhu in the wrong place. (Cthulhu in the wrong place will /severely/ mess up your day.)

The =malloc(sizeof()) part makes sure we’ve allocated memory to the maximum size a Person can be. That’s pretty large in the case of some sedentary sorts.

I think assert(who !=NULL) checks that that happened right, but it might also be that ‘who’ is not a name of 0 characters. Those might look the same in the wrong light. It’s checking who, rather than checking the pointer named who. Someone call for the fucking Tardis.

who->name=stdrup(name) is the stand-out here, so let’s do the next line first.
who->age=age is pretty obvious. Within the struct sub-language, you’ve got -> which says ‘put this into the struct’. So assign ‘name’ from the input of the function into the bit of ‘who’ that is labelled ‘age’.

The same applies with who->name=stdrup(name) except we handle it a bit differently because it’s a string, not an integer. It’s string duplicate. It copies the string we want, the name, into the space we have reserved for the name. I don’t know why that’s explicitly different from int – maybe it’s for security, maybe it’s because it’s easiest to copy a string that way, I just dunno. But that’s what it does.

The return returns the whole object. Later, we’ll see that we run this function with a = in front of it. We’re making ‘who’ and then assigning it to a named pointer we create at the same time.

Person_destroy is my favourite… no, let me alter that. /Running/ Person_destroy is my favourite part of the program. I could sit there running it all day. Only I can’t, because the person has to exist to be destroyed. Again, if there’s a NULL entry, we can’t destroy it, and we output that. I can see a bit more sense in this than in checking the creation. You don’t want to typo the name of a poor unfortunate to be blatted to oblivion, and let them live, after all. But I’m also pretty sure both will be good practice, and if I’m going to have my fun at the end of a function’s life, I can build in sense at the start of it.

We free up the name separately from the rest. I guess because the name is a string, and has to be treated differently, so you only free up to the null byte at the end. Maybe you can group different strings to destr… uh, ‘free’ in the same way as we group everything else on the next line, but we’re doing the strings and then everything else as a one-er.

(Person_destroy($^). Mmmm. It’d be so peaceful.)

Person_print doesn’t check on the existence of the person in question, but I have people for that. It prints out everything we explicitly list, according to the -> syntax. This is likely a bit easier to remember than ***pointer-to_otherPointer(pointer002).

Then we hit main(). It’ll return an int. That int will be 0, because nothing will go wrong. Nothing, you hear me?

Now, we have that equals sign I was talking about up the page. We make a person we label ‘joe’ for the computer. We give him a memory address and fill in all the details, and then we link those details to pointer ‘joe’. He’s 32. His life will be short, although it will have some miraculous aging.

Ditto Frank. Name ‘Frank Blank’, pointer-name, ‘frank’.

%p is the only new-ish part of printf. It gives us the address at which the pointer-thing resides. *joe points to %p where %p is labelled ‘joe’. To find ‘joe’ we look up *joe and that gives us the address %p. Then we run the function that prints out their details, Person_print.

We do the same for Frank. Frank moved away from the neighbourhood and changed his name, but he’s still in his brother Joe’s shadow.

Person_destroy(joe); BAHWHAAWHAHAHAHA…

Ahem, yeah, we just call that function we discussed earlier. Joe’s brief, warm moment of existence is over, and we get back the memory. If we’ve had a /really/ bad moment and killed the wrong person and we know the memory address we might be able to copy him or install a new Joe very percisely over him, but frankly that’s advanced ninja work, and I’ll be having none of it.

Our crime is complete. Nobody can prove Frank or Joe ever existed. We return ‘0’ to say that all is well, and end the main function.

I should go back and write this up as comments in the code, but I had too much fun blorting it into a longer form. Don’wanna!

Probably will, though.

ETA: Did.

Extra credit – can’t work out how to remove memory allocation from stack. I’m not using malloc() so I can’t use free(). Everything else works.

Learn C the Hard Way – reference book

Now that I’ve got a project where I’m using C in the wild, I’m concentrating more on that than on learning. It’s definitely rubbing in the stuff I need to know, but I’m also aware I’m using some very basic tools and there might be better stuff out there. I’m about to approach structs in the book, but so far they haven’t reared their ugly head in anything I need to do. I think.

This is a thing I found with LPythonTHW as well. I took what I needed, and moved on a lot more slowly from that point, but I also went back pretty much constantly to the earlier lessons, to use them for syntax. Every time I’m unsure how to type something, I know that there will be an example somewhere in LCTHW that shows me the thing I’m after. That’s good.

I’ll likely drift away from that model too, unless it turns out it covers things I’m picking up here and there. Stuff like bitshifts are really useful when I’m setting an array of pins and need to go through a binary number in order. I’m sure that’ll come up as an operator, but it hasn’t yet. Having learned how to do it, if I get things wrong there’s still the internet, but for now there’s mostly Zed’s book.

Sparky – the state of the code 2015-07-24

Sparky is pretty much functional, and needs making into something good. I’ve re-written the Arduino code with what I’ve learned so far in Learn C the Hard Way, and I’ll use the same board as the Arduino’s on to trigger electronically isolated LEDs, meaning I don’t have to have any outputs, so I can use all the pins for measuring.

The code is as generic as I can make it. Other than the LED pin, none of the pins come pre-named, so you can decide what to plug in where and how, and then output it, as long as you have this program and an Arduino programmer.

/*
 * 
 * Version 6 of Oxygen is an almost complete re-write.
 * V6 mounts the LEDs on the in pins, allowing for easy reading, without needing output.  Physical output can be provided by buffering LEDs to numbered pins.
 * V6 has a timing loop of one second, followed by a toggle of the LED on reserved Pin 13.
 * We do not use pins 0 & 1 (RX/TX).
 * We scan as many lines as we can find pins for, and store them in an array so we can do good things with them.
 * The output to Serial Monitor has two possible outputs of human-readable including pin names, or binary string.
 * 
 * TO DO: binary output function for Serial Monitor
 * TO DO: use millisecond timing from boot-up rather than a set delay to make the timing loop 1 second
 * TO DO: Import oscillator code from V5, as separate function applicable to any pin
 * TO DO: Function to map analogue pins to arbitrary voltage levels (default 5v 2 decimal places).
 * 
 * May^wDoes contain sarcasm.
 */

// unchanging constants and annoying variables

// #include <stdarg.h> - use for more elegant printing later - Mat to show me how.  #includes are not generally needed in Arduino - implicit functions are brought in automatically

// Blink stuff
int ledState = LOW;
int ledPin = 13;


// Pin Arrays that I will later resent treating this way

// digital (measurement) pins

int digitalPinNumbers[] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};  // Leave out Pin13.
const int digitalPinCount = sizeof(digitalPinNumbers)/sizeof(int);  // const so we have a non-variable for indexing
char *digitalPinNames[digitalPinCount] = {"Pin 2", "Pin 3", "Pin 4", "Pin 5", "Pin 6", "Pin 7", "Pin 8", "Pin 9", "Pin 10", "Pin 11", "Pin 12"};  // also leave out pin 13
int digitalPinStates[digitalPinCount] = {HIGH}; // Currently working with pull-up resistors.  To be changed.

// analogue (measurement) pins

int analoguePinNumbers[] = {A0, A1, A2, A3, A4, A5}; // A4 & A5 are hard to get to thus likely to float
const int analoguePinCount = sizeof(analoguePinNumbers)/sizeof(int);
char *analoguePinNames[analoguePinCount] = {"Pin A0", "Pin A1", "Pin A2", "Pin A3", "Pin A4", "Pin A5"};
int analoguePinStates[analoguePinCount] = {};


// misplaced functions I will later regret

// !!! TO DO - add binary output !!!

void HumanPrint(){

  Serial.println("Digital Pins");
  for(int i = 0; i < digitalPinCount; i++){
    digitalPinStates[i] = digitalRead(digitalPinNumbers[i]);
    Serial.print(digitalPinNames[i]);
    Serial.print(": ");
    Serial.println(digitalPinStates[i]);
  }
  Serial.println("Analogue Pins");
  for(int i = 0; i < analoguePinCount; i++){
    analoguePinStates[i] = analogRead(analoguePinNumbers[i]);
    Serial.print(analoguePinNames[i]);
    Serial.print(": ");
    Serial.println(analoguePinStates[i]);
  }

}
void setup(){
  Serial.begin(9600);
  
  for(int i = 0; i < digitalPinCount; i++){
    pinMode(digitalPinNumbers[i], INPUT_PULLUP);
  }
  for(int i = 0; i < analoguePinCount; i++){
    pinMode(analoguePinNumbers[i], INPUT);
  }
  pinMode(ledPin, OUTPUT);
  Serial.println("Initialised."); 
}

//Do this later - Mat to demo
//void SerialPrint(char *v0, varargs ...)
//{
//}

void loop() {

  HumanPrint();
  
  ledState = !ledState;
  digitalWrite(ledPin, ledState);
  delay(1000);
}

Learn C the Hard Way – making things useful

Ex 15. Slowed down by altering my system clock and having to stop to deal with that. In fact, the time it took me (no wireless, no wired internet, one small-screened phone) was probably not worth it. I’d have been better off waiting an hour. Modification times are not my friend.

Also not my friend: my brain. I need projects I can use all this new knowledge on. I learn best by doing things and multi-tentacling my brain. That’s like multi-threading, but more muscular, and also rather disgusting. But I need a set of short, easy things that are useful, and that I can do. I’m happier with electronics because I’m working towards a project, but while you can create a project out of logic chips that someone hands you, it’s a lot harder to create a program out of functions that exist. Nobody’s handing me the functions, and choice paralysis is creeping in. It helps that Zed’s adding in independent research and ‘go break this’ and the Extra Credit section – I’m taking those as my projects pro tem, but I’d also really like Stuff To Do. I might look at Arduino projects and what I can do with them. I started learning for Sparky, but once I had that part of the project dealt with, I didn’t have anything else to make the jump between theoretical and ‘wow this is useful’.

So I can probably make the LED array into genuine arrays. I’ll be able to read Mat’s bit of code for the logical read-out to the Serial Monitor, and I can have a minimal physical output plus a proper electronic output. It’ll be a nice break for my brain.

Ooh. Shiny!

Learn C the Hard Way – a lesson where I can’t do too much. Maybe

Ex 8:

This is harder for me to type out with my brain switched off, as it’s new to me so I want to understand it. It’s been pointed out that my wish to understand everything immediately is leading me off down blind alleys. Well, yes. That’s true. I shall try harder not to step off the path, and to trust this book to lead me to where I need to go. I find it hard to stop on the external resea… OK, I find it hard to stop on anything. But I can, so I should. One big risk is that I’ll learn too far ahead and hit a lesson that should be teaching me, and I’ll basically just skim it. I’ve fallen prey to that a lot before. A little learning is a dangerous thing. Although sometimes it can get you cash on game shows, so it’s not all bad.

Extra Credit:

Embedding a null byte in the char name[] increases its size but stops us from reading everything after the null character.

It’s easier to get garbage out of an int than out of a char. I can call for item n+4 out of n in a list of integers and get back what looks like a sensible integer.

If I define an array, I’m defining its size. I can then write out over the end of it, and it stays at the same size (there is a null byte) but I can also pick from it. This gets by the compiler and valgrind. There must be ways of stopping it, presumably tests I can write or flags or some other tool.

Playing with putting characters into ints and ints into characters is… less frustrating than in Python, but probably more dangerous. Python protects me from myself. Here, I can easily put in a character that means something and have it be formatted and it looks right, and it’s just from the wrong place entirely. So I’m pretty damned sure there will be ways of dealing with that. What I need to take from this is that I’ve got the ability to feed X into Y and Y will just chomp it up and not worry about the flavour.

Other stuff:

I’m pretty sure that I will use something like sizeof() in the Arduino, if I want to make an array of my LEDs. Sparky needs visual output. Either that or explicit sizing of the … oh. I think I triggered an error over fitting everything into an explicitly sized array when I tried that last time. I probably didn’t have the null character accounted for. So I could try that next time I’m sitting down to program Sparky. That’ll deal with the error where things are the wrong size, and I can look at why they are really not working instead. Sparky’s next due for a look this evening or on Tuesday.

Sparky – or, How To Shave A Yak

So, the reason I have this blog is to keep a record of my non-painting projects, most of which are in a constant state of tinkerage. The big one is Sparky. Sparky is my finest piece of yak shaving to date.

Yak shaving, for those who don’t know, is the end result of a linked set of tasks which lead back causally to the original task that started it. See rationalwiki.org/wiki/Fun:Yak_shaving for the full definition and some very fine examples.

I don’t know what the original task was that made me start on this course, but here’s the part of it I remember….

... I need to learn how to use the Mill in makespace
but there isn't a course so I'll co-write a course.
...now I have a broken centre drill in my practice piece
BUT Mat says spark erosion's pretty easy.  We'll build a Spark Erosion machine to get it out
Now I need to write an Arduino program, to read off the data from the electronic board.
What could possibly go wrong?

So far, I’ve spent about a year and forgotten my original task. It was probably something to do with art, but it’s turning into a machine that includes research on yak species as version names.

Learn C the Hard Way – big numbers

Yep.

If you take a number that has an optional sign, you need to leave room for the negative numbers. If you don’t, all that room can be added up top instead, effectively doubling the size of the number-holder you can play with, as long as it’s positive. If all you’re concerned with is the size of the number, that’s cool. You’ve got a box that’s twice as long, but each unit in the box is double the size of the one before, so an unsigned long is really MASSIVE.

It came out as 0 on my output. I don’t know why. Um, maybe the computer itself couldn’t handle it? Compiler was happy, valgrind was happy, but it was outputting as 0. I’ll have a think.

Extra credit asks about why chars and ints can be treated just about the same. Well, it’s just ones and zeros, innit? So if the char and the int can be interchanged, then they get to be. If not, if one won’t fit into the other, just throw a wobbly in the compiler.

Learn C the Hard Way – chars and strings and tigers and bears

‘Kay. So now we’re looking at the char[] without a *. So I’m going to guess that the * means multiple argvs of type char[] are available. Still keeping that on the back burner.

I’m getting closer to a problem I have on the Arduino, where I want to output in a particular format, binary with 0 padding at the front. That’s %05d – but I don’t know how to pass the right thing out yet. Maybe printing it as soon as I calculate it and not trying to pass it back out for the printing later on. Now I know what printf can do, I’m happier trying that, although I believe I need sprintf – stringprint. Again, not a thing to look at yet.

Breaking things for extra credit:

char x = ”; is an error. Char is explicitly 1 character long. Related to the ” instead of “” I figger.

char x[] = “” isn’t an error. It’s 0 length but that doesn’t really matter. It’s initialised as a space for there to be a string, and that’s that.

printf("")

– sort of funny. How can you tell if it’s done anything? I’m assuming it exists because the compiled program has some size, and I left it on its own in there, but it’s a 0-length string. The compiler doesn’t like it, but goes for it anyhow, but when you run it nothing appears to happen.

By law I must now link to Oglaf’s Fountain of Doubt. (SFW)

Subtle, isn’t it?

Putting an int into a char results in the character returned being (I guess) ASCII result for that integer value. So that’s not broken, but it’s potentially unexpected. That’s how I got H out for integer 72 in an earlier exercise.

According to www.cdf.toronto.edu/~ajr/209/notes/printf.html s is already a char pointer. I think that’s just a sign that says ‘use this long thing over here’ instead of having to write out what the long thing is in a compressed space.

Learn C the Hard Way – packing away my ego

Ex 5. I’m pretty good at copying typing I can see, but unfortunately I’m also pretty good at remembering what I’ve seen in previous exercises, so I nearly made the argvs into ints. Brain managed to pull up at the last minute, though. However, that’s one to be very careful of in future.

Line 4, /this/ version of the main function needs that combo of ints and chars. I took a moment realising that that was not a universal truism for main().

Line 5, starting the body of the function, threw me for a loop. I’m learning this because I’m messing with an Arduino for my current project, Sparky. That means I’ve been basically copying and pasting and trying to make things work. So I’ve seen an if() that had brace pairs and an if() that didn’t. For a moment I was trying to over-ride what Zed says. Obviously here, the {} are only required if there’s more than one line…

So I’m going to believe him. That’s a very hard thing for me. And yeah, a bit later on we’re told that statements end in ; – except logic.

What’s going on in there is that we demand an int be returned, and then we return a 0 at the end, and in between we do all sorts of interesting stuff. I believe we could type

void main(int whatever)

if we wanted to input ‘whatever’ and get nothing out. We’d just do stuff inside the main function. That’s how the Arduino sets things up. It has void loop() and that loop just goes round and round and round, doing stuff but never actually outputting.

I think the only thing I’m unsure of is the char *argv[]. The [] means it’s an array. (I know that because I’m working out failure messages for Sparky, and that’s how they are filed.) But char* x is different to char *x and the * is worrying me. Pointer. It’s a pointer of some sort. But is *char a pointer to a character… well, colour me ignorant. I’m guessing, not looking this up. It’ll end up explained.

Learn C the Hard Way – Arch is a bastard for this and I’m fine with that

Ex 4.

Valgrind is available in the /extra repository in Arch. We’re going to make it ourselves, though. Fair enough. I’ve made a few packages as far as I recall, but not in a while. When I was initially setting up my machine, inkscape wasn’t so good and I was using inkscape-bzr and now I don’t need that any more.

$ tar -xf <FILE>

is enough to unpack most things. ‘eXtract File’. The tool will work out what sort of file it’s working on and just does it.

$ ./configure

– error. Valgrind works on kernels 2.4 and 2.6 – Arch is a rolling release. I’m on kernel 4.something. Soooo. Package manager it is. At some point I’ll need to work out what about the package has been changed to make it work in Arch. The README.aarch has instructions on cross-compiling and paths and hosts which have a shape that makes sense but I’m not looking at the detail. I’ve used pacman and I have valgrind on the system. I stared at the Makefiles that my attempt generated, though, in the hope of absorbing their strength by drooling. On with the lesson.

The output of valgrind is already similar to Zed’s, but at some point I may diverge – Arch is like that. For now, though, I’m getting error tracking.

By fixing the uninitialised variable in ex 4, I fix all the actual errors. This is odd, as valgrind doesn’t pick up the %d without a related integer, in the first printf function. I can’t see why that might be in the manual. However, I know what the program should say, so I know what to fix. An uninitialised variable is an error that could lead to unexpected problems, and valgrind picks it up. A variable that’s missing could lead to, well, also unexpected problems. But valgrind doesn’t pick it up. Odd. Maybe an Arch thing but I don’t think so. It was not there in Zed’s print-out either.

The compiler tells me what the other problem is, so I’ll deal with that. Variables are now initialised and don’t go unused, and all format sequences are filled.

I did some messing about with making downloaded packages, but I’ve got to look into Arch’s installation process to really understand that. pacman is a powerful tool, and like all powerful tools, it hates me right from the off. I know I can make a package and then have pacman install it from my local file, but for now I’m not using that. Onward, upward, and avoid the Pevensey children on the way.