Linux – which xxx – 查找执行的下令所在的路

by admin on 2018年12月15日

Linux 下,咱们通常动用 cd ,grep,vi
等一声令下,有时候我们而查到这么些命令所在的职,如何是好也?

引言 – 为觅平粒超新星

Linux 下起2只指令可形成该效能:which ,whereis

  图片 1

 which 用来查当

为要寻一颗明星
        徐志摩 1924年12月1日《晨报六周年纪念增刊》

我骑著一匹拐腿的瞎马,

向著黑夜里加鞭;——

向著黑夜里加鞭,

我跨著一匹拐腿的瞎马。//

我冲入这黑绵绵的昏夜,

为要寻一颗明星;——

为要寻一颗明星,

我冲入这黑茫茫的荒野。//

累坏了,累坏了我胯下的牲口,

那明星还不出现;——

那明星还不出现,

累坏了,累坏了马鞍上的身手。//

这回天上透出了水晶似的光明,

荒野里倒著一只牲口,

黑夜里躺著一具尸首。——

这回天上透出了水晶似的光明!//

面前倘诺实践之命所在的路子。

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

whereis 用来查阅一个命或者文件所在的路径,

 

 

前言 – 有点扯

 

  C基本是程序生涯的入门语言. 虽说简单, 但已经断层了. 估算是老式吧.

which命令的法则:在PATH变量指定的不二法门中,搜索某个系统命令的地点,并且再次来到第一单寻结果。也就是说,使用which命令,就能够看到某系统命令是否是,以及实施的究竟是呀一个职务的通令。

行事被为即以网络层框架会映入眼帘有些C的影子. 自己之所以C开发久了, 发现C一个弊端是 当一个体系领先2千行 x 10 时候用C协作

which命令的使实例:

坏麻烦受. C风格是独随机的英雄主义表现.

  $ which grep

但是 实事求是的生使dota, 大家无是 hero 而只是 那么些小兵, 促地反弹会成为超级兵. 哈哈.

 

然随即不重要, 爱就好.

 

  生活不断眼前之苟且 … …

whereis命令原理:只可以用于程序名的搜索,而且才摸二进制文件(参数-b)、man表达文件(参数-m)和源代码文件(参数-s)。假使简单参数,则归所有信息。

   好这大家初阶,看看这么些关于C基础的活化石. 真想问问 <<C程序设计>> 这门课而真正学好了也?

whereis命令的用实例:

 

  $ whereis grep

正文 – 有点难

 

1.  int i = 0; ++i 一贯延续会咋样?

下面举个例证来注解。参与你的linux系统上装了五只版本的Java。假设你直接当命令行敲命令
“java -version”
,会拿走一个结出。可是,你懂凡是啊一个门道下之java在推行呢?虽然想知道,可以为此
which 命令:

俺们先行看这样的测试代码

which java

#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;
}

回去的凡 PATH路径中率先个JAVA的地点,也就是JAVA命令默认执行的职

若会算是清楚测试结果也, 假若可以评释你电脑组成原经济学的死去活来好. 运行截图如下

而选拔命令: whereis java

图片 2

这你会师获取许多漫漫结果,因为这令将所有包含java(不管是文件要文件夹)的门路都排了出。

所以 我们得 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;
}

运作结果是

图片 3

经这意识, 若是直接用 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 write_buffer, udp_address[0]));
    printf("offsetof(struct write_buffer, udp_address) = %d\n", offsetof(struct write_buffer, udp_address));

    system("pause");
    return 0;
}

运作的结果如下

图片 4

由此者 可以理解 offsetof 其实总括的凡结构体中字段的偏移量. 关于结构体的内存总括基础力量, 必须要理解的. 洞悉内存结构非常首要.

实际上 offsetof 是 stddef.h 中定义的一个 宏 如下

#define offsetof(s,m) ((size_t)&(((s*)0)->m))

凡未是好清爽. 就是这般, 没事简单的.

实则下面代码还蕴藏一个 关于 数组的 细节 . int a[10];  &a[0] == a
== &a 地址是同的.

 

4. 什么社团一个只能于积上分红结构体?

//堆上 声明结构体
struct request_open {
    int id;
    int port;
    uintptr_t opaque;
    char host[];
};

哪怕地点这样, 加了[], 表示未全类型. 只可以当积上分配内存. 使用方法.

struct request_open *open = malloc(sizeof(struct request_open) + sizeof(char) * 19);

这种协会相似在底部库会看见. 一些总的程序员喜欢这样形容

//堆上 声明结构体
struct request_open {
    int id;
    int port;
    uintptr_t opaque;
    char host[0];
};

//堆上 声明结构体
struct request_open {
    int id;
    int port;
    uintptr_t opaque;
    char host[1];
};

因为一贯的编译器不扶助 char host[]; 后边标准加以了. 后来从未改变了习惯.

 

5. 争社团一个当栈上开始化的指针变量

说之坏领会, 抑或这么问, 下边定义之色怎么解.

struct cstring_data {
    char* cstr;                                 //保存字符串的内容
    uint32_t hash;                                //字符串hash,如果是栈上的保存大小
    uint16_t type;                                //主要看 _INT_STRING_* 宏,默认0表示临时串
    uint16_t ref;                                //引用的个数, 在 type == 0时候才有用
};

typedef struct _cstring_buffer {
    struct cstring_data* str;
} cstring_buffer[1];                            //这个cstring_buffer是一个在栈上分配的的指针类型

面也是底层库中会境遇一个技巧.

当声明cstring_buffer cb; 后.可以一贯cb->str调用它,

当 cb 传入到 函数中. 如故可 cb->str. 可以知晓呢这一个价值是栈上的可是足以当指针变量用法去而用. 看下或好了解

typedef struct _jmp_buf { 
    int _jb[_JBLEN + 1]; 
} jmp_buf[1];

是是 setjmp.h 里的一条龙定义,把一个 struct 定义成一个数组。

这样,在声明 jmp_buf
的上,可以把数据分配到仓库上。可是当参数传递的时段则当一个指针. 

推而广之一下读明白美观下边. 应该可以清楚为啥这样搞.

//特殊的数组 声明结构体
#define _INT_STRING_ONSTACK        (4)                //标识 字符串分配在栈上
                                                //0 潜在 标识,这个字符串可以被回收,游离态

#define _INT_ONSTACK            (128)            //栈上内存大小

struct cstring_data {
    char* cstr;                                 //保存字符串的内容
    uint32_t hash;                                //字符串hash,如果是栈上的保存大小
    uint16_t type;                                //主要看 _INT_STRING_* 宏,默认0表示临时串
    uint16_t ref;                                //引用的个数, 在 type == 0时候才有用
};

typedef struct _cstring_buffer {
    struct cstring_data* str;
} cstring_buffer[1];                            //这个cstring_buffer是一个在栈上分配的的指针类型

/*
 * v : 是一个变量名
 *
 * 构建一个 分配在栈上的字符串.
 * 对于 cstring_buffer 临时串,都需要用这个 宏声明创建声明,
 * 之后可以用 CSTRING_CLOSE 关闭和销毁这个变量,防止这个变量变成临时串
 */
#define CSTRING_BUFFER(v) \
    char v##_cstring[_INT_ONSTACK] = { '\0' }; \
    struct cstring_data v##_cstring_data = { v##_cstring, 0, _INT_STRING_ONSTACK, 0 }; \
    cstring_buffer v; \
    v->str = &v##_cstring_data;

 

6. 这一个年总起个align字段举办内存对同

/*字节对齐的类型Align,为了优化CPU读取*/
typedef union {
    long        l_dummy;
    double      d_dummy;
    void        *p_dummy;
} Align;

/*标志大小,默认是4字节*/
#define MARK_SIZE       (4)
/*内存块头结点,双向链表结点size,filename,line都是为了调试添加的调试信息.prev和next是双向链表的核心*/
typedef struct {
    int         size;
    char        *filename;
    int         line;
    Header      *prev;
    Header      *next;
    unsigned char       mark[MARK_SIZE];
} HeaderStruct;

/*Align类型的字节大小*/
#define ALIGN_SIZE      (sizeof(Align))
/*这是个不错的技巧,求最小的n使得n*ALIGN_SIZE>=val成立,n,val,ALIGN_SIZE都属于自然数*/
#define revalue_up_align(val)   ((val) ? (((val) - 1) / ALIGN_SIZE + 1) : 0)
/*将HeaderStruct按照Align划分,找到最小的n,使得n*ALIGN_SIZE>=sizeof(HeaderStruct),在自然数集中*/
#define HEADER_ALIGN_SIZE       (revalue_up_align(sizeof(HeaderStruct)))

/*实现了memory.h接口中Header不完全类型,Align是对齐用的,内存结构的头结点.链表链接的主要结点*/
union Header_tag {
    HeaderStruct        s;
    Align               u[HEADER_ALIGN_SIZE];
};

 主要看 union Headr_tag 中 Align结构. 保证不同机器及外存是对同步的. 相比古老了. 特别底层的堆栈会合到.

 

7.  可转换参数宏, 这么些从事

一律直接扣下工程中因故底演示

//4.0 控制台打印错误信息, fmt必须是双引号括起来的宏
#ifndef CERR
#define CERR(fmt, ...) \
    fprintf(stderr,"[%s:%s:%d][error %d:%s]" fmt "\r\n",\
         __FILE__, __func__, __LINE__, errno, strerror(errno),##__VA_ARGS__)
#endif/* !CERR */

//4.1 控制台打印错误信息并退出, t同样fmt必须是 ""括起来的字符串常量
#ifndef CERR_EXIT
#define CERR_EXIT(fmt,...) \
    CERR(fmt,##__VA_ARGS__),exit(EXIT_FAILURE)
#endif/* !ERR */

#ifndef IF_CERR
/*
 *4.2 if 的 代码检测
 *
 * 举例:
 *        IF_CERR(fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP), "socket create error!");
 * 遇到问题打印日志直接退出,可以认为是一种简单模板
 *    code : 要检测的代码 
 *  fmt     : 必须是""括起来的字符串宏
 *    ...     : 后面的参数,参照printf
 */
#define IF_CERR(code, fmt, ...)    \
    if((code) < 0) \
        CERR_EXIT(fmt, ##__VA_ARGS__)
#endif //!IF_CERR

#ifndef IF_CHECK
/*
 * 是上面IF_CERR 的简化版很好用
 */
#define IF_CHECK(code) \
    if((code) < 0) \
        CERR_EXIT(#code)
#endif // !IF_CHECK

这 传说着之 3粒痣, 就是可转换参数宏的一切o(∩_∩)o

 

8. 简便的谢幕. 如故大

一个累如何和0较,真的是 == 吗. 其实好之思绪是概念阀值.

//3.0 浮点数据判断宏帮助, __开头表示不希望你使用的宏
#define __DIFF(x, y)                ((x)-(y))                      //两个表达式做差宏
#define __IF_X(x, z)                ((x)<z&&(x)>-z)                //判断宏,z必须是宏常量
#define EQ(x, y, c)                 EQ_ZERO(__DIFF(x,y), c)        //判断x和y是否在误差范围内相等

//3.1 float判断定义的宏
#define _FLOAT_ZERO               (0.000001f)                      //float 0的误差判断值
#define EQ_FLOAT_ZERO(x)          __IF_X(x,_FLOAT_ZERO)            //float 判断x是否为零是返回true
#define EQ_FLOAT(x, y)            EQ(x, y, _FLOAT_ZERO)            //判断表达式x与y是否相等

谢幕吧 : [

  先生布置一个功课, 问学生, 看见好晾衣杆吗. 什么人会襄助我测试出中度来.

一个同班自告奋勇的管晾衣杆放倒了. 测试出长 为 1.5m.

  先生将他骂了同等搁浅, 我若的是可观, 不是加上度.

]

//5.0 获取数组长度,只能是数组类型或""字符串常量,后者包含'\0'
#ifndef LEN
#define LEN(arr) \
    (sizeof(arr)/sizeof(*(arr)))
#endif/* !ARRLEN */

 

继记 – 认真做善之

  错误是难免的, 欢迎吐槽交流.
 … 还有下半辈子的苟且.  哈哈, 可是于变, 这会转换得有意思, O(∩_∩)O哈哈~

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图