2017-05-17 44 views
1

在下面的源代码中,有人可以解释理性(为什么编程练习typedef结构_lwm2m_object_t新名称lwm2m_object_t?它只是删除下划线?为什么在第一次使用下划线?为什么要在C中为结构使用下划线?

typedef struct _lwm2m_object_t lwm2m_object_t; 

typedef uint8_t (*lwm2m_read_callback_t) (lwm2m_uri_t * uriP, char ** bufferP, int * lengthP, lwm2m_object_t * objectP); 
typedef uint8_t (*lwm2m_write_callback_t) (lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP); 
typedef uint8_t (*lwm2m_execute_callback_t) (lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP); 
typedef uint8_t (*lwm2m_create_callback_t) (lwm2m_uri_t * uriP, char * buffer, int length, lwm2m_object_t * objectP); 
typedef uint8_t (*lwm2m_delete_callback_t) (uint16_t id, lwm2m_object_t * objectP); 
typedef void (*lwm2m_close_callback_t) (lwm2m_object_t * objectP); 


struct _lwm2m_object_t 
{ 
    uint16_t     objID; 
    lwm2m_list_t *   instanceList; 
    lwm2m_read_callback_t readFunc; 
    lwm2m_write_callback_t writeFunc; 
    lwm2m_execute_callback_t executeFunc; 
    lwm2m_create_callback_t createFunc; 
    lwm2m_delete_callback_t deleteFunc; 
    lwm2m_close_callback_t closeFunc; 
    void *     userData; 
}; 
+0

它不需要在使用类型的地方使用'struct'。下划线是为了防止非typedef的名称和typedef的名称之间的冲突 – Toby

+1

我不认为这是个好主意。 A)这是一种标准违规行为。文件范围和标记命名空间中以下划线开头的所有标识符都被保留,B)它不必要地丢弃全局命名空间。不必要的,因为你可以为你的struct标记和你的typedef('typedef struct foo foo;')使用相同的名字 - 这是一种C++甚至构建到语言中的约定。 – PSkocik

+0

“文件范围内的所有标识符和以下划线开头的标记名称空间都被保留” - U wot?不完全的。 – Bathsheba

回答

5

其实,如果你使用

typedef struct lwm2m_object_t lwm2m_object_t; 

struct lwm2m_object_t { 
// 
} 

它仍然会由C.允许这是因为结构名称和typedef的标识符有不同的命名空间。请参阅Why doesn't ANSI C have namespaces?以获取有关C中命名空间的信息。

但是,许多专业用户避免这种情况,并为结构和typedef使用不同的名称。 MISRA 也不允许这样做。

规则5.6(咨询):在一个名字空间没有标识符应当具有相同的拼写在另一个的名称空间的标识符,与 结构构件和联合成员名称除外。[MISRA C 2004]

下划线的使用只是一些人遵循的惯例。您可以遵循其他惯例,例如

typedef struct sTag_lwm2m_object_t lwm2m_object_t; 

struct sTag_lwm2m_object_t { 
// 
} 

https://en.wikipedia.org/wiki/MISRA_C

+0

也许包含一个MISRA的链接? – Bathsheba

+0

我无法抗拒。添加了一个引用,并有一个upvote。 – Bathsheba

0

前面的下划线是用于不同的目的通过每个人或团队详情请阅读此answer,特别是专用于段落

我通常看到这一点:。

typedef struct lwm2m_object lwm2m_object_t; 

其中一个将追加_t结构的名称,表示这是一个typedef'ef名称的读者。

1

写入typedef struct _lwm2m_object_t lwm2m_object_t;意味着当您想要引用struct类型时,不需要编写更详细的struct _lwm2m_object_t,但可以直接使用lwm2m_object_t。它可以节省打字并可以使源代码更清晰。

给一个单独的_加上实际的struct名称是一个长年累月的惯例。许多民间使用_t作为后缀来表示类型

但几件事情需要注意:

  1. 千万不要使用下划线,作为正式这样做的行为是不确定的。

  2. 不要使用单个下划线和大写字母开头。同样,这种类型的名称是保留的。

  3. POSIX明确禁止您以_t结束自己的类型,但请注意标准 C允许。

许多经验丰富的C程序员发现(3)可恶而忽略它。 (我做的。)

+0

双下划线约定也是可恶的,非常诚实。许多C程序员也忽略了*。我想,不同程度的照顾便携性。 – StoryTeller

+0

@StoryTeller:我认为这很淘气,因为它可能会与实现C标准库时闲时定义的宏冲突。 (我禁止在我的代码库中。) – Bathsheba

+0

如果真诚地看待它,与标准库冲突的可能性不会大于与POSIX的冲突。我非常怀疑'__mycompany_mymodule_mycomponent_hiddenfeature'会与标准库中的任何内容发生冲突。 – StoryTeller

0

就其本身而言,领先的下划线没有内在的意义,它只是创建标签名称与typedef名独特的标识符。你可以用

typedef struct foo fooType; 

标签名称占据从普通的标识符不同的命名空间达到同样的效果,所以你可以写

typedef struct foo foo; 

其中一些人认为混乱。我没有 - 标签名称被存在的struct(或unionenum)关键字消歧。

你应该使用导致在你的标识符下划线 - 标识符以两个前导下划线或前导下划线跟着一个大写字母,始终保留用于任何用途的执行,并用单下划线开头的标识符在保留普通和标签名称空间。

你可以使用一个尾随强调了同样的效果

typedef struct foo_ foo; 

和满足大家。

相关问题