C语言编程技巧/C Programming Tips

目录

1 说明

本文不介绍基本C语言编程,只记录实际代码中用到的各种编程技巧,这些技巧一般是GCC 编译器强相关的,

2 返回结构体

使用型别强制转换与打括号组合,返回结构体类别:

#include <stdio.h>

struct bucket {
        int array[128];
};

struct slot {
        int x;
        struct bucket *bucket;
};

static inline struct slot __to_slot(unsigned long v)
{
        return (struct slot){v & 3, (struct bucket *)(v & ~3)};
}

int main()
{
        struct slot sl;

        sl = __to_slot(0x1234567890abcdef);

        printf("bucket=%p, x=%x\n", sl.bucket, sl.x);

        return 0;
}

3 内联汇编

3.1 基本格式

3.1.1 语法

asm("assembly code");
  • 指令在引号之间
  • 多行汇编语言之间要加上换行"\n",一般也加上"\t"进行适度缩进
  • 添加\(volatile\)禁止编译器优化inline汇编
  • ANSI C对\(asm\)有其他定义,可替换为\(__asm__\)关键字替换

3.1.2 示例

#include <stdio.h>

int a = 10, b = 20, r = 0;

int main()
{
        asm volatile("movl a, %eax\n\t"
                     "addl b, %eax\n\t"
                     "movl %eax, r\n\t");

        printf("%d + %d = %d\n", a, b, r);
        return 0;
}

3.2 扩展格式

3.2.1 语法

asm("assembly code" : output locations : input operands : changed registers);
assembly code
与基本格式的assembly code格式相同,
output locations
inline汇编代码输出

3.3 cpu ticks rdstc

3.3.1 inline function

#include <stdio.h>
#include <time.h>
#include <unistd.h>

static __always_inline unsigned long rdtsc_ordered(void)
{
        unsigned long low, high;

        asm volatile("mfence\n\tlfence\n\t" ::: "memory");
        asm volatile("rdtsc" : "=a" (low), "=d" (high));

        return low | (high << 32);
}

int main()
{
        unsigned long start, end;

        start = rdtsc_ordered();
        usleep(1000);
        end = rdtsc_ordered();

        printf("elapsed=%lu [start=%lu end=%lu]\n", end - start, start, end);

        return 0;
}

3.3.2 gcc extend macro

#include <stdio.h>
#include <time.h>
#include <unistd.h>

#define rdtsc_ordered() ({                              \
        unsigned long low, high;                                \
        asm volatile("mfence\n\tlfence\n\t" ::: "memory");      \
        asm volatile("rdtsc" : "=a" (low), "=d" (high));        \
        low | (high << 32); })

int main()
{
        unsigned long start, end;

        start = rdtsc_ordered();
        usleep(1000);
        end = rdtsc_ordered();

        printf("elapsed=%lu [start=%lu end=%lu]\n", end - start, start, end);

        return 0;
}

4 Reference Materials

LWN A guide to inline assembly code in GCC
https://lwn.net/Articles/685739/