块及其使用 [英] Blocks and Their Use

查看:50
本文介绍了块及其使用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个关于*使用*块的问题。


在Plauger的第6章xfmtval.c中的标准C库中我注意到了

函数_Fmtval(),经过50行左右的处理后,他创建了一个



char * _Fmtval(...)

{


/ * .. 50行左右的代码... * /


{/ * build fmt控制下的buf中的字符串* /

char * end,* s;

const char * g;

size_t i,ns;


for(s = buf; * fmt; ++ fmt,s + = strlen(s))

/ * ... * /


}

返回(buf);


} / *结束函数_Fmtval * /

我们都知道这是合法的,但我承认我之前没有见过这种技术

。 Plauger也在setlocal.c中使用了这个技术在同一个

章节。


是推荐这种技术,还是有警告?我可以看到一些C编码

指南不包括它的使用,如果没有具体的暗示,

或许。


刚刚在void函数中为现有文件添加了一些代码,我选择使用这种技术。它的形式如下:


if(error)

{

/ *报告错误* /

返回;

}


if(another_error)

{

/ *报告此错误* /

返回;

}


/ * ...还有一些错误检查... * /


/ *这里没有错误,开始处理* /

{

unsigned char c;

/ * ...更多定义... * /


/ * ...处理...... * /

}


我觉得这很有效,因为只有当上面找到的错误不存在时,块中定义的变量才是必需的。


有没有人对这种技术有任何建设性意见?


-

马丁

解决方案

" Martin" < martin.o_brien @ [no-spam] which.net:


我对*使用*块有疑问。


在Plauger的第6章xfmtval.c中的标准C库我注意到

函数_Fmtval()在经过50行左右的处理之后,他创建了一个

区块


char * _Fmtval(...)

{


/ *。 50行左右的代码... * /


{/ *在fmt控制下的buf构建字符串* /

char * end,* s;

const char * g;

size_t i,ns;


for(s = buf; * fmt; + + fmt,s + = strlen(s))

/ * ... * /


}

return(buf) ;


} / *结束函数_Fmtval * /


我们都知道这是合法的,但我承认我还没有看到这个技术。 Plauger也在同一章的

setlocal.c中使用了这种技术。


推荐这种技术,还是有警告?我可以看到一些

C编码指南,不包括它的使用,如果没有具体的那么可能是

暗示。



阅读完上述内容后,我对你的意思并不清楚

的这种技巧。在使用

技术之后读取代码,我看到你指的是为了声明局部变量而引入一个块来实现
的目的

前面的代码需要。 (主题词块和他们的使用应该已经说明了

我!)


是的,这是一种非常有效的技术,我看到了

风格上没有错。请注意,它并不一定能为您节省任何内存;你可以假设块中的变量不会被分配,除非你输入块,但是这不是

保证和编译器在进入

函数时可以自由分配所有函数的'b
局部变量(包括内部块中的变量)。 (我想,除了VLA之外。)但它确实清楚说明这些变量只在块中使用,这使得

代码更容易理解。 br />

尝试将end,s,g,i和ns的声明移到函数的开头

,在50行左右之上代码" ;.如果没有

仔细阅读所有50行,你就不能确定那些

变量的使用位置。


我是即将表示惊讶,代码在循环的每次迭代中重新计算

上的strlen。这是一个常见的新手错误

类似于:


for(i = 0; i< strlen(s); i ++) {

/ * ...代码使用s [i] ... * /

}


问题是strlen()必须扫描整个字符串,使得

循环为O(N ** 2)。将strlen(s)的值保存在一个变量中会使得它成为O(N),这是一个显着的改进。


但当然PJ Plauger没有'这样一个新手的错误。

strlen(s)*有*在每次迭代时重新计算,因为它在每次迭代时都会改变
。 s + = strlen(s)是指s + = strlen(s)。只是一个聪明的方式来将
推进指针直到下一个''\ 0''字符。


-

Keith Thompson(The_Other_Keith) ks***@mib.org < http://www.ghoti.net/~ kst>

圣地亚哥超级计算机中心< *< http://users.sdsc.edu/~kst>

"我们必须做点什么。这是事情。因此,我们必须这样做。

- Antony Jay和Jonathan Lynn,是部长


Martin写道:


我对* use * of blocks有疑问。



< snip>


>

刚刚将一些代码添加到void函数中的现有文件中,我

当选采用这种技术。它的形式如下:


if(error)

{

/ *报告错误* /

返回;

}


if(another_error)

{

/ *报告此错误* /

返回;

}


/ * ...还有一些错误检查... * /


/ *这里没有错误,开始处理* /

{

unsigned char c;

/ * ...更多定义... * /


/ * ...处理...... * /

}


我觉得这很有效,因为只有当上面找到的错误不存在时,块中定义的变量才是必需的。


有没有人对这种技术有任何建设性意见?



这是一个非常有效的技术,用于包含变量范围。

它也是一个强烈的暗示,块中的代码可能会更好

在它自己的功能中。


-

Ian Collins。


3月25日星期日2007 21:15:59 +0100,Martin

< martin.o_brien @ [no-spam] which.netwrote in comp.lang.c:


我有一个关于*使用*块的问题。


在Plauger的第6章xfmtval.c中的标准C库中,我注意到了

函数_Fmtval()经过50行左右的处理后,他创建了一个



char * _Fmtval(。 ..)

{


/ * .. 50行左右的代码... * /


{/ *在fmt的控制下在buf中构建字符串* /

char * end,* s;

const char * g;

size_t i,ns;


for(s = buf; * FMT; ++ fmt,s + = strlen(s))

/ * ... * /


}

return(buf );


} / *结束函数_Fmtval * /


我们都知道这是合法的,但我承认我没见过这种技巧
以前雇用
。 Plauger也在setlocal.c中使用了这个技术在同一个

章节。


是推荐这种技术,还是有警告?我可以看到一些C编码

指南不包括它的使用,如果没有具体的暗示,

或许。


刚刚在void函数中为现有文件添加了一些代码,我选择使用这种技术。它的形式如下:


if(error)

{

/ *报告错误* /

返回;

}


if(another_error)

{

/ *报告此错误* /

返回;

}


/ * ...还有一些错误检查... * /


/ *这里没有错误,开始处理* /

{

unsigned char c;

/ * ...更多定义... * /


/ * ...处理...... * /

}


我觉得这很有效,因为只有当上面找到的错误不存在时,块中定义的变量才是必需的。


有没有人对这种技术有任何建设性意见?



我使用添加块的技术仅仅是为了打开本地范围

最经常在我维护旧代码时,我自己或者有人

其他'。


不幸的是,有很多旧的C代码具有非常大的

功能和在函数定义的任何地方使用的所有变量

在顶部。


事实上,我已经在交换机中看到了C函数和几十个案例/>
语句,全部写在一行,其中一些计数器变量,

总是命名为''i',用于两个或三个案例,并且

定义在文件的顶部。


另一种方法是将每个案例处理程序放在自己的

范围内:


case''1'':

{

/ *如果需要定义变量* /

打破;

}


打开一个新的范围可以确保你可以定义新的

v ariables在函数中间添加代码并帮助你

避免意外修改现有的值,特别是

当不容易看到所有的地方可能会被使用的地方。


另一方面,我从来没有在新的

代码中定义本地范围。代码总是可以更好地构建。


在您的特定示例中,这可能是一种简化,您可以使用else打开该块,或者如果
打开该块。 。


-

Jack Klein

主页: http://JK-Technology.Com

常见问题解答

comp.lang.c http://c-faq.com/

comp.lang。 c ++ http://www.parashift.com/c++-faq-lite/

alt.comp.lang.learn.c-c ++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html


I have a question regarding *use* of blocks.

In Plauger''s THE STANDARD C LIBRARY in xfmtval.c in Chapter 6 I noticed in
function _Fmtval() that after some processing of 50 lines or so he creates a
block

char *_Fmtval( ... )
{

/* .. 50 lines or so of code ... */

{ /* build string in buf under control of fmt */
char *end, *s;
const char *g;
size_t i, ns;

for (s = buf; *fmt; ++fmt, s+= strlen(s))
/* ... */

}
return (buf);

} /* end function _Fmtval */

We all know this is legitimate, but I admit I have not seen this technique
employed before. Plauger also uses this technique in setlocal.c in the same
chapter.

Is this technique recommended, or are there caveats? I can see some C Coding
Guidelines excluding its use, if not specifically then by implication,
perhaps.

Having just added some code to an existing file in a void function, I
elected to employ this techique. It takes the form:

if ( error )
{
/* report error */
return;
}

if ( another_error )
{
/* report this error */
return;
}

/* ... a few more error checks ... */

/* no errors here, start processing */
{
unsigned char c;
/* ... more definitions ... */

/*... processing ... */
}

Which I think works well because the variables defined in the block are
necessary only if the errors looked for above are not present.

Has anyone any constructive comments about this technique?

--
Martin

解决方案

"Martin" <martin.o_brien@[no-spam]which.netwrites:

I have a question regarding *use* of blocks.

In Plauger''s THE STANDARD C LIBRARY in xfmtval.c in Chapter 6 I noticed in
function _Fmtval() that after some processing of 50 lines or so he creates a
block

char *_Fmtval( ... )
{

/* .. 50 lines or so of code ... */

{ /* build string in buf under control of fmt */
char *end, *s;
const char *g;
size_t i, ns;

for (s = buf; *fmt; ++fmt, s+= strlen(s))
/* ... */

}
return (buf);

} /* end function _Fmtval */

We all know this is legitimate, but I admit I have not seen this
technique employed before. Plauger also uses this technique in
setlocal.c in the same chapter.

Is this technique recommended, or are there caveats? I can see some
C Coding Guidelines excluding its use, if not specifically then by
implication, perhaps.

After reading the above, it wasn''t at all clear to me what you meant
by "this technique". Reading the code after that that uses the
technique, I see that you''re referring to introducing a block for the
purpose of declaring local variables that aren''t needed by the
preceding code. (The subject "Blocks and Their Use" should have clued
me in!)

Yes, that''s a perfectly valid technique, and I see nothing wrong with
it stylistically. Note that it doesn''t necessarily save you any
memory; you might assume that the variables in the block won''t be
allocated until and unless you enter the block, but that''s not
guaranteed, and a compiler is free to allocate all of a function''s
local variables (including ones in inner blocks) on entry to the
function. (Except for VLAs, I suppose.) But it does make it clear
that those variables are only used within the block, which makes the
code easier to understand.

Try moving the declarations of end, s, g, i, and ns to the beginning
of the function, above the "50 lines or so of code". Without
carefully reading all 50 lines, you can''t be sure where those
variables are used.

I was about to express surprise that the code recomputes strlen(s) on
each iteration of the loop. It''s a common newbie error to do
something like:

for (i = 0; i < strlen(s); i ++) {
/* ... code that uses s[i] ... */
}

The problem is that strlen() has to scan the entire string, making the
loop O(N**2). Saving the value of strlen(s) in a variable would make
it O(N), a significant improvement.

But of course P.J. Plauger didn''t make such a newbie mistake.
strlen(s) *has* to be recomputed on each iteration, because it changes
on each iteration. The "s += strlen(s)" is simply a clever way to
advance the pointer s up to the next ''\0'' character.

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <* <http://users.sdsc.edu/~kst>
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"


Martin wrote:

I have a question regarding *use* of blocks.

<snip>

>
Having just added some code to an existing file in a void function, I
elected to employ this techique. It takes the form:

if ( error )
{
/* report error */
return;
}

if ( another_error )
{
/* report this error */
return;
}

/* ... a few more error checks ... */

/* no errors here, start processing */
{
unsigned char c;
/* ... more definitions ... */

/*... processing ... */
}

Which I think works well because the variables defined in the block are
necessary only if the errors looked for above are not present.

Has anyone any constructive comments about this technique?

It is a perfectly valid technique for containing the scope of variables.
It is also a strong hint that the code in the block might be better off
in its own function.

--
Ian Collins.


On Sun, 25 Mar 2007 21:15:59 +0100, "Martin"
<martin.o_brien@[no-spam]which.netwrote in comp.lang.c:

I have a question regarding *use* of blocks.

In Plauger''s THE STANDARD C LIBRARY in xfmtval.c in Chapter 6 I noticed in
function _Fmtval() that after some processing of 50 lines or so he creates a
block

char *_Fmtval( ... )
{

/* .. 50 lines or so of code ... */

{ /* build string in buf under control of fmt */
char *end, *s;
const char *g;
size_t i, ns;

for (s = buf; *fmt; ++fmt, s+= strlen(s))
/* ... */

}
return (buf);

} /* end function _Fmtval */

We all know this is legitimate, but I admit I have not seen this technique
employed before. Plauger also uses this technique in setlocal.c in the same
chapter.

Is this technique recommended, or are there caveats? I can see some C Coding
Guidelines excluding its use, if not specifically then by implication,
perhaps.

Having just added some code to an existing file in a void function, I
elected to employ this techique. It takes the form:

if ( error )
{
/* report error */
return;
}

if ( another_error )
{
/* report this error */
return;
}

/* ... a few more error checks ... */

/* no errors here, start processing */
{
unsigned char c;
/* ... more definitions ... */

/*... processing ... */
}

Which I think works well because the variables defined in the block are
necessary only if the errors looked for above are not present.

Has anyone any constructive comments about this technique?

I use the technique of adding a block merely to open a local scope
most often when I am maintaining older code, my own or somebody
else''s.

There is, unfortunately, a lot of older C code with very large
functions and all the variables used anywhere in the function defined
at the top.

In fact, I have seen C functions with dozens of cases in a switch
statement, all written in line, where some counter variable,
invariably named ''i'', is used in two or three of the cases, and
defined way up at the top of the file.

The alternative is quite simply to put each case handler in its own
scope:

case ''1'':
{
/* define variables if needed */
break;
}

Opening a new scope allows you to make sure that you can define new
variables for added code in the middle of a function and helps you
avoid accidentally modifying the value of an existing on, especially
when it is not easy to see all the places where it might be used.

On the other hand, I never a block just to define a local scope in new
code. The code can always be structured better.

In your particular example, which could be a simplification, you could
open that block with an else or else if.

--
Jack Klein
Home: http://JK-Technology.Com
FAQs for
comp.lang.c http://c-faq.com/
comp.lang.c++ http://www.parashift.com/c++-faq-lite/
alt.comp.lang.learn.c-c++
http://www.club.cc.cmu.edu/~ajo/docs/FAQ-acllc.html


这篇关于块及其使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆