If you stay up to date with niche software news, your ears may recently have twitched at the release of a new programming language: V. New hobby-project programming languages are released all the time, you would correctly argue; what makes this one special? The answer is a number of design choices which promote speed and safety: V is tiny and very fast. It’s also in a self-proclaimed alpha state, and though it’s already been used to build some interesting projects, is still at an early stage.
If you have ever worked in software-related industries, the chances are that the word “Rockstar” will elicit a visceral reaction. It’s a word used by a Certain Type Of Manager for an elite software developer who’s so 1337 they don’t play by the rules of ordinary mortals. In reality it’s use is invariably an indication of trouble ahead, either from clueless startups or troublesome rockstar developers making a toxic atmosphere for the mere members of the backing band. Hackaday has a team that brings together a huge breadth of experience, and we’ve been there.
Would you like to be a rockstar developer, but without the heartache? No silly incentives, or even guitars required! [Dylan Beattie] can help, because he’s come up with a specification for the Rockstar programming language, a Turing-complete programming language whose syntax follows the conventions of 1980s rock power ballads. Of course, it’s a joke, and an excuse of some “Certified Rockstar Developer” laptop stickers, but it’s also an entertaining journey into lyrical language and compiler parsing, and the discovery that yes indeed, a singable set of classic rock lyrics can also be a compilable program.
Our particular favourite comes from the scheme used to represent numbers, as sentences in which a decimal is built from the lengths of the sentence words, and poetic licence can be employed to the fullest. The example is
My dreams were ice. A life unfulfilled; wakin' everybody up, taking booze and pills
which line of code places the value 3.1415926535 into a variable called “my dreams”.
There does not appear to be a working Rockstar compiler at the time of writing, but we are sure that the amazing community of Rockstar developers will shortly create one. And we would be hugely disappointed were we not to hear some performative coding from spandex-clad guitar-wielding developers as a result. After all, how else will they get their work noticed!
Esoteric languages have featured before here, but they have usually been far more challenging ones.
Shared libraries are our best friends to extend the functionality of C programs without reinventing the wheel. They offer a collection of exported functions, variables, and other symbols that we can use inside our own program as if the content of the shared library was a direct part of our code. The usual way to use such libraries is to simply link against them at compile time, and let the linker resolve all external symbols and make sure everything is in place when creating our executable file. Whenever we then run our executable, the loader, a part of the operating system, will try to resolve again all the symbols, and load every required library into memory, along with our executable itself.
But what if we didn’t want to add libraries at compile time, but instead load them ourselves as needed during runtime? Instead of a predefined dependency on a library, we could make its presence optional and adjust our program’s functionality accordingly. Well, we can do just that with the concept of dynamic loading. In this article, we will look into dynamic loading, how to use it, and what to do with it — including building our own plugin system. But first, we will have a closer look at shared libraries and create one ourselves.
In the first part of this series, we covered the basics of pointers in C, and went on to more complex arrangements and pointer arithmetic in the second part. Both times, we focused solely on pointers representing data in memory.
But data isn’t the only thing residing in memory. All the program code is accessible through either the RAM or some other executable type of memory, giving each function a specific address inside that memory as entry point. Once again, pointers are simply memory addresses, and to fully utilize this similarity, C provides the concept of function pointers. Function pointers provide us with ways to make conditional code execution faster, implement callbacks to make code more modular, and even provide a foothold into the running machine code itself for reverse engineering or exploitation. So read on!
In general, function pointers aren’t any more mysterious than data pointers: the main difference is that one references variables and the other references functions. If you recall from last time how arrays decay into pointers to their first element, a function equally decays into a pointer to the address of its entry point, with the
() operator executing whatever is at that address. As a result, we can declare a function pointer variable
fptr and assign a function
func() to it:
fptr = func;. Calling
fptr(); will then resolve to the entry point of function
func() and execute it.
Admittedly, the idea of turning a function into a variable may seem strange at first and might require some getting used to, but it gets easier with time and it can be a very useful idiom. The same is true for the function pointer syntax, which can be intimidating and confusing in the beginning. But let’s have a look at that ourselves.
Looking for a first project in a relatively new language that’ll stretch your abilities? [Ron] was, so he hacked a commercially available drone and opened up a lot of its functionality, while writing the client software in Go.
The drone is a DJI Tello, which has some impressive hardware like a 14-core Intel processor and excellent video processing abilities. There’s also a vibrant community and a lot of support, making it the ideal platform for a project like this. It communicates to a base station via WiFi, and using some tools like the Wireshark [Rob] was able to decipher a lot of the communications and create a whole new driver for the drone. While the drone can be controlled in the traditional way, users can also write programs to control the drone as well.
The project is both an impressive feat in reverse engineering an inexpensive drone, and a fun example of programming in the Go language. Because of the fun and excitement of drones, they have become a popular platform on which to hack, from increasing their range to becoming a platform for developing AI.
In our first part on pointers, we covered the basics and common pitfalls of pointers in C. If we had to break it down into one sentence, the main principle of pointers is that they are simply data types storing a memory address, and as long as we make sure that we have enough memory allocated at that address, everything is going to be fine.
In this second part, we are going to continue with some more advanced pointer topics, including pointer arithmetic, pointers with another pointer as underlying data type, and the relationship between arrays and pointers. But first, there is one particular pointer we haven’t talked about yet.
The one proverbial exception to the rule that pointers are just memory addresses is the most (in)famous pointer of all: the
NULL pointer. Commonly defined as preprocessor macro
(void *) 0, we can assign
NULL like any other pointer.