C语言常用知识积累

来源:互联网 发布:妮维雅 知乎 编辑:程序博客网 时间:2024/05/17 00:54

(1)如何将一个函数定义成一个宏

#define BCM_UNIT_CHECK(unit_id) bcm_unit_check((unit_id),A,B,C..)
此处函数bcm_unit_check在被调用的时候就可以直接使用BCM_UNIT_CHECK来替代这个函数,注意现在两个函数的入参个数不同,在使用过程中只有unit_id是有效的,其他的参数要填写默认的值,否则使用过程会出错!(在调用一个函数的时候要谨记函数的入参一定要正确)

(2)memcpy函数的使用

memcpy函数主要是实现将一段内存的数据拷贝到一段内存中

memcpy(d_data,s_data,length字节数)

memcpy(group_inof.acl_name,mux_info->acl_name,FTMBCM_ACL_NAME_LEN)

将muxinfo中的acl_name复制到group_info中的acl_name中去.

这里为什么不使用复制操作将muxinfo中的acl_name赋值给group_info中的acl_name,是因为acl_name的定义是一个数组

char acl_name[32],这里是一个char行的32个元素的数组,将数组中的内容复制到另一个数组中,就用这个函数比较方便。

省去了好多for循环操作!

(3)memcmp函数的使用

int memcmp函数是比较两端内存中的内容使用的:

int memcmp(const void *buf1, const void *buf2, unsigned int count);
比较两段内存buf1和buf2中的前count 个字节数的内容

(1)头文件
#include <string.h>或#include<memory.h>
(2)返回值
如果两段内存中的值完全一样,返回0
如果前段内存buf1中的数值的ascII码值小于buf2中的ascII码值返回-1,否则返回1
如:char *buf1 ="abc" char *buf2 = "acb"
首先比较a=a,然后比较吧b<c则直接返回-1,不再进行第三项的比较。

(4)strcpy函数的使用

实现将一个字符串复制到另一个字符串中

char ACL_NAME[FTMBCM_ACL_NAME_LEN] = {0};

char acl_name[32]="zte";

strcpy((char *)&ACL_NAME, (char *)&acl_name);

注意(这里面的两个参数必须是地址,而且是指向char型变量的地址)

(5)表的使用

(1)首先新建一个结构体,结构体重的成员要包含这个表中的所有内容的类型
typedef struct FTMBCM_ACL_QUALIFY_INFO_TABLE_T
{
 FTMBCM_ACL_QUALIFIER_TYPE_E qualify_type;
 CHAR descript[32];
}FTMBCM_ACL_QUALIFY_INFO_TABLE_t;
注意此处结构体的名字和下面括号外的名字只是相差一个字母,一个大写一个小写,上面的红色(T),以后再使用这个类型的时候,直接使用下面的名字就好,带小写字母的名字。

const FTMBCM_ACL_QUALIFY_INFO_TABLE_t qualifyinfo_table[FTMBCM_ACL_QUALIFIER_NUM] =
{
    {FTMBCM_ACL_QUALIFIER_PORT_IN,  "PORT_IN"},
    {FTMBCM_ACL_QUALIFIER_PORT_OUT,  "PORT_OUT"},
    {FTMBCM_ACL_QUALIFIER_VLAN_ID_IN, "VLAN_ID_IN"},
    {FTMBCM_ACL_QUALIFIER_VLAN_ID_OUT, "VLAN_ID_OUT"},
    {FTMBCM_ACL_QUALIFIER_VRF,   "VRF"},
    {FTMBCM_ACL_QUALIFIER_VLAN_COS_IN, "VLAN_COS_IN"},
    {FTMBCM_ACL_QUALIFIER_VLAN_COS_OUT,"VLAN_COS_OUT"},
    {FTMBCM_ACL_QUALIFIER_VLAN_CFI_IN, "VLAN_CFI_IN"},
    {FTMBCM_ACL_QUALIFIER_VLAN_CFI_OUT, "VLAN_CFI_OUT"},
    {FTMBCM_ACL_QUALIFIER_MAC_SA,  "MAC_SA"},
    {FTMBCM_ACL_QUALIFIER_MAC_DA,  "MAC_DA"},
    {FTMBCM_ACL_QUALIFIER_ETHER_TYPE, "ETHER_TYPE"},
    {FTMBCM_ACL_QUALIFIER_IPV4_SRC,  "IPV4_SRC"},
    {FTMBCM_ACL_QUALIFIER_IPV4_DEST,  "IPV4_DEST"},
    {FTMBCM_ACL_QUALIFIER_IPV6_SRC,  "IPV6_SRC"},
    {FTMBCM_ACL_QUALIFIER_IPV6_DEST,  "IPV6_DEST"},
    {FTMBCM_ACL_QUALIFIER_IP_PROTOCOL, "IP_PROTOCOL"},
    {FTMBCM_ACL_QUALIFIER_DSCP,   "DSCP"},
    {FTMBCM_ACL_QUALIFIER_TOS,   "TOS"},
    {FTMBCM_ACL_QUALIFIER_IP_FRAGMENT, "IP_FRAGMENT"},
    {FTMBCM_ACL_QUALIFIER_TCP_CONTROL, "TCP_CONTROL"},
    {FTMBCM_ACL_QUALIFIER_L4PORT_SRC, "L4PORT_SRC"},
    {FTMBCM_ACL_QUALIFIER_L4PORT_DEST, "L4PORT_DEST"},
    {FTMBCM_ACL_QUALIFIER_ICMP,   "ICMP"},
    {FTMBCM_ACL_QUALIFIER_FLOW_LABEL, "FLOW_LABEL"},
    {FTMBCM_ACL_QUALIFIER_LIF_IN,  "LIF_IN"},
    {FTMBCM_ACL_QUALIFIER_LIF_OUT,  "LIF_OUT"},
    {FTMBCM_ACL_QUALIFIER_VPN_ID_OUT, "VPN_ID_OUT"},
    {FTMBCM_ACL_QUALIFIER_L4PORT_EGRESS_SRC,"L4PORT_EGRESS_SRC"},
    {FTMBCM_ACL_QUALIFIER_L4PORT_EGRESS_DEST,"L4PORT_EGRESS_DEST"},
    {FTMBCM_ACL_QUALIFIER_PORT_SOURCE, "PORT_SOURCE"},
    {FTMBCM_ACL_QUALIFIER_L2SRCHIT,  "L2SRCHIT"},
    {FTMBCM_ACL_QUALIFIER_FORWARDTYPE, "FORWARDTYPE"}, 
    {FTMBCM_ACL_QUALIFIER_FEC,   "FEC"},
    {FTMBCM_ACL_QUALIFIER_DST_PORT,   "DST_PORT"},
    {FTMBCM_ACL_QUALIFIER_CASCADEDKEYVALUE, "CASCADEDKEYVALUE"},
    {FTMBCM_ACL_QUALIFIER_L2_DST_HIT, "L2_DST_HIT"},
    {FTMBCM_ACL_QUALIFIER_RPF_DEST_GPORT, "RPF_DEST_GPORT"},

};

上面定义的这张表就是实现了将结构体存储在数组的结构中,数组中的每一个内容就是定义的结构体的内容,包含一个qualify类型和对应的名字!

下面是其具体的使用:printf(" [%s] [%d]\n",qualifyinfo_table[rule_q->qualifyType].descript,qualifyinfo_table[rule_q->qualifyType].qualify_type);

注意(数组 作为函数入参 时,传递数组的地址只需要传递数组名字即可,数组名就代表数组的地址)

(6)回调函数的使用


注意(函数名和数组 名作为函数入参传递时,实质是传递指向这个函数的地址和数组的地址!因此函数名和数组名作为函数入参的时候,实质代表指向这个函数的地址和指向这个数组的地址)

(1)首先定义一种函数指针
typedef WORD32 (*DRVBCM_ACL_QUALIFY_SET)(WORD32 unit_id, WORD32 entry_id,FTMBCM_ACL_QUALIFIER_t *qualify_info);/*定义了一种指向设置qualify函数的指针*/

(2)定义一个存放上面这种指针类型的全局数组,存放每种类型的qualify对应的函数地址
DRVBCM_ACL_QUALIFY_SET g_drvbcm_acl_qualify_func[FTMBCM_ACL_QUALIFIER_NUM];

(3)为数组中的每个元素赋值,将函数地址存放到数组中
    g_drvbcm_acl_qualify_func[FTMBCM_ACL_QUALIFIER_PORT_IN] = drvbcm_acl_qualify_port_in_set;
    g_drvbcm_acl_qualify_func[FTMBCM_ACL_QUALIFIER_PORT_OUT] = drvbcm_acl_qualify_port_out_set;
    g_drvbcm_acl_qualify_func[FTMBCM_ACL_QUALIFIER_VLAN_ID_IN] = drvbcm_acl_qualify_vlan_in_set;
    、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

(4)上面表达式右值得函数定义如下:
WORD32 drvbcm_acl_qualify_port_in_set(WORD32 unit_id, WORD32 entry_id, FTMBCM_ACL_QUALIFIER_t *qualify_info)
{
    WORD32 rtn_code = 0;
    SWORD32 data = 0;
//    SWORD32 mask = 0;
    SWORD32 unit =0;
    SWORD32 unitPort = 0;

    FTM_ACL_PARAM_CHECK(qualify_info);

    data = qualify_info->data.data16.acl_data;
    //mask = qualify_info->data.data32.acl_mask;
    rtn_code = ftmbcm_get_local_unit_port_from_panelport(data, &unit, &unitPort);
    rtn_code = bcm_field_qualify_InPort(unit_id, entry_id, unitPort, -1);

    if (BCM_E_NONE != rtn_code)
    {
        FTM_ACL_ERROR_PRINT("bcm_field_qualify_InPort fail\n");
        return DRVBCM_ACL_QUALIFY_SET_FAIL;
    }

    return DRVBCM_ACL_OK;
}


WORD32 drvbcm_acl_qualify_port_out_set(WORD32 unit_id, WORD32 entry_id, FTMBCM_ACL_QUALIFIER_t *qualify_info)
{
    WORD32 rtn_code = 0;
    SWORD32 data = 0;
    //SWORD32 mask = 0;
    SWORD32 unit = 0;
    SWORD32 unitPort = 0;

    FTM_ACL_PARAM_CHECK(qualify_info);
 if(SOC_IS_JERICHO(unit_id))
 {
        rtn_code = drvbcm_acl_qualify_port_dst_set(unit_id,entry_id, qualify_info);
  return rtn_code;
 }

    data = qualify_info->data.data16.acl_data;
    //mask = qualify_info->data.data32.acl_mask;
    rtn_code = ftmbcm_get_local_unit_port_from_panelport(data, &unit, &unitPort);

    rtn_code = bcm_field_qualify_OutPort(unit_id, entry_id, unitPort, -1);

    if (BCM_E_NONE != rtn_code)
    {
        FTM_ACL_ERROR_PRINT("bcm_field_qualify_OutPort fail\n");
        return DRVBCM_ACL_QUALIFY_SET_FAIL;
    }

    return DRVBCM_ACL_OK;

}


WORD32 drvbcm_acl_qualify_vlan_in_set(WORD32 unit_id, WORD32 entry_id, FTMBCM_ACL_QUALIFIER_t *qualify_info)
{
    WORD32 rtn_code = 0;
    WORD16 data = 0;
    WORD16 mask = 0;

    FTM_ACL_PARAM_CHECK(qualify_info);

    data = qualify_info->data.data16.acl_data;
    mask = qualify_info->data.data16.acl_mask;

    rtn_code = bcm_field_qualify_InnerVlanId(unit_id, entry_id, data, mask);

    if (BCM_E_NONE != rtn_code)
    {
        FTM_ACL_ERROR_PRINT("bcm_field_qualify_InnerVlanId fail\n");
        return DRVBCM_ACL_QUALIFY_SET_FAIL;
    }

    return DRVBCM_ACL_OK;
}


(5)如下所示:函数名作为函数的入参使用的时候,函数名代表的是指向这个函数的地址,而这个函数的定义和调用这个函数的函数的这个参数的定义要完全一致!
SWORD32 myavl_walk_inorder_double_argu(AVL_TREE *pRoot, void walkExec(AVL_TREE *ppNode,void *argu),void *argu)
{

}
myavl_walk_inorder_double_argu((AVL_TREE*)&group_info->pGroupBindInfo, ftmbcm_acl_add_notify, group_info);

VOID ftmbcm_acl_add_notify(AVL_TREE * ppNode, void *argu)
{

}

 

 

 

 

注意(函数名和数组 名作为函数入参传递时,实质是传递指向这个函数的地址和数组的地址!因此函数名和数组名作为函数入参的时候,实质代表指向这个函数的地址和指向这个数组的地址)

(1)首先定义一种函数指针
typedef WORD32 (*DRVBCM_ACL_QUALIFY_SET)(WORD32 unit_id, WORD32 entry_id,FTMBCM_ACL_QUALIFIER_t *qualify_info);/*定义了一种指向设置qualify函数的指针*/

(2)定义一个存放上面这种指针类型的全局数组,存放每种类型的qualify对应的函数地址
DRVBCM_ACL_QUALIFY_SET g_drvbcm_acl_qualify_func[FTMBCM_ACL_QUALIFIER_NUM];

(3)为数组中的每个元素赋值,将函数地址存放到数组中
    g_drvbcm_acl_qualify_func[FTMBCM_ACL_QUALIFIER_PORT_IN] = drvbcm_acl_qualify_port_in_set;
    g_drvbcm_acl_qualify_func[FTMBCM_ACL_QUALIFIER_PORT_OUT] = drvbcm_acl_qualify_port_out_set;
    g_drvbcm_acl_qualify_func[FTMBCM_ACL_QUALIFIER_VLAN_ID_IN] = drvbcm_acl_qualify_vlan_in_set;
    、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、

(4)上面表达式右值得函数定义如下:
WORD32 drvbcm_acl_qualify_port_in_set(WORD32 unit_id, WORD32 entry_id, FTMBCM_ACL_QUALIFIER_t *qualify_info)
{
    WORD32 rtn_code = 0;
    SWORD32 data = 0;
//    SWORD32 mask = 0;
    SWORD32 unit =0;
    SWORD32 unitPort = 0;

    FTM_ACL_PARAM_CHECK(qualify_info);

    data = qualify_info->data.data16.acl_data;
    //mask = qualify_info->data.data32.acl_mask;
    rtn_code = ftmbcm_get_local_unit_port_from_panelport(data, &unit, &unitPort);
    rtn_code = bcm_field_qualify_InPort(unit_id, entry_id, unitPort, -1);

    if (BCM_E_NONE != rtn_code)
    {
        FTM_ACL_ERROR_PRINT("bcm_field_qualify_InPort fail\n");
        return DRVBCM_ACL_QUALIFY_SET_FAIL;
    }

    return DRVBCM_ACL_OK;
}


WORD32 drvbcm_acl_qualify_port_out_set(WORD32 unit_id, WORD32 entry_id, FTMBCM_ACL_QUALIFIER_t *qualify_info)
{
    WORD32 rtn_code = 0;
    SWORD32 data = 0;
    //SWORD32 mask = 0;
    SWORD32 unit = 0;
    SWORD32 unitPort = 0;

    FTM_ACL_PARAM_CHECK(qualify_info);
 if(SOC_IS_JERICHO(unit_id))
 {
        rtn_code = drvbcm_acl_qualify_port_dst_set(unit_id,entry_id, qualify_info);
  return rtn_code;
 }

    data = qualify_info->data.data16.acl_data;
    //mask = qualify_info->data.data32.acl_mask;
    rtn_code = ftmbcm_get_local_unit_port_from_panelport(data, &unit, &unitPort);

    rtn_code = bcm_field_qualify_OutPort(unit_id, entry_id, unitPort, -1);

    if (BCM_E_NONE != rtn_code)
    {
        FTM_ACL_ERROR_PRINT("bcm_field_qualify_OutPort fail\n");
        return DRVBCM_ACL_QUALIFY_SET_FAIL;
    }

    return DRVBCM_ACL_OK;

}


WORD32 drvbcm_acl_qualify_vlan_in_set(WORD32 unit_id, WORD32 entry_id, FTMBCM_ACL_QUALIFIER_t *qualify_info)
{
    WORD32 rtn_code = 0;
    WORD16 data = 0;
    WORD16 mask = 0;

    FTM_ACL_PARAM_CHECK(qualify_info);

    data = qualify_info->data.data16.acl_data;
    mask = qualify_info->data.data16.acl_mask;

    rtn_code = bcm_field_qualify_InnerVlanId(unit_id, entry_id, data, mask);

    if (BCM_E_NONE != rtn_code)
    {
        FTM_ACL_ERROR_PRINT("bcm_field_qualify_InnerVlanId fail\n");
        return DRVBCM_ACL_QUALIFY_SET_FAIL;
    }

    return DRVBCM_ACL_OK;
}


(5)如下所示:函数名作为函数的入参使用的时候,函数名代表的是指向这个函数的地址,而这个函数的定义和调用这个函数的函数的这个参数的定义要完全一致!
SWORD32 myavl_walk_inorder_double_argu(AVL_TREE *pRoot, void walkExec(AVL_TREE *ppNode,void *argu),void *argu)
{

}
myavl_walk_inorder_double_argu((AVL_TREE*)&group_info->pGroupBindInfo, ftmbcm_acl_add_notify, group_info);

VOID ftmbcm_acl_add_notify(AVL_TREE * ppNode, void *argu)
{

}

(7)avl树的使用

(1)向树种插入一个结点的函数
函数说明:
入参:
AVL_TREE       *root 树根结点的指针变量
void       *newNode 要插入的结点的信息,类型可变
GENERIC_ARGUMENT    key 在树种搜索时使用的key
SWORD32 compare(void *, GENERIC_ARGUMENT) 比较使用的回调函数

int myavl_insert
(
    AVL_TREE       *root,       /* pointer to the root node ptr */
    void       *newNode,    /* ptr to the node we want to insert */
    GENERIC_ARGUMENT    key,        /* search key of newNode */
    SWORD32 compare(void *, GENERIC_ARGUMENT)   /* comparison function */
)
{
    AVL_NODE **nodepp;              /* ptr to current node ptr */
    AVL_NODE **ancestor[AVL_MAX_HEIGHT];   /* list of pointers to all
                           our ancestor node ptrs */
    SWORD32     ancestorCount;          /* number of ancestors */
    SWORD32     loop = 1;

    nodepp = root;
    ancestorCount = 0;

    while (loop)    /* for pclint */
    {
        AVL_NODE   *nodep;  /* pointer to the current node */
        SWORD32     delta;  /* result of the comparison operation */

        nodep = *nodepp;

        if (nodep == NULL)
        {
            break;    /* we can insert a leaf node here ! */
        }

        ancestor[ancestorCount++] = nodepp;

        delta = compare(nodep, key);

        if (0 == delta)
        {
            return -1;
        }
        else if (delta < 0)
        {
            nodepp = (AVL_NODE **) & (nodep->left);
        }
        else
        {
            nodepp = (AVL_NODE **) & (nodep->right);
        }
    }

    ((AVL_NODE *)newNode)->left = NULL;
    ((AVL_NODE *)newNode)->right = NULL;
    ((AVL_NODE *)newNode)->height = 1;
    *nodepp = newNode;

    myavl_rebalance(ancestor, ancestorCount);

    return 1;
}


(2)在AVL树种查找一个结点的函数
函数说明:
入参:
AVL_TREE       *root 树根结点的指针变量
GENERIC_ARGUMENT    key 在树种搜索时使用的key
SWORD32 compare(void *, GENERIC_ARGUMENT) 比较使用的回调函数 此处使用的回调和插入函数使用的回调是一个函数
void *myavl_search
(
    AVL_TREE        root,           /* root node pointer */
    GENERIC_ARGUMENT    key,            /* search key */
    SWORD32 compare(void *, GENERIC_ARGUMENT)   /* comparison function */
)
{
    AVL_NODE   *nodep;  /* pointer to the current node */
    SWORD32 loop = 1;

    nodep = root;

    while (loop)    /* for pclint */
    {
        SWORD32 delta;  /* result of the comparison operation */

        if (nodep == NULL)
        {
            return NULL;    /* not found ! */
        }

        delta = compare(nodep, key);

        if (0 == delta)
        {
            return nodep;    /* found the node */
        }
        else if (delta < 0)
        {
            nodep = nodep->left;
        }
        else
        {
            nodep = nodep->right;
        }
    }

    return NULL;
}

(3)在树种删除一个结点的函数
函数说明:
入参:
AVL_TREE       *root 树根结点的指针变量
GENERIC_ARGUMENT    key 在树种搜索时使用的key
SWORD32 compare(void *, GENERIC_ARGUMENT) 比较使用的回调函数 此处使用的回调和插入函数使用的回调是一个函数

void *myavl_delete
(
    AVL_TREE       *root,   /* pointer to the root node pointer */
    GENERIC_ARGUMENT    key,    /* search key of node we want to delete */
    SWORD32 compare(void *, GENERIC_ARGUMENT)   /* comparison function */
)
{
    AVL_NODE **nodepp;              /* ptr to current node ptr */
    AVL_NODE   *nodep;              /* ptr to the current node */
    AVL_NODE **ancestor[AVL_MAX_HEIGHT];   /* list of pointers to all our
                           ancestor node pointers */
    SWORD32 ancestorCount;              /* number of ancestors */
    AVL_NODE   *deletep;            /* ptr to the node we have to
                           delete */
    SWORD32 loop = 1;

    nodepp = root;
    ancestorCount = 0;

    while (loop)    /* for pclint */
    {
        int delta;      /* result of the comparison operation */

        nodep = *nodepp;

        if (nodep == NULL)
        {
            return NULL;    /* node was not in the tree ! */
        }

        ancestor[ancestorCount++] = nodepp;

        delta = compare(nodep, key);

        if (0 == delta)
        {
            break;    /* we found the node we have to delete */
        }
        else if (delta < 0)
        {
            nodepp = (AVL_NODE **) & (nodep->left);
        }
        else
        {
            nodepp = (AVL_NODE **) & (nodep->right);
        }
    }

    deletep = nodep;

    if (nodep->left == NULL)
    {
        /*
         * There is no node on the left subtree of delNode.
         * Either there is one (and only one, because of the balancing rules)
         * on its right subtree, and it replaces delNode, or it has no child
         * nodes at all and it just gets deleted
         */

        *nodepp = nodep->right;

        /*
         * we know that nodep->right was already balanced so we don't have to
         * check it again
         */

        ancestorCount--;
    }
    else
    {
        /*
         * We will find the node that is just before delNode in the ordering
         * of the tree and promote it to delNode's position in the tree.
         */

        AVL_NODE **deletepp;       /* ptr to the ptr to the node
                           we have to delete */
        SWORD32    deleteAncestorCount;    /* place where the replacing
                           node will have to be
                           inserted in the ancestor
                           list */

        deleteAncestorCount = ancestorCount;
        deletepp = nodepp;
        deletep = nodep;

        /* search for node just before delNode in the tree ordering */

        nodepp = (AVL_NODE **) & (nodep->left);

        while (loop)
        {
            nodep = *nodepp;

            if (nodep->right == NULL)
            {
                break;
            }

            ancestor[ancestorCount++] = nodepp;
            nodepp = (AVL_NODE **) & (nodep->right);
        }

        /*
         * this node gets replaced by its (unique, because of balancing rules)
         * left child, or deleted if it has no childs at all
         */

        *nodepp = nodep->left;

        /* now this node replaces delNode in the tree */

        nodep->left = deletep->left;
        nodep->right = deletep->right;
        nodep->height = deletep->height;
        *deletepp = nodep;

        /*
         * We have replaced delNode with nodep. Thus the pointer to the left
         * subtree of delNode was stored in delNode->left and it is now
         * stored in nodep->left. We have to adjust the ancestor list to
         * reflect this.
         */

        ancestor[deleteAncestorCount] = (AVL_NODE **) & (nodep->left);
    }

    myavl_rebalance(ancestor, ancestorCount);

    return deletep;
}