设为首页 加入收藏

TOP

C基础 那些年用过的奇巧淫技(一)
2017-10-12 12:45:25 】 浏览:4939
Tags:基础 那些 奇巧

引言 - 为寻一颗明星

  

为要寻一颗明星
        徐志摩 1924年12月1日《晨报六周年纪念增刊》 我骑著一匹拐腿的瞎马, 向著黑夜里加鞭;—— 向著黑夜里加鞭, 我跨著一匹拐腿的瞎马。
// 我冲入这黑绵绵的昏夜, 为要寻一颗明星;—— 为要寻一颗明星, 我冲入这黑茫茫的荒野。// 累坏了,累坏了我胯下的牲口, 那明星还不出现;—— 那明星还不出现, 累坏了,累坏了马鞍上的身手。// 这回天上透出了水晶似的光明, 荒野里倒著一只牲口, 黑夜里躺著一具尸首。—— 这回天上透出了水晶似的光明!//

{   :  http://music.163.com/#/song?id=5276735  }

 

前言 - 有点扯

  C基本是程序生涯的入门语言. 虽说简单, 但已经断层了. 估计是不合时宜吧.

工作中也就在网络层框架会看见部分C的影子. 自己用C开发久了, 发现C一个弊端是 当一个项目超过 2千行 x 10 时候用C协作

非常难受. C风格是个自由的英雄主义表现.

但是 真实的生活如dota, 我们不是 hero 而只是 那个小兵, 时来运转会成为超级兵. 哈哈.

但这不重要, 喜欢就好.

  生活不止眼前的苟且 ... ...

   好那我们开始,看看那些关于C基础的活化石. 真想问 <<C程序设计>> 这门课你真的学好了吗?

 

正文 - 有点难

1.  int i = 0; ++i 一直继续会怎样?

我们先看这样的测试代码

#include <stdio.h>
#include <stdlib.h>

/*
 * 测试 int 的最大值
 */
int main(void) {
    int id = 0x7fffffff;

    printf("-1 = %x\n", -1);
    printf("id = %d\n", id);
    ++id;
    printf("id = %d\n", id);
    id += 0x7fffffff;
    printf("id = %d\n", id);
    id += 0x7fffffff;
    printf("id = %d\n", id);

    system("pause");
    return 0;
}

你能算明白测试结果吗, 如果可以说明你计算机组成原理学的很好. 运行截图如下

因而 我们得到 int i = 0; ++i 一直继续的 会是 0->INT_MAX->INT_MIN->0 这样循环的.  例如 skynet 存在这个使用错误

        int id = __sync_add_and_fetch(&(ss->alloc_id), 1);
        if (id < 0) {
            id = __sync_and_and_fetch(&(ss->alloc_id), 0x7fffffff);
        }

原作者希望 再从 0开始 , 但却忘了

#define INT_MIN     (-2147483647 - 1) // minimum (signed) int value
#define INT_MAX       2147483647    // maximum (signed) int value

对于 signed  MAX + MIN = -1 , 因为计算机中 正数从0开始, 负数从-1开始.

 

2. 添加双引号 的宏用法

看下面代码

// 添加双引号的宏
#ifdef _API_MEM
#   define  STRINIFY_(S)    #S
#   define  STRINIFY(S)     STRINIFY_(S)
#   include STRINIFY(_API_MEM)
#   undef   STRINIFY
#   undef   STRINIFY_
#endif

有些工程中使用上面代码, 来动态的导入头文件. 核心在于 STRINIFY_ 和 STRINIFY 两个宏使用. 我们测试一下

#include <stdio.h>
#include <stdlib.h>

#   define  STRINIFY_(S)    #S
#   define  STRINIFY(S)     STRINIFY_(S)

#define _API_MEM api.h

// 测试添加双引号宏
int main(void) {

    puts(STRINIFY_(_API_MEM));
    puts(STRINIFY(_API_MEM));

    system("pause");
    return 0;
}

运行结果是

通过这个发现, 如果直接用 STRINIFY_ 不会将参数展开了. 这也是一个C行业淫荡的技巧了. 但是觉得大巧若拙 

个人觉得 最好做法是

#define _API_MEM "api.h"
#ifdef _API_MEM # include _API_MEM #endif

 

3. 除了sizeof, 其实还有 offsetof

直接看例子

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>

#define UDP_ADDRESS_SIZE 19 // ipv6 128bit + port 16 bit + 1 byte type

struct write_buffer {
    struct write_buffer* next;
    void* buffer;
    char* ptr;
    int sz;
    bool userobject;
    uint8_t udp_address[UDP_ADDRESS_SIZE];
};

/*
 * 测试 宏 offsetof
 */
int main(int argc, char* argv[]) {

    printf("offsetof(struct write_buffer, udp_address[0]) = %d\n", offsetof(struct wr
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇LN : leetcode 242 Valid Anagram 下一篇gcc

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目