3686|12

6423

帖子

16

TA的资源

版主

楼主
 

你喜欢使用typedef吗? [复制链接]

 
先来一个见过的最大的结构体镇楼

  1. /*
  2. * This describes a single thread/process executing a fio job.
  3. */
  4. struct thread_data {
  5.         struct thread_options o;
  6.         unsigned long flags;
  7.         void *eo;
  8.         char verror[FIO_VERROR_SIZE];
  9.         pthread_t thread;
  10.         unsigned int thread_number;
  11.         unsigned int groupid;
  12.         struct thread_stat ts;

  13.         int client_type;

  14.         struct io_log *slat_log;
  15.         struct io_log *clat_log;
  16.         struct io_log *lat_log;
  17.         struct io_log *bw_log;
  18.         struct io_log *iops_log;

  19.         uint64_t stat_io_bytes[DDIR_RWDIR_CNT];
  20.         struct timeval bw_sample_time;

  21.         uint64_t stat_io_blocks[DDIR_RWDIR_CNT];
  22.         struct timeval iops_sample_time;

  23.         volatile int update_rusage;
  24.         struct fio_mutex *rusage_sem;
  25.         struct rusage ru_start;
  26.         struct rusage ru_end;

  27.         struct fio_file **files;
  28.         unsigned char *file_locks;
  29.         unsigned int files_size;
  30.         unsigned int files_index;
  31.         unsigned int nr_open_files;
  32.         unsigned int nr_done_files;
  33.         unsigned int nr_normal_files;
  34.         union {
  35.                 unsigned int next_file;
  36.                 os_random_state_t next_file_state;
  37.                 struct frand_state __next_file_state;
  38.         };
  39.         int error;
  40.         int sig;
  41.         int done;
  42.         pid_t pid;
  43.         char *orig_buffer;
  44.         size_t orig_buffer_size;
  45.         volatile int terminate;
  46.         volatile int runstate;
  47.         unsigned int last_was_sync;
  48.         enum fio_ddir last_ddir;

  49.         int mmapfd;

  50.         void *iolog_buf;
  51.         FILE *iolog_f;

  52.         char *sysfs_root;

  53.         unsigned long rand_seeds[FIO_RAND_NR_OFFS];

  54.         union {
  55.                 os_random_state_t bsrange_state;
  56.                 struct frand_state __bsrange_state;
  57.         };
  58.         union {
  59.                 os_random_state_t verify_state;
  60.                 struct frand_state __verify_state;
  61.         };
  62.         union {
  63.                 os_random_state_t trim_state;
  64.                 struct frand_state __trim_state;
  65.         };
  66.         union {
  67.                 os_random_state_t delay_state;
  68.                 struct frand_state __delay_state;
  69.         };

  70.         struct frand_state buf_state;

  71.         unsigned int verify_batch;
  72.         unsigned int trim_batch;

  73.         int shm_id;

  74.         /*
  75.          * IO engine hooks, contains everything needed to submit an io_u
  76.          * to any of the available IO engines.
  77.          */
  78.         struct ioengine_ops *io_ops;

  79.         /*
  80.          * Queue depth of io_u's that fio MIGHT do
  81.          */
  82.         unsigned int cur_depth;

  83.         /*
  84.          * io_u's about to be committed
  85.          */
  86.         unsigned int io_u_queued;

  87.         /*
  88.          * io_u's submitted but not completed yet
  89.          */
  90.         unsigned int io_u_in_flight;

  91.         /*
  92.          * List of free and busy io_u's
  93.          */
  94.         struct io_u_ring io_u_requeues;
  95.         struct io_u_queue io_u_freelist;
  96.         struct io_u_queue io_u_all;
  97.         pthread_mutex_t io_u_lock;
  98.         pthread_cond_t free_cond;

  99.         /*
  100.          * async verify offload
  101.          */
  102.         struct flist_head verify_list;
  103.         pthread_t *verify_threads;
  104.         unsigned int nr_verify_threads;
  105.         pthread_cond_t verify_cond;
  106.         int verify_thread_exit;

  107.         /*
  108.          * Rate state
  109.          */
  110.         uint64_t rate_bps[DDIR_RWDIR_CNT];
  111.         long rate_pending_usleep[DDIR_RWDIR_CNT];
  112.         unsigned long rate_bytes[DDIR_RWDIR_CNT];
  113.         unsigned long rate_blocks[DDIR_RWDIR_CNT];
  114.         struct timeval lastrate[DDIR_RWDIR_CNT];

  115.         uint64_t total_io_size;
  116.         uint64_t fill_device_size;

  117.         unsigned long io_issues[DDIR_RWDIR_CNT];
  118.         uint64_t io_blocks[DDIR_RWDIR_CNT];
  119.         uint64_t this_io_blocks[DDIR_RWDIR_CNT];
  120.         uint64_t io_bytes[DDIR_RWDIR_CNT];
  121.         uint64_t io_skip_bytes;
  122.         uint64_t this_io_bytes[DDIR_RWDIR_CNT];
  123.         uint64_t zone_bytes;
  124.         struct fio_mutex *mutex;

  125.         /*
  126.          * State for random io, a bitmap of blocks done vs not done
  127.          */
  128.         union {
  129.                 os_random_state_t random_state;
  130.                 struct frand_state __random_state;
  131.         };

  132.         struct timeval start;        /* start of this loop */
  133.         struct timeval epoch;        /* time job was started */
  134.         struct timeval last_issue;
  135.         struct timeval tv_cache;
  136.         unsigned int tv_cache_nr;
  137.         unsigned int tv_cache_mask;
  138.         unsigned int ramp_time_over;

  139.         /*
  140.          * Time since last latency_window was started
  141.          */
  142.         struct timeval latency_ts;
  143.         unsigned int latency_qd;
  144.         unsigned int latency_qd_high;
  145.         unsigned int latency_qd_low;
  146.         unsigned int latency_failed;
  147.         uint64_t latency_ios;
  148.         int latency_end_run;

  149.         /*
  150.          * read/write mixed workload state
  151.          */
  152.         union {
  153.                 os_random_state_t rwmix_state;
  154.                 struct frand_state __rwmix_state;
  155.         };
  156.         unsigned long rwmix_issues;
  157.         enum fio_ddir rwmix_ddir;
  158.         unsigned int ddir_seq_nr;

  159.         /*
  160.          * rand/seq mixed workload state
  161.          */
  162.         union {
  163.                 os_random_state_t seq_rand_state[DDIR_RWDIR_CNT];
  164.                 struct frand_state __seq_rand_state[DDIR_RWDIR_CNT];
  165.         };

  166.         /*
  167.          * IO history logs for verification. We use a tree for sorting,
  168.          * if we are overwriting. Otherwise just use a fifo.
  169.          */
  170.         struct rb_root io_hist_tree;
  171.         struct flist_head io_hist_list;
  172.         unsigned long io_hist_len;

  173.         /*
  174.          * For IO replaying
  175.          */
  176.         struct flist_head io_log_list;

  177.         /*
  178.          * For tracking/handling discards
  179.          */
  180.         struct flist_head trim_list;
  181.         unsigned long trim_entries;

  182.         struct flist_head next_rand_list;

  183.         /*
  184.          * for fileservice, how often to switch to a new file
  185.          */
  186.         unsigned int file_service_nr;
  187.         unsigned int file_service_left;
  188.         struct fio_file *file_service_file;

  189.         unsigned int sync_file_range_nr;

  190.         /*
  191.          * For generating file sizes
  192.          */
  193.         union {
  194.                 os_random_state_t file_size_state;
  195.                 struct frand_state __file_size_state;
  196.         };

  197.         /*
  198.          * Error counts
  199.          */
  200.         unsigned int total_err_count;
  201.         int first_error;

  202.         struct fio_flow *flow;

  203.         /*
  204.          * Can be overloaded by profiles
  205.          */
  206.         struct prof_io_ops prof_io_ops;
  207.         void *prof_data;

  208.         void *pinned_mem;
  209. };
复制代码


最新回复

值得注意。  详情 回复 发表于 2016-12-1 09:31
点赞 关注
个人签名training
 
 

回复
举报

6423

帖子

16

TA的资源

版主

沙发
 
本帖最后由 白丁 于 2016-11-30 22:08 编辑

以下来自知乎话题
原文地址

此话题由队长推荐   为什么 Linux 内核中不经常使用 typedef?
在使用C语言编写程序时,我们看见很多都对结构体使用了typedef,在stackoverflow上这个问题Why should we typedef a struct so often in C?就讨论了这样的使用带来的好处,但是为什么在Linux 内核中像task_struct,mm_struct这样的数据结构确没有使用typedef呢?而且这样的例子在内核代码中貌似还很多。
个人签名training
 
 
 

回复

6423

帖子

16

TA的资源

版主

板凳
 
作者:chmmn chmmn
链接:https://www.zhihu.com/question/20928231/answer/18201676
来源:知乎
著作权归作者所有,转载请联系作者获得授权。

typedef 只是给 struct 起了个别名,使之看起来像是个 C 基本类型,但是,C 语言确实没有把 struct 当作普通类型,证据是struct 类型的名字空间是独立的,如可以这样声明变量 struct iphdr iphdr;
除了可能少打几个字外,对 struct 用 typedef 没有好处,比如 stackoverflow 上 的提前声明例子,不用 typedef 也没问题:
  头文件:
    struct Point;
    struct Point* point_new(int x, int y);
  C 文件:
    struct Point {...};
  同样隐藏了 struct Point 的实现,只是多了 struct 而已。 用了 typedef ,只是看起来像是实现了一个类型,但对 C 语言的适用环境,反而可能是有害的。

用 C 语言编程,必须意识到代码编译后的物理形态,C 没有运行时防护措施,没有类型系统,程序员不仅要实现逻辑目标,为了安全和性能,还要(至少是有可能)设计&控制 指令、内存分布的实现,甚至要考虑 cache 的利用率,那么变量的物理形态是非常重要的信息,使用 typedef 无益于程序员理解当前代码。

如果代码只是为了实现逻辑目标(kernel 显然不是这样),那么 C 语言不是最佳选择,即使是这种情况下用 C 语言, struct 的 typedef 也有其问题,一旦使用,就难以阻止滥用。常见的一个例子,针对 struct 指针 typedef,如:
    typedef _Point {...} Point, *PPoint;
若是用 Pascal,  将 Point^ 定义为 PPoint, 不算有问题,毕竟没别的办法,Point^ 也不是一个单词。但 C 这么写,只会给基于 token 的索引工具制造麻烦,作为程序员,看到 PPoint 时,自然会联想到这是 struct _Point*, 或 Point*,  但是,谁能保证这是真的?也许在本模块的前面,已经被一个随便的家伙改成了 typedef unsigned int SmallPoint,*PPoint 了。所以,对 struct 使用 typedef, 是多余的无益行为。


个人签名training
 
 
 

回复

6423

帖子

16

TA的资源

版主

4
 
Linus 在内核编程规范第五章中,明确规定了不要对 struct 使用 typedef。

因此 Linux 内核代码应当尽量遵守该规范。简而言之,除非绝对必要,不要对指针和 struct 使用 typedef 。

至于为什么不要使用 typedef ,Linus 在文章中也已经解释得很清楚了。

参考:
https://www.kernel.org/doc/Documentation/CodingStyle

作者:pansz
链接:https://www.zhihu.com/question/20928231/answer/16632332
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
个人签名training
 
 
 

回复

6423

帖子

16

TA的资源

版主

5
 
linux的内核用了gcc很多专有扩展,根本没办法用其它编译器来编译,所以移植性特别差(雾)。所以我觉得作者根本不需要纠结这个问题。我举个例子:

int sum = ({
int r=0, i=0;
while(i<100) r+=++i;
r;
});
// 然后sum就等于5050了

作者:vczh
链接:https://www.zhihu.com/question/20928231/answer/18200251
来源:知乎
著作权归作者所有,转载请联系作者获得授权。
个人签名training
 
 
 

回复

6423

帖子

16

TA的资源

版主

6
 
请看这里:
http://lkml.iu.edu/hypermail/linux/kernel/0206.1/0402.html
Linux-Kernel Archive: Re: [PATCH] 2.5.21
个人签名training
 
 
 

回复

6423

帖子

16

TA的资源

版主

7
 
意义不明确是一个因素。

印象中遇到过因为用了 typedef 结构体名,和变量重名,导致程序编译出来的代码块异常的情况。更悲催的是编译器不提示不报错。
个人签名training
 
 
 

回复

6423

帖子

16

TA的资源

版主

8
 
  1. .. _codingstyle:

  2. Linux kernel coding style
  3. =========================

  4. This is a short document describing the preferred coding style for the
  5. linux kernel.  Coding style is very personal, and I won't **force** my
  6. views on anybody, but this is what goes for anything that I have to be
  7. able to maintain, and I'd prefer it for most other things too.  Please
  8. at least consider the points made here.

  9. First off, I'd suggest printing out a copy of the GNU coding standards,
  10. and NOT read it.  Burn them, it's a great symbolic gesture.

  11. Anyway, here goes:


  12. 1) Indentation
  13. --------------

  14. Tabs are 8 characters, and thus indentations are also 8 characters.
  15. There are heretic movements that try to make indentations 4 (or even 2!)
  16. characters deep, and that is akin to trying to define the value of PI to
  17. be 3.

  18. Rationale: The whole idea behind indentation is to clearly define where
  19. a block of control starts and ends.  Especially when you've been looking
  20. at your screen for 20 straight hours, you'll find it a lot easier to see
  21. how the indentation works if you have large indentations.

  22. Now, some people will claim that having 8-character indentations makes
  23. the code move too far to the right, and makes it hard to read on a
  24. 80-character terminal screen.  The answer to that is that if you need
  25. more than 3 levels of indentation, you're screwed anyway, and should fix
  26. your program.

  27. In short, 8-char indents make things easier to read, and have the added
  28. benefit of warning you when you're nesting your functions too deep.
  29. Heed that warning.

  30. The preferred way to ease multiple indentation levels in a switch statement is
  31. to align the ``switch`` and its subordinate ``case`` labels in the same column
  32. instead of ``double-indenting`` the ``case`` labels.  E.g.:

  33. .. code-block:: c

  34.         switch (suffix) {
  35.         case 'G':
  36.         case 'g':
  37.                 mem <<= 30;
  38.                 break;
  39.         case 'M':
  40.         case 'm':
  41.                 mem <<= 20;
  42.                 break;
  43.         case 'K':
  44.         case 'k':
  45.                 mem <<= 10;
  46.                 /* fall through */
  47.         default:
  48.                 break;
  49.         }

  50. Don't put multiple statements on a single line unless you have
  51. something to hide:

  52. .. code-block:: c

  53.         if (condition) do_this;
  54.           do_something_everytime;

  55. Don't put multiple assignments on a single line either.  Kernel coding style
  56. is super simple.  Avoid tricky expressions.

  57. Outside of comments, documentation and except in Kconfig, spaces are never
  58. used for indentation, and the above example is deliberately broken.

  59. Get a decent editor and don't leave whitespace at the end of lines.


  60. 2) Breaking long lines and strings
  61. ----------------------------------

  62. Coding style is all about readability and maintainability using commonly
  63. available tools.

  64. The limit on the length of lines is 80 columns and this is a strongly
  65. preferred limit.

  66. Statements longer than 80 columns will be broken into sensible chunks, unless
  67. exceeding 80 columns significantly increases readability and does not hide
  68. information. Descendants are always substantially shorter than the parent and
  69. are placed substantially to the right. The same applies to function headers
  70. with a long argument list. However, never break user-visible strings such as
  71. printk messages, because that breaks the ability to grep for them.


  72. 3) Placing Braces and Spaces
  73. ----------------------------

  74. The other issue that always comes up in C styling is the placement of
  75. braces.  Unlike the indent size, there are few technical reasons to
  76. choose one placement strategy over the other, but the preferred way, as
  77. shown to us by the prophets Kernighan and Ritchie, is to put the opening
  78. brace last on the line, and put the closing brace first, thusly:

  79. .. code-block:: c

  80.         if (x is true) {
  81.                 we do y
  82.         }

  83. This applies to all non-function statement blocks (if, switch, for,
  84. while, do).  E.g.:

  85. .. code-block:: c

  86.         switch (action) {
  87.         case KOBJ_ADD:
  88.                 return "add";
  89.         case KOBJ_REMOVE:
  90.                 return "remove";
  91.         case KOBJ_CHANGE:
  92.                 return "change";
  93.         default:
  94.                 return NULL;
  95.         }

  96. However, there is one special case, namely functions: they have the
  97. opening brace at the beginning of the next line, thus:

  98. .. code-block:: c

  99.         int function(int x)
  100.         {
  101.                 body of function
  102.         }

  103. Heretic people all over the world have claimed that this inconsistency
  104. is ...  well ...  inconsistent, but all right-thinking people know that
  105. (a) K&R are **right** and (b) K&R are right.  Besides, functions are
  106. special anyway (you can't nest them in C).

  107. Note that the closing brace is empty on a line of its own, **except** in
  108. the cases where it is followed by a continuation of the same statement,
  109. ie a ``while`` in a do-statement or an ``else`` in an if-statement, like
  110. this:

  111. .. code-block:: c

  112.         do {
  113.                 body of do-loop
  114.         } while (condition);

  115. and

  116. .. code-block:: c

  117.         if (x == y) {
  118.                 ..
  119.         } else if (x > y) {
  120.                 ...
  121.         } else {
  122.                 ....
  123.         }

  124. Rationale: K&R.

  125. Also, note that this brace-placement also minimizes the number of empty
  126. (or almost empty) lines, without any loss of readability.  Thus, as the
  127. supply of new-lines on your screen is not a renewable resource (think
  128. 25-line terminal screens here), you have more empty lines to put
  129. comments on.

  130. Do not unnecessarily use braces where a single statement will do.

  131. .. code-block:: c

  132.         if (condition)
  133.                 action();

  134. and

  135. .. code-block:: none

  136.         if (condition)
  137.                 do_this();
  138.         else
  139.                 do_that();

  140. This does not apply if only one branch of a conditional statement is a single
  141. statement; in the latter case use braces in both branches:

  142. .. code-block:: c

  143.         if (condition) {
  144.                 do_this();
  145.                 do_that();
  146.         } else {
  147.                 otherwise();
  148.         }

  149. 3.1) Spaces
  150. ***********

  151. Linux kernel style for use of spaces depends (mostly) on
  152. function-versus-keyword usage.  Use a space after (most) keywords.  The
  153. notable exceptions are sizeof, typeof, alignof, and __attribute__, which look
  154. somewhat like functions (and are usually used with parentheses in Linux,
  155. although they are not required in the language, as in: ``sizeof info`` after
  156. ``struct fileinfo info;`` is declared).

  157. So use a space after these keywords::

  158.         if, switch, case, for, do, while

  159. but not with sizeof, typeof, alignof, or __attribute__.  E.g.,

  160. .. code-block:: c


  161.         s = sizeof(struct file);

  162. Do not add spaces around (inside) parenthesized expressions.  This example is
  163. **bad**:

  164. .. code-block:: c


  165.         s = sizeof( struct file );

  166. When declaring pointer data or a function that returns a pointer type, the
  167. preferred use of ``*`` is adjacent to the data name or function name and not
  168. adjacent to the type name.  Examples:

  169. .. code-block:: c


  170.         char *linux_banner;
  171.         unsigned long long memparse(char *ptr, char **retptr);
  172.         char *match_strdup(substring_t *s);

  173. Use one space around (on each side of) most binary and ternary operators,
  174. such as any of these::

  175.         =  +  -  <  >  *  /  %  |  &  ^  <=  >=  ==  !=  ?  :

  176. but no space after unary operators::

  177.         &  *  +  -  ~  !  sizeof  typeof  alignof  __attribute__  defined

  178. no space before the postfix increment & decrement unary operators::

  179.         ++  --

  180. no space after the prefix increment & decrement unary operators::

  181.         ++  --

  182. and no space around the ``.`` and ``->`` structure member operators.

  183. Do not leave trailing whitespace at the ends of lines.  Some editors with
  184. ``smart`` indentation will insert whitespace at the beginning of new lines as
  185. appropriate, so you can start typing the next line of code right away.
  186. However, some such editors do not remove the whitespace if you end up not
  187. putting a line of code there, such as if you leave a blank line.  As a result,
  188. you end up with lines containing trailing whitespace.

  189. Git will warn you about patches that introduce trailing whitespace, and can
  190. optionally strip the trailing whitespace for you; however, if applying a series
  191. of patches, this may make later patches in the series fail by changing their
  192. context lines.


  193. 4) Naming
  194. ---------

  195. C is a Spartan language, and so should your naming be.  Unlike Modula-2
  196. and Pascal programmers, C programmers do not use cute names like
  197. ThisVariableIsATemporaryCounter.  A C programmer would call that
  198. variable ``tmp``, which is much easier to write, and not the least more
  199. difficult to understand.

  200. HOWEVER, while mixed-case names are frowned upon, descriptive names for
  201. global variables are a must.  To call a global function ``foo`` is a
  202. shooting offense.

  203. GLOBAL variables (to be used only if you **really** need them) need to
  204. have descriptive names, as do global functions.  If you have a function
  205. that counts the number of active users, you should call that
  206. ``count_active_users()`` or similar, you should **not** call it ``cntusr()``.

  207. Encoding the type of a function into the name (so-called Hungarian
  208. notation) is brain damaged - the compiler knows the types anyway and can
  209. check those, and it only confuses the programmer.  No wonder MicroSoft
  210. makes buggy programs.

  211. LOCAL variable names should be short, and to the point.  If you have
  212. some random integer loop counter, it should probably be called ``i``.
  213. Calling it ``loop_counter`` is non-productive, if there is no chance of it
  214. being mis-understood.  Similarly, ``tmp`` can be just about any type of
  215. variable that is used to hold a temporary value.

  216. If you are afraid to mix up your local variable names, you have another
  217. problem, which is called the function-growth-hormone-imbalance syndrome.
  218. See chapter 6 (Functions).


  219. 5) Typedefs
  220. -----------

  221. Please don't use things like ``vps_t``.
  222. It's a **mistake** to use typedef for structures and pointers. When you see a

  223. .. code-block:: c


  224.         vps_t a;

  225. in the source, what does it mean?
  226. In contrast, if it says

  227. .. code-block:: c

  228.         struct virtual_container *a;

  229. you can actually tell what ``a`` is.

  230. Lots of people think that typedefs ``help readability``. Not so. They are
  231. useful only for:

  232. (a) totally opaque objects (where the typedef is actively used to **hide**
  233.      what the object is).

  234.      Example: ``pte_t`` etc. opaque objects that you can only access using
  235.      the proper accessor functions.

  236.      .. note::

  237.        Opaqueness and ``accessor functions`` are not good in themselves.
  238.        The reason we have them for things like pte_t etc. is that there
  239.        really is absolutely **zero** portably accessible information there.

  240. (b) Clear integer types, where the abstraction **helps** avoid confusion
  241.      whether it is ``int`` or ``long``.

  242.      u8/u16/u32 are perfectly fine typedefs, although they fit into
  243.      category (d) better than here.

  244.      .. note::

  245.        Again - there needs to be a **reason** for this. If something is
  246.        ``unsigned long``, then there's no reason to do

  247.         typedef unsigned long myflags_t;

  248.      but if there is a clear reason for why it under certain circumstances
  249.      might be an ``unsigned int`` and under other configurations might be
  250.      ``unsigned long``, then by all means go ahead and use a typedef.

  251. (c) when you use sparse to literally create a **new** type for
  252.      type-checking.

  253. (d) New types which are identical to standard C99 types, in certain
  254.      exceptional circumstances.

  255.      Although it would only take a short amount of time for the eyes and
  256.      brain to become accustomed to the standard types like ``uint32_t``,
  257.      some people object to their use anyway.

  258.      Therefore, the Linux-specific ``u8/u16/u32/u64`` types and their
  259.      signed equivalents which are identical to standard types are
  260.      permitted -- although they are not mandatory in new code of your
  261.      own.

  262.      When editing existing code which already uses one or the other set
  263.      of types, you should conform to the existing choices in that code.

  264. (e) Types safe for use in userspace.

  265.      In certain structures which are visible to userspace, we cannot
  266.      require C99 types and cannot use the ``u32`` form above. Thus, we
  267.      use __u32 and similar types in all structures which are shared
  268.      with userspace.

  269. Maybe there are other cases too, but the rule should basically be to NEVER
  270. EVER use a typedef unless you can clearly match one of those rules.

  271. In general, a pointer, or a struct that has elements that can reasonably
  272. be directly accessed should **never** be a typedef.


  273. 6) Functions
  274. ------------

  275. Functions should be short and sweet, and do just one thing.  They should
  276. fit on one or two screenfuls of text (the ISO/ANSI screen size is 80x24,
  277. as we all know), and do one thing and do that well.

  278. The maximum length of a function is inversely proportional to the
  279. complexity and indentation level of that function.  So, if you have a
  280. conceptually simple function that is just one long (but simple)
  281. case-statement, where you have to do lots of small things for a lot of
  282. different cases, it's OK to have a longer function.

  283. However, if you have a complex function, and you suspect that a
  284. less-than-gifted first-year high-school student might not even
  285. understand what the function is all about, you should adhere to the
  286. maximum limits all the more closely.  Use helper functions with
  287. descriptive names (you can ask the compiler to in-line them if you think
  288. it's performance-critical, and it will probably do a better job of it
  289. than you would have done).

  290. Another measure of the function is the number of local variables.  They
  291. shouldn't exceed 5-10, or you're doing something wrong.  Re-think the
  292. function, and split it into smaller pieces.  A human brain can
  293. generally easily keep track of about 7 different things, anything more
  294. and it gets confused.  You know you're brilliant, but maybe you'd like
  295. to understand what you did 2 weeks from now.

  296. In source files, separate functions with one blank line.  If the function is
  297. exported, the **EXPORT** macro for it should follow immediately after the
  298. closing function brace line.  E.g.:

  299. .. code-block:: c

  300.         int system_is_up(void)
  301.         {
  302.                 return system_state == SYSTEM_RUNNING;
  303.         }
  304.         EXPORT_SYMBOL(system_is_up);

  305. In function prototypes, include parameter names with their data types.
  306. Although this is not required by the C language, it is preferred in Linux
  307. because it is a simple way to add valuable information for the reader.


  308. 7) Centralized exiting of functions
  309. -----------------------------------

  310. Albeit deprecated by some people, the equivalent of the goto statement is
  311. used frequently by compilers in form of the unconditional jump instruction.

  312. The goto statement comes in handy when a function exits from multiple
  313. locations and some common work such as cleanup has to be done.  If there is no
  314. cleanup needed then just return directly.

  315. Choose label names which say what the goto does or why the goto exists.  An
  316. example of a good name could be ``out_free_buffer:`` if the goto frees ``buffer``.
  317. Avoid using GW-BASIC names like ``err1:`` and ``err2:``, as you would have to
  318. renumber them if you ever add or remove exit paths, and they make correctness
  319. difficult to verify anyway.

  320. The rationale for using gotos is:

  321. - unconditional statements are easier to understand and follow
  322. - nesting is reduced
  323. - errors by not updating individual exit points when making
  324.   modifications are prevented
  325. - saves the compiler work to optimize redundant code away ;)

  326. .. code-block:: c

  327.         int fun(int a)
  328.         {
  329.                 int result = 0;
  330.                 char *buffer;

  331.                 buffer = kmalloc(SIZE, GFP_KERNEL);
  332.                 if (!buffer)
  333.                         return -ENOMEM;

  334.                 if (condition1) {
  335.                         while (loop1) {
  336.                                 ...
  337.                         }
  338.                         result = 1;
  339.                         goto out_buffer;
  340.                 }
  341.                 ...
  342.         out_free_buffer:
  343.                 kfree(buffer);
  344.                 return result;
  345.         }

  346. A common type of bug to be aware of is ``one err bugs`` which look like this:

  347. .. code-block:: c

  348.         err:
  349.                 kfree(foo->bar);
  350.                 kfree(foo);
  351.                 return ret;

  352. The bug in this code is that on some exit paths ``foo`` is NULL.  Normally the
  353. fix for this is to split it up into two error labels ``err_free_bar:`` and
  354. ``err_free_foo:``:

  355. .. code-block:: c

  356.          err_free_bar:
  357.                 kfree(foo->bar);
  358.          err_free_foo:
  359.                 kfree(foo);
  360.                 return ret;

  361. Ideally you should simulate errors to test all exit paths.


  362. 8) Commenting
  363. -------------

  364. Comments are good, but there is also a danger of over-commenting.  NEVER
  365. try to explain HOW your code works in a comment: it's much better to
  366. write the code so that the **working** is obvious, and it's a waste of
  367. time to explain badly written code.

  368. Generally, you want your comments to tell WHAT your code does, not HOW.
  369. Also, try to avoid putting comments inside a function body: if the
  370. function is so complex that you need to separately comment parts of it,
  371. you should probably go back to chapter 6 for a while.  You can make
  372. small comments to note or warn about something particularly clever (or
  373. ugly), but try to avoid excess.  Instead, put the comments at the head
  374. of the function, telling people what it does, and possibly WHY it does
  375. it.

  376. When commenting the kernel API functions, please use the kernel-doc format.
  377. See the files Documentation/kernel-documentation.rst and scripts/kernel-doc
  378. for details.

  379. The preferred style for long (multi-line) comments is:

  380. .. code-block:: c

  381.         /*
  382.          * This is the preferred style for multi-line
  383.          * comments in the Linux kernel source code.
  384.          * Please use it consistently.
  385.          *
  386.          * Description:  A column of asterisks on the left side,
  387.          * with beginning and ending almost-blank lines.
  388.          */

  389. For files in net/ and drivers/net/ the preferred style for long (multi-line)
  390. comments is a little different.

  391. .. code-block:: c

  392.         /* The preferred comment style for files in net/ and drivers/net
  393.        
复制代码


个人签名training
 
 
 

回复

6423

帖子

16

TA的资源

版主

9
 
Re: [PATCH] 2.5.21 - list.h cleanup

From: Linus Torvalds (torvalds@transmeta.com)
Date: Mon Jun 10 2002 - 12:21:36 EST
Next message: Manik Raina: "Re: [PATCH] 2.5.21 - list.h cleanup"
Previous message: Oliver Neukum: "Re: PCI DMA to small buffers on cache-incoherent arch"
In reply to: Thomas 'Dent' Mirlacher: "Re: [PATCH] 2.5.21 - list.h cleanup"
Next in thread: Rusty Russell: "Re: [PATCH] 2.5.21 - list.h cleanup"
Reply: Rusty Russell: "Re: [PATCH] 2.5.21 - list.h cleanup"
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
On Mon, 10 Jun 2002, Thomas 'Dent' Mirlacher wrote:
>
> On Mon, 10 Jun 2002, Linus Torvalds wrote:
>
> --snip/snip
> > But in the end, maintainership matters. I personally don't want the
> > typedef culture to get the upper hand, but I don't mind a few of them, and
> > people who maintain their own code usually get the last word.
>
> to sum it up:
>
> using the "struct mystruct" is _recommended_, but not a must.
Well, it's more than just "struct xx". It's really typedefs in general.
For example, some people like to do things like
        typedef unsigned int counter_t;
and then use "counter_t" all over the place. I think that's not just ugly,
but stupid and counter-productive. It makes it much harder to do things
like "printk()" portably, for example ("should I use %u, %l or just %d?"),
and generally adds no value. It only _hides_ information, like whether the
type is signed or not.
There is nothing wrong with just using something like "unsigned long"
directly, even if it is a few characters longer than you might like. And
if you care about the number of bits, use "u32" or something. Don't make
up useless types that have no added advantage.
We actually have real _problems_ due to this in the kernel, where people
use "off_t", and it's not easily printk'able across different
architectures (we used to have this same problem with size_t). We should
have just used "unsigned long" inside the kernel, and be done with it (and
"unsigned long long" for loff_t).
We should also have some format for printing out "u32/u64" etc, but that's
another issue and has the problem that gcc won't understand them, so
adding new formats is _hard_ from a maintenance standpoint.
                        Linus
PS. And never _ever_ make the "pointerness" part of the type. People who
write
        typedef struct urb_struct * urbp_t;
(or whatever the name was) should just be shot. I was _soo_ happy to see
that crap get excised from the kernel USB drivers.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Next message: Manik Raina: "Re: [PATCH] 2.5.21 - list.h cleanup"
Previous message: Oliver Neukum: "Re: PCI DMA to small buffers on cache-incoherent arch"
In reply to: Thomas 'Dent' Mirlacher: "Re: [PATCH] 2.5.21 - list.h cleanup"
Next in thread: Rusty Russell: "Re: [PATCH] 2.5.21 - list.h cleanup"
Reply: Rusty Russell: "Re: [PATCH] 2.5.21 - list.h cleanup"
Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]
This archive was generated by hypermail 2b29 : Sat Jun 15 2002 - 22:00:18 EST
个人签名training
 
 
 

回复

136

帖子

0

TA的资源

一粒金砂(中级)

10
 
typedef定义类型时好用
 
 
 

回复

3416

帖子

0

TA的资源

纯净的硅(高级)

11
 
一些集成环境里面,用typedef方便一些
这些IDE可能对此做过配置,错误的使用也会有警告或者错误
但是在另一些编译环境,特别是一些开源工具中,这个得小心了
楼主代码块异常的情况,俺也遇到过,坑
个人签名

So TM what......?

 

 
 

回复

406

帖子

1

TA的资源

一粒金砂(中级)

12
 
项目原有代码都是这样的,只能跟着用typedef
 
 
 

回复

6111

帖子

4

TA的资源

版主

13
 
值得注意。
 
 
 

回复
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表