Fundamentals 13 min read

Master C Static Functions, Struct Alignment & Linux Kernel Macros – Interview Q&A

This article walks through C static keyword meanings, struct size calculations, macro definitions, hexadecimal conversion functions, a full‑featured Linux I2C driver example, and a list of common interview questions for embedded and kernel development, providing clear explanations and code snippets.

IT Services Circle
IT Services Circle
IT Services Circle
Master C Static Functions, Struct Alignment & Linux Kernel Macros – Interview Q&A

Written Exam Section

1. Describe the meaning of the two static keywords in the code

static void func(void)
{
    static unsigned int i; 
}

Line 1: static before the function makes it a file‑local function, visible only to other functions in the same source file.

Line 3: static before the variable declares a local static variable whose lifetime lasts for the whole program, scope limited to the function, stored in the global data segment, and retains its value between calls.

2. Determine the value of variable a after executing the code

unsigned int a,b=3;
void move(void *p, unsigned int val) { p=&val; }
void main(void)
{
    a = b++;
    move(&a,b);
}

Answer: 3

Explanation: a = b++ assigns the original value of b (3) to a and then increments b to 4. The move function receives the address of a and a copy of b (value 4), but it does not modify a, so a remains 3.

3. Size of the struct in a 32‑bit MCU

typedef struct {
    short a;
    char  b;
    char  C;
    int   d;
} struct1;

Answer: 8/12 bytes (depending on alignment).

Explanation: Byte alignment introduces padding. The memory layout of struct1 and struct2 is shown in the diagram (short, two chars, then padding before the 4‑byte int).

4. Define a typedef for a function pointer and use it to call test

#include <stdio.h>

typedef void (*func_t)(int data);

void testfunc(int data)
{
    printf("yikou linux %d
", data);
}

int main(int argc, char **argv)
{
    func_t pfunc;
    pfunc = testfunc;
    pfunc(9);
    return 0;
}

The example demonstrates that a function name is an address, and a function pointer can be assigned to it and invoked.

5. Macro definitions

Set bit 1 of an unsigned integer a: a |= 0x1 << 1; Clear bit 5 of an unsigned integer b: b &= ~(0x1 << 5); Calculate the number of elements in an array: #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0])) Macros are heavily used in the Linux kernel; the example shows a waiting‑queue macro implementation.

6. Convert a hexadecimal byte to two characters

unsigned char hex2char(unsigned char ch)
{
    if (ch >= 0 && ch <= 9)
        return ch + '0';
    if (ch >= 0xA && ch <= 0xF)
        return ch - 10 + 'A';
    return (unsigned char)0xFF;
}

int hex_to_chars(unsigned char hex, char *char1, char *char2)
{
    unsigned char high, low;
    low  = hex & 0xF;
    high = (hex >> 4) & 0xF;
    char1[0] = hex2char(high);
    char2[0] = hex2char(low);
    return 0;
}

The function splits a byte into high and low nibbles and converts each nibble to its ASCII representation.

I2C Programming Question

Below is a Linux I2C driver skeleton that implements more than 90 % of the chip’s functionality, ignoring the INT pin. The driver shows how to read and write bytes, handle ioctl commands, and register the character device.

#define YIKOU_MAJOR 500
#define YIKOU_MINOR 0

struct yikou_device {
    struct cdev cdev;
    struct i2c_client *client;
};

static int yikou_read_byte(struct i2c_client *client, unsigned char reg)
{
    int ret;
    char txbuf[1] = { reg };
    char rxbuf[1];
    struct i2c_msg msg[2] = {
        { client->addr, 0, 1, txbuf },
        { client->addr, I2C_M_RD, 1, rxbuf }
    };
    ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
    if (ret < 0)
        return ret;
    return rxbuf[0];
}

static int yikou_write_byte(struct i2c_client *client, unsigned char reg, unsigned char val)
{
    char txbuf[2] = { reg, val };
    struct i2c_msg msg[1] = {
        { client->addr, 0, 2, txbuf }
    };
    i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
    return 0;
}

static long yikou_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
    union yikou_data data;
    struct i2c_client *client = yikou->client;
    switch (cmd) {
        case CMD1:
            data.data1 = yikou_read_byte(client, REG1);
            break;
        default:
            printk("invalid argument
");
            return -EINVAL;
    }
    if (copy_to_user((void __user *)arg, &data, sizeof(data)))
        return -EFAULT;
    return sizeof(data);
}

static const struct file_operations yikou_fops = {
    .unlocked_ioctl = yikou_ioctl,
    /* ... other operations ... */
};

static int yikou_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
    int ret;
    dev_t devno = MKDEV(YIKOU_MAJOR, YIKOU_MINOR);
    yikou = kzalloc(sizeof(*yikou), GFP_KERNEL);
    if (!yikou)
        return -ENOMEM;
    yikou->client = client;
    ret = register_chrdev_region(devno, 1, "yikou");
    cdev_init(&yikou->cdev, &yikou_fops);
    ret = cdev_add(&yikou->cdev, devno, 1);
    return 0;
}

static int yikou_remove(struct i2c_client *client)
{
    /* cleanup */
    return 0;
}

static const struct i2c_device_id yikou_id[] = {
    { "yikou", 0 },
    { }
};
MODULE_DEVICE_TABLE(i2c, yikou_id);

static struct i2c_driver yikou_driver = {
    .driver = {
        .name = "yikou",
        .of_match_table = of_match_ptr(yikou_dt_match),
    },
    .probe = yikou_probe,
    .remove = yikou_remove,
    .id_table = yikou_id,
};

module_i2c_driver(yikou_driver);

The i2c_msg structure must follow the chip’s timing diagram: one message for a write sequence, two messages for a read sequence, with appropriate addr, len, and buf fields.

图片
图片

Interview Section

1. What do you know about the company?

2. Self‑introduction and project experience.

3. How to implement website interception?

4. How to achieve WAN/LAN auto‑adaptation?

5. What role does a router play and which protocols are involved in data transmission?

6. How does a phone obtain data packets after connecting to a router’s LAN port?

7. Which are you more comfortable with: application development or driver development?

8. After creating a kernel thread (pthread_create), how do you terminate it?

图片
图片
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

C++LinuxinterviewembeddedMacrosstructsI2C
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.