Behavioural

  • What do you know about Infinera? Why Infinera?
    • Telecommunications
  • What is the hardest problem you have solved? Biggest achievement?
  • Tell me about a time you wish you’d handled a situation differently with a colleague.
  • How have you handled a difficult situation with a coworker?

Theory

C/C++

What is static?

  • A static variable in the body of a function retains its value between invocations of that function
    • Not that this should rarely be used as it’s not thread-safe and makes code harder to read/maintain
#include <stdio.h>
 
void foo()
{
    int a = 10;
    static int sa = 10;
 
    a += 5; // always prints 15
    sa += 5; // sa increments by 5 from last invocation
 
    printf("a = %d, sa = %d\n", a, sa);
}
 
int main()
{
    int i;
 
    for (i = 0; i < 10; ++i)
        foo();
}
  • Static variables
    • A static variable in a function can’t be accessed from outside the function (local scope)
    • A static variable of a class can be addressed from the class and its instances
    • A static variable in a namespace scope (outside of functions and classes) is accessible by all functions within that file, but not by any functions in any other module; it’s a localised global
  • Static functions
    • A static function can only be called by other functions in that module; scope of the function is localised to the module in which it is declared
    • A static function in a class differs from regular member functions in that it can be called without an instance; because there’s no instance, it can only access other static members of the class
      • E.g. static int get_count { return A_s_count; }
  • The above two principles are important for encapsulation. Generally, those file-level data/functions should be static unless there’s a need to expose them to the outside
  • ==Note that C++ has an additional use: static in a class transforms a class variable into a shared property amongst all instances of that class==.
    • Example: keep track of the number of instances for a class

[1] https://stackoverflow.com/questions/572547/what-does-static-mean-in-c [2] https://rmbconsulting.us/publications/a-c-test-the-0x10-best-questions-for-would-be-embedded-programmers [3] https://stackoverflow.com/questions/943280/difference-between-static-in-c-and-static-in-c [4] https://stackoverflow.com/questions/15235526/the-static-keyword-and-its-various-uses-in-c

What is volatile?

  • A volatile informs the compilers that the object may be changed by something outside of the knowledge of the compiler (e.g. an ISR); the variable will then be read before any use and written after every change
    • volatile int foo tells the compiler to explicitly create a LDR/STR instruction for each statement that foo is used, pulling from the address and writing to the address immediately
    • What happens if you don’t use volatile? The compiler will use a cached copy of the variable in registers or flash, leading to undesired results
    • A good embedded example: suppose somewhere in your code you have a variable in memory which is read many times but never written to. The compiler sees this and tries to optimise fetching - it thinks “because that value is never going to change, instead of fetching the value from memory and putting it into a register, we can save cycles by caching a copy of it in a register.”
      • This is fine if the variable is only under control of the code.
      • But if the variable’s liable to change from external factors (an ISR or some hardware), the compiler will not be aware that it has changed and will continue to use the wrong cached version.
      • Hardware examples: hardware registers in peripherals (e.g. status register for a bus), a GPIO input port
    • volatile does not guarantee anything else - atomicity, cache coherency
    • TLDR: tells the compiler to make no assumptions about the value of a variable
  • Follow-up questions
    • Can a parameter be both const and volatile? Yes, an example would be a read-only register bit; this value should not be modified by the program, but it might be changed due to hardware
    • Can a pointer be volatile? Yes, an example is if an ISR changes the pointer to a buffer

[1] https://stackoverflow.com/questions/46010403/static-volatile-vs-static-vs-volatile-in-c

What is virtual?

  • The main distinction between virtual functions and non-virtual ones is that "if a derived class is handled using pointer or reference to the base class, a call to an overridden virtual function would invoke the behavior defined in the derived class [instead of the base class]"
  • In other words, we want to tag member functions which we expect to redefine in child classes with virtual
  • What happens if we don’t use virtual for an overridden function?
class Animal
{
    public: // we should add "virtual" in front of void
        void eat() { std::cout << "I'm eating generic food."; }
};
 
class Cat : public Animal
{
    public:
        void eat() { std::cout << "I'm eating a rat."; }
};
 
int main() {
	Animal *animal = new Animal;
	Animal *cat = new Cat;
 
	animal->eat(); // I'm eating generic food
	cat->eat();    // I'm eating generic food
}
  • Although we assign cat to be a Cat object, the method being invoked is based on the pointer type (Animal) and not the type of object it is pointing to
  • This is a characteristic of static binding (compile time binding); which version of the method gets used is decided at compile time based on the type of the pointer
  • With virtual we get dynamic binding (runtime binding); which version of the method gets used is based on the type of the object being pointed to (desired behaviour, usually)
  • Note that virtual is not strictly mandatory but is strongly recommended

[1] https://en.cppreference.com/w/cpp/language/virtual [2] https://stackoverflow.com/questions/2391679/why-do-we-need-virtual-functions-in-c

Static member functions

[1] https://www.ibm.com/docs/en/zos/2.1.0?topic=only-member-functions

Explain overriding vs overwriting.

  • Overriding and overloading exist in C++ but the term “overwrite” is not an official C++ principle
  • Overriding data members is not possible, the typical solution is to virtual the getters/setters - see following
    • If a get_value() method that returns some data member money declared in the base class is not virtual, for example, then how would it know anything about money in subclasses?
    • It only knows about itself
  • Overriding occurs when a subclass “overrides” members of its parent class which it inherited.
    • It’s still possible to access the base function even if the child class overrode it:
int main() {
	Derived derived1, derived2;
    derived1.print();
 
    // access print() function of the Base class
    derived2.Base::print();
    // you can also call the overriden method of the Base class
    // directly within child's function definition
    // Base::print();
    return 0
}
  • The above describes the general behaviour of overriding, note that there is also an override identifier in C++ 11
    • override in a derived class function says to the compiler “I’m overriding a virtual method of my parent class, if there’s no virtual method in the parent class matching my signature, fail to compile”
    • If Child::func()’s function signature doesn’t equal Parent::func()’s signature, compiler raises error as we are not properly overriding but defining a new method
      • Signature generally includes the parameter list of a function (types of the parameters) and name
    • Note that override is optional and not required, but using it for a derived class’s override helps code maintenance; we want the compiler to complain when we aren’t overriding properly!
    • Bonus: final for “I’m overriding this function and I don’t want any potential children to try to override me.”
struct Base { virtual void foo() {} };
struct Derived: Base { void foo() override {} };
  • Overloading: “I like this function name/operator shorthand so I’m gonna steal it and redefine it”
    • Function overloading: multiple functions can have the same name as long as the parameter lists differ
    • Operator overloading also exists
  • Overwriting is typically understood as overwriting the value of an object, for example the assignment of a variable. This concept is not exclusive to C++ or OOP

[1] https://stackoverflow.com/questions/4738315/c-overriding-overwriting [2] https://www.programiz.com/cpp-programming/function-overriding [3] https://stackoverflow.com/questions/18198314/what-is-the-override-keyword-in-c-used-for

Compare and contrast referencing vs. passing a function or variable.

Public vs. Protected vs. Private?
  • public members of a class are accessible to all
  • protected members are accessible within the class and any classes that derive from it
  • private members are only accessible within the class
How does polymorphism work?

[1] https://stackoverflow.com/questions/5854581/polymorphism-in-c

How would you debug some issue (like memory corruption)

Transmission

  • Compare and contrast I2C, UART, and SPI
  • How does an ADC work? How about a DAC?

RTOS

Why would you use an RTOS? When would you not?
Compare and contrast mutexes and semaphores.
  • A mutex is a binary semaphore, i.e. a semaphore initiated with counter at 1. Mutex for mutually exclusive access, semaphores to manage wait queues. These are the main differences and similarities in a nutshell.
What is an interrupt?
What is polling? When to use each?
  • An interrupt service routine is a software process invoked by an interrupt request from hardware
  • How does interrupt work?
What programming practices should typically be avoided in embedded systems, and why?

OSes

  • Do you know gRPC? gRPC
What’s the difference between FLASH and RAM?
  • What does single threaded mean to you?
  • Explain all processes that happen in kernel level in any OS
  • How does user page and kernel page communicate with each other?
  • How would you design a system for packets exchange?

Code Problems

Bit Manipulation

Syntax

What do those do?
int a; // an integer
int *p_a; // pointer to an integer
int **pp_a; //pointer to a pointer to an integer
int arr[10]; //array of 10 integers
int *arr[10]; // array of 10 pointers to integer
int (*a)(int); // pointer to function that takes and return int
int (*a[10])(int); // array of 10 pointers to functions that take and return int
You have an array of chars, cast the list to shorts and print it out. How would you toggle two bits in a register at a given address? How could you determine the endianness of your hardware?

More Problems

https://www.toptal.com/c-plus-plus/interview-questions