Variadic函数使用参数列表调用可变参数函数,HLL位在LE处理器上移位 [英] Variadic functions calling variadic functions with the argument list, HLL bit shifts on LE processors

查看:48
本文介绍了Variadic函数使用参数列表调用可变参数函数,HLL位在LE处理器上移位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述






我希望你能帮我理解varargs设施。


说我我在ISO C编程,包括stdarg.h,我声明了一个

函数:


void log_printf(const char * logfilename,const char * formatter, ...);


然后,我想这样称呼:


int i = 1;

const char * s =" string";


log_printf(" logfile.txt"," Int:%d String%s",i,s);


然后,在log_printf的定义中我有一些东西

这个:


void log_printf( const char * logfilename,const char * formatter,...){


va_list ap;


FILE * logfile;

if(logfilename == NULL){return; }

if(formatter == NULL){return; }

logfile = fopen(logfilename," a");

if(logfile == NULL){return; }


va_start(ap,formatter);


fprintf(logfile,formatter,ap);


va_end(ap);


fprintf(logfile," \ n");

fclose(logfile);

返回;


}


正如您所见,我想用其可变参数列表调用fprintf

与传递给log_printf的参数列表相同。


请解释(a)此函数的正确实现。我看了一下C参考手册和Schildt的方便的C / C ++程序员的

参考和各种平台的手册和文档。 />
对此表示关注,并且不太明白。我搜索va_start(ap,

fmt)。

然后,我也有一些关于转换小端

处理器的问题。作为强制性的时事性理由,在comp.lang.c上,性能问题是关于C的问题。无论如何,在HLL C中,当你将$ 32 $无效符号值向右移动32位无符号值0x00010000时,结果

等于0x00008000。现在,在小端架构上,

在内存中表示为

$ b $ 00 00 01 01


和然后


00 80 00 00


在LE寄存器中,它的代表是


00 00 01 00


然后在HLL中向右移动一点导致

$ b $ 00 00 80 00 00


但是人们希望右移指令的shr能够支付
而不是:

$ b $ 00 00 00 00 80


所以我想知道除了使用汇编程序指令还有

其他众所周知的高级语言方法用于转移,

尤其如此一位移位和8位的倍数

移位。


这基本上是关于msb-> lsb位填充顺序之间的冲突但是

LSB-> MSB,LE或Little-Endian字节顺序,相应地在

lsb-> msb和MSB-> LSB,BE或Big-E之间ndian,在高水平转移方面

和指令级别转移。我没有反编译LE机器上的

编译器的输出,也许那将是最直接的方式来获得
看看编译器如何完成跨越字节的位移

保留数值的边界,但如果你碰巧知道

,那将会很有趣并且值得赞赏。我基本上是用b $ b来看一下扫描仪的汇编程序的基本必要性。在HLL中可以很容易地完成它,我只关心编译器指令生成的微不足道的问题。


这是另一个问题,但它是关于链接器的。比如说,一个单位

包含多个符号,默认情况下有extern存储

类。我想这取决于链接器是否要在模块的所有符号中绘制,或者将已使用的符号从已编译的模块中拉出来。我在gcc的输出处看了

,并且它绘制了未使用的符号,只是

,因为使用了同一编译单元中的其他符号。 for

例如:


[空格:〜/ Desktop / fc_test] nm构建/测试

....

00003c7c T _fc_mem_free

00003c38 T _fc_mem_malloc

00003cc4 T _fc_mem_realloc

00003d10 T _fc_mem_stackalloc

00003d6c T _fc_mem_stackfree

....


所有这些定义都在相同的汇编或翻译中

单位,但仅限于fc_mem_stackalloc和fc_mem_stackfree实际上是使用了
,并且没有理由将该代码放在输出中。我

将优化更改为-O3,不必要的符号仍然是

那里。


[空格:〜/桌面/ fc_test] space%cc -v

从/usr/libexec/gcc/darwin/ppc/2.95.2/specs阅读规格

Apple Computer,Inc。版本gcc- 926,基于gcc版本2.95.2

19991024(发布)


将编译单元划分为每个

编译单元只包含一个函数,但是它变得非常笨重,因为这个项目中的一些翻译单元有几十个几乎相同的功能,如果我可以提示链接器删除不必要的代码,我宁愿没有数百个源代码来获取b $ b代码文件。

链接到静态库的一些程序只需要一个那些

数百个生成的函数。


所以:


1.变量函数参数称为变量函数?

2. HLL转移在Little-Endian上?

3.链接器提示不需要的符号除了编译成单独的

单位


然后我有一些问题关于信号的最佳实践,Microsoft

SEH或结构化异常处理,可移植性和运行时

longjmp的依赖关系和东西。


谢谢!


Ross F.

解决方案

Ross A. Finlayson写道:



我希望你能帮我理解varargs工具。

说我在ISO C编程,包括stdarg.h和我声明一个
函数如下:

void log_printf(const char * logfilename,const char * formatter,...);

然后,我想打电话它如此:

int i = 1;
const char * s =" string";

log_printf(" logfile.txt"," Int:%d String%s",i,s);

然后,在log_printf的定义中我h顺便提一下这个:

void log_printf(const char * logfilename,const char * formatter,...){

va_list ap;

FILE * logfile;
if(logfilename == NULL){return; }
if(formatter == NULL){return; } log / = logfile = fopen(logfilename," a");
if(logfile == NULL){return; }

va_start(ap,formatter);

fprintf(logfile,formatter,ap);

va_end(ap);

fprintf(logfile," \ n");
fclose(logfile);
返回;

}

当你可以看到我想用其变量参数列表调用fprintf
这是与传递给log_printf的参数列表相同。


Yuo想要vfprintf();这就是它的用途。
然后,我也有一些关于转换小端处理器的问题。作为强制性的时事性理由,C的性能问题是关于comp.lang.c的主题。无论如何,在HLL C时


Erm,不 - 至少不在实施水平。


[snip]

1.变量函数参数将被称为可变参数函数?
2. HLL在Little-Endian上移位?
3.链接器提示不需要的符号除了编译成单独的
单元


特定链接器的操作在这里不是主题。
然后我对信号的最佳实践,Microsoft
SEH或结构化异常处理,可移植性和运行时有一些疑问
依赖longjmp和东西。

谢谢!

Ross F。




HTH ,

- $

-

Artie Gold - 德克萨斯州奥斯汀
http://it-matters.blogspot.com (新帖子12/5)
http://www.cafepress.com/goldsays

< br>

Artie Gold写道:

特定链接器的操作在这里不是主题。


然后我有一些关于信号的最佳实践,
Microsoft SEH或结构化异常处理,可移植性和运行时
longjmp的依赖性和东西。

谢谢!

罗斯F。



HTH,
- g
-
Artie Gold - 德克萨斯州奥斯汀
http://it-matters.blogspot.com (新帖子12/5)
http://www.cafepress.com/goldsays




谢谢!


是的,vfprintf正是我所需要的。

http://www.cppreference.com/stdio/vp..._vsprintf.html


关于链接器,一些链接器只会小心地提取所需的

符号,这是一个链接器和链接器选项相关的问题。虽然

就是这样,但它影响了C程序的设计,因为没有mryiad链接器可以减少

代码的生成

配置,然后最终成为数百个b $ b b编译单元的混乱。


关于LE架构的HLL转换,它通常不会问题,

,想要考虑设计HLL C

语言源代码的良好实践,无需重新配置即可使用

生成指令执行的处理器。


关于信号和东西,这基本上是关于垫片,以及其他

考虑因素比方说,有一个库组件分配堆

内存,报告错误和其他运行时方面。


再次感谢。

Ross F.


>我希望你能帮我理解varargs设施。


说我在ISO C编程,包括stdarg.h,我声明了一个
函数:

void log_printf(const char * logfilename,const char * formatter,...);

然后,我想这样称呼:

int i = 1;
const char * s =" ; string" ;;

log_printf(" logfile.txt"," Int:%d String%s",i,s);

然后,在定义中log_printf的内容我的内容如下:

void log_printf(const char * logfilename,const char * formatter,...){

va_list ap;

FILE * logfile;
if(logfilename == NULL){return; }
if(formatter == NULL){return; } log / = logfile = fopen(logfilename," a");
if(logfile == NULL){return; }

va_start(ap,formatter);

fprintf(logfile,formatter,ap);


存在vfprintf()函数的唯一原因是

处理这类问题。

va_end (ap);

fprintf(logfile," \ n");
fclose(logfile);
return;

}

然后,我也有一些关于转换小端处理器的问题。作为强制性的时事性理由,C的性能问题是关于comp.lang.c的主题。无论如何,在HLL C中,当你将32位无符号值0x00010000向右移一位时,结果
等于0x00008000。


是的,不管字节顺序如何。你应该编写程序

所以他们不关心字节序。

现在,在内存中表示为的小端架构

00 00 01 00

00/00 00 00

在LE寄存器上,它的表示是


没有LE注册这样的东西。在最受欢迎的CPU

架构上。寄存器具有它们具有的任何宽度,并且对值进行

移位。许多

CPU上的寄存器的一个关键特性是它们没有内存地址,因此没有

具有字节序。

00 00 01 00

然后在HLL中向右移动一点导致

00 80 00 00

但是人们希望shr for转移正确的指令将转而离开:

00 00 00 80

所以我想知道除了使用汇编程序指令还有其他众所周知的方法用于移位的高级语言,特别是在一位移位和八位移位的倍数方面。


编译器需要使用汇编程序指令。

并不是它可以做的其他事情。你期待魔法吗?

Transmute Endianness咒语?

这基本上是关于msb-> lsb位填充顺序之间的冲突但是
LSB-> ; MSB,LE或Little-Endian字节顺序,相应地在
lsb-> msb和MSB-> LSB,BE或Big-Endian之间,在高电平移位和指令电平转换方面。


有什么冲突?移位操作通常直接映射到

汇编语言移位指令。有时候换一个变量

金额可能需要使用一个循环。


它正在转移一个价值。

我还没有在LE机器上反编译
编译器的输出,这可能是最直接的方式来看看编译器在跨越字节边界的位移上做了什么来保留数字价值,但如果你碰巧知道
,那将是有趣和赞赏的。


值在寄存器中移位。注册表没有字节边界,

或至少不是那些有所不同的,性能明智。

我基本上是在看着用于扫描器的汇编程序的基本必要性。它很容易在HLL中完成,我只关心编译器指令生成的琐碎问题。

这是另一个问题,但它''关于链接器。比如说,一个单元
包含多个符号,默认情况下有extern存储类。我想这取决于链接器要么绘制模块的所有符号,要么将已使用的符号从已编译的模块中拉出来。我在gcc的输出处查看,并且它绘制了未使用的符号,只是因为使用了同一编译单元中的某些其他符号。


你能建议一种方法让gcc确定对象的哪一部分

根据想要的符号和哪些符号而忽略?

这并不容易。

示例:

[space:〜/ Desktop / fc_test] nm构建/测试 ...
00003c7c T _fc_mem_free
00003c38 T _fc_mem_malloc
00003cc4 T _fc_mem_realloc
00003d10 T _fc_mem_stackalloc
00003d6c T _fc_mem_stackfree
...

所有这些定义都在相同的编译或翻译单元中,但实际上只使用了fc_mem_stackalloc和fc_mem_stackfree,并且没有理由将该代码放在输出中。我将优化更改为-O3,不必要的符号仍然存在。

[空格:〜/ Desktop / fc_test]空间%cc -v
阅读来自/usr/libexec/gcc/darwin/ppc/2.95.2/specs的规格
Apple Computer,Inc。版本gcc-926,基于gcc版本2.95.2
19991024(发布)

分割编译单元是一个考虑因素,因此每个编译单元只包含一个功能,但是这个功能非常笨重,因为这个项目中的一些翻译单元有几十个几乎相同的函数,如果我能暗示链接器删除不必要的代码,我宁愿没有数百个源代码文件。
一些链接到静态库的程序只需要其中一个数百个生成的函数。

所以:

1。变量函数参数将被称为可变参数函数?
2。 HLL转向Little-Endian?
3。链接器提示不需要的符号除了编译成单独的
单元

然后我对信号的最佳实践有一些疑问,Microsoft
SEH或结构化异常处理,可移植性和运行时 longjmp和东西的依赖。

谢谢!

Ross F。



Gordon L. Burditt



Hi,

I hope you can help me understand the varargs facility.

Say I am programming in ISO C including stdarg.h and I declare a
function as so:

void log_printf(const char* logfilename, const char* formatter, ...);

Then, I want to call it as so:

int i = 1;
const char* s = "string";

log_printf("logfile.txt", "Int: %d String %s", i, s);

Then, in the definition of log_printf I have something along the lines
of this:

void log_printf(const char* logfilename, const char* formatter, ...){

va_list ap;

FILE* logfile;
if(logfilename == NULL) { return; }
if(formatter == NULL) { return; }
logfile = fopen(logfilename, "a");
if( logfile == NULL ) { return; }

va_start(ap, formatter);

fprintf(logfile, formatter, ap );

va_end(ap);

fprintf(logfile, "\n");
fclose(logfile);
return;

}

As you can see I want to call fprintf with its variable argument list
that is the same list of arguments as passed to log_printf.

Please explain the (a) correct implementation of this function. I
looked to the C Reference Manual and Schildt''s handy C/C++ Programmer''s
Reference and various platform''s man pages and documentation with
regards to this, and don''t quite get it. I search for va_start(ap,
fmt).
Then, also I have some questions about shift on little-endian
processors. As an obligatory topicality justification, performance
issues of C are on-topic on comp.lang.c. Anyways, in the HLL C when
you shift the 32 bit unsigned value 0x00010000 one bit right the result
is equal to 0x00008000. Now, on little-endian architectures that is
represented in memory as

00 00 01 00

and then

00 80 00 00

On the LE register as well, its representation is

00 00 01 00

and then shifting it one bit right in the HLL leads to

00 80 00 00

but one would hope that the shr for shift right instruction would
instead leave:

00 00 00 80

so I am wondering if besides using assembler instructions there are
other well known methods in the high level language for shifting,
particularly in terms of one bit shift and multiples of eight bit
shifts.

That''s basically about the conflict between msb->lsb bit fill order but
LSB->MSB, LE or Little-Endian byte order, and correspondingly between
lsb->msb and MSB->LSB, BE or Big-Endian, in terms of high level shift
and instruction level shift. I have not decompiled the output of the
compiler on the LE machine, maybe that would be the most direct way to
see what the compiler does to accomplish bit shifts across byte
boundaries that preserve numeric values, but if you happen to know
offhand, that would be interesting and appreciated. I''m basically
looking at the basic necessity of assembler for a bit scanner. It is
acceptably easily done in the HLL, I''m just concerned about trivial
issues of compiler instruction generation.

Here''s another question, but it''s about the linker. Say, a unit
contains multiple symbols, that have by default the extern storage
class. I guess it''s up to the linker to either draw in all symbols of
the module or pull the used symbols out of the compiled module. I look
at the output with gcc, and it draws in symbols that are unused, just
because some other symbol in the same compilation unit is used. for
example:

[space:~/Desktop/fc_test] nm Build/test
....
00003c7c T _fc_mem_free
00003c38 T _fc_mem_malloc
00003cc4 T _fc_mem_realloc
00003d10 T _fc_mem_stackalloc
00003d6c T _fc_mem_stackfree
....

All of those definitions are in the same compilation or translation
unit, but only fc_mem_stackalloc and fc_mem_stackfree are actually
used, and there is no reason for that code to be in the output. I
change the optimization to -O3 and the unnecessary symbols are still
there.

[space:~/Desktop/fc_test] space% cc -v
Reading specs from /usr/libexec/gcc/darwin/ppc/2.95.2/specs
Apple Computer, Inc. version gcc-926, based on gcc version 2.95.2
19991024 (release)

It''s one consideration to divide the compilation units so that each
compilation unit contains only one function, but that gets very bulky,
as some of the translation units in this project have dozens of nearly
identical functions, and I would rather not have hundreds of source
code files if I could hint to the linker to remove unnecessary code.
Some programs linking to the static library only need one of those
hundreds of generated functions.

So:

1. variadic function arguments going to called variadic function?
2. HLL shift on Little-Endian?
3. linker hints for unneeded symbols besides compiling into separate
units

Then I have some questions about best practices with signals, Microsoft
SEH or Structured Exception Handling, portability and runtime
dependency of longjmp, and stuff.

Thank you!

Ross F.

解决方案

Ross A. Finlayson wrote:

Hi,

I hope you can help me understand the varargs facility.

Say I am programming in ISO C including stdarg.h and I declare a
function as so:

void log_printf(const char* logfilename, const char* formatter, ...);

Then, I want to call it as so:

int i = 1;
const char* s = "string";

log_printf("logfile.txt", "Int: %d String %s", i, s);

Then, in the definition of log_printf I have something along the lines
of this:

void log_printf(const char* logfilename, const char* formatter, ...){

va_list ap;

FILE* logfile;
if(logfilename == NULL) { return; }
if(formatter == NULL) { return; }
logfile = fopen(logfilename, "a");
if( logfile == NULL ) { return; }

va_start(ap, formatter);

fprintf(logfile, formatter, ap );

va_end(ap);

fprintf(logfile, "\n");
fclose(logfile);
return;

}

As you can see I want to call fprintf with its variable argument list
that is the same list of arguments as passed to log_printf.

Yuo want vfprintf(); that''s exactly what it''s for.
Then, also I have some questions about shift on little-endian
processors. As an obligatory topicality justification, performance
issues of C are on-topic on comp.lang.c. Anyways, in the HLL C when
Erm, no -- at least not at the implementation level.

[snip]

1. variadic function arguments going to called variadic function?
2. HLL shift on Little-Endian?
3. linker hints for unneeded symbols besides compiling into separate
units
The operation of particular linkers is not topical here.
Then I have some questions about best practices with signals, Microsoft
SEH or Structured Exception Handling, portability and runtime
dependency of longjmp, and stuff.

Thank you!

Ross F.



HTH,
--ag
--
Artie Gold -- Austin, Texas
http://it-matters.blogspot.com (new post 12/5)
http://www.cafepress.com/goldsays


Artie Gold wrote:

The operation of particular linkers is not topical here.


Then I have some questions about best practices with signals, Microsoft SEH or Structured Exception Handling, portability and runtime
dependency of longjmp, and stuff.

Thank you!

Ross F.



HTH,
--ag
--
Artie Gold -- Austin, Texas
http://it-matters.blogspot.com (new post 12/5)
http://www.cafepress.com/goldsays



Thanks!

Yeah that vfprintf is just what I needed.

http://www.cppreference.com/stdio/vp..._vsprintf.html

About the linker, some linkers do carefully extract only the needed
symbols, and it is a linker and linker option dependent issue. While
that is so, it affects the design of the C program, because to have the
code generation be of reduced size without mryiad linker
configurations, then there ends up being the clutter of hundreds of
compilation units.

About the HLL shift on LE architecture, it generally doesn''t matter,
yet, in wanting to consider good practices for the design of the HLL C
language source code to be used without reconfiguration with respect to
the processor upon which the generated instructions execute.

About the signals and stuff, that''s basically about a shim, and other
considerations of, say, having a library component allocate heap
memory, report errors, and other runtime aspects.

Hey thanks again.

Ross F.


>I hope you can help me understand the varargs facility.


Say I am programming in ISO C including stdarg.h and I declare a
function as so:

void log_printf(const char* logfilename, const char* formatter, ...);

Then, I want to call it as so:

int i = 1;
const char* s = "string";

log_printf("logfile.txt", "Int: %d String %s", i, s);

Then, in the definition of log_printf I have something along the lines
of this:

void log_printf(const char* logfilename, const char* formatter, ...){

va_list ap;

FILE* logfile;
if(logfilename == NULL) { return; }
if(formatter == NULL) { return; }
logfile = fopen(logfilename, "a");
if( logfile == NULL ) { return; }

va_start(ap, formatter);

fprintf(logfile, formatter, ap );
The only reason for the existence of the vfprintf() function is to
deal with this kind of problem.

va_end(ap);

fprintf(logfile, "\n");
fclose(logfile);
return;

}
Then, also I have some questions about shift on little-endian
processors. As an obligatory topicality justification, performance
issues of C are on-topic on comp.lang.c. Anyways, in the HLL C when
you shift the 32 bit unsigned value 0x00010000 one bit right the result
is equal to 0x00008000.
Yes, regardless of endianness. You are supposed to write programs
so they don''t care about endianness.
Now, on little-endian architectures that is
represented in memory as

00 00 01 00

and then

00 80 00 00

On the LE register as well, its representation is
There''s no such thing as a "LE register" on most popular CPU
architectures. Registers have whatever width they have, and the
shift is done on the value. A key feature of registers on many
CPUs is that they do not have a memory address and therefore do not
have endianness.

00 00 01 00

and then shifting it one bit right in the HLL leads to

00 80 00 00

but one would hope that the shr for shift right instruction would
instead leave:

00 00 00 80

so I am wondering if besides using assembler instructions there are
other well known methods in the high level language for shifting,
particularly in terms of one bit shift and multiples of eight bit
shifts.
The compiler needs to use assembler instructions. There
isn''t much else that it CAN do. You were expecting magic?
Transmute Endianness incantations?
That''s basically about the conflict between msb->lsb bit fill order but
LSB->MSB, LE or Little-Endian byte order, and correspondingly between
lsb->msb and MSB->LSB, BE or Big-Endian, in terms of high level shift
and instruction level shift.
What conflict? A shift operation generally maps directly to an
assembly-language shift instruction. Sometimes a shift for a variable
amount might have to use a loop.

It''s shifting a VALUE.
I have not decompiled the output of the
compiler on the LE machine, maybe that would be the most direct way to
see what the compiler does to accomplish bit shifts across byte
boundaries that preserve numeric values, but if you happen to know
offhand, that would be interesting and appreciated.
A value gets shifted in a register. Registers don''t HAVE byte boundaries,
or at least not ones that make any difference, performance wise.
I''m basically
looking at the basic necessity of assembler for a bit scanner. It is
acceptably easily done in the HLL, I''m just concerned about trivial
issues of compiler instruction generation.

Here''s another question, but it''s about the linker. Say, a unit
contains multiple symbols, that have by default the extern storage
class. I guess it''s up to the linker to either draw in all symbols of
the module or pull the used symbols out of the compiled module. I look
at the output with gcc, and it draws in symbols that are unused, just
because some other symbol in the same compilation unit is used. for
Can you suggest a way for gcc to determine what part of the object
to leave out based on which symbols are wanted and which aren''t?
It''s not easy.
example:

[space:~/Desktop/fc_test] nm Build/test
...
00003c7c T _fc_mem_free
00003c38 T _fc_mem_malloc
00003cc4 T _fc_mem_realloc
00003d10 T _fc_mem_stackalloc
00003d6c T _fc_mem_stackfree
...

All of those definitions are in the same compilation or translation
unit, but only fc_mem_stackalloc and fc_mem_stackfree are actually
used, and there is no reason for that code to be in the output. I
change the optimization to -O3 and the unnecessary symbols are still
there.

[space:~/Desktop/fc_test] space% cc -v
Reading specs from /usr/libexec/gcc/darwin/ppc/2.95.2/specs
Apple Computer, Inc. version gcc-926, based on gcc version 2.95.2
19991024 (release)

It''s one consideration to divide the compilation units so that each
compilation unit contains only one function, but that gets very bulky,
as some of the translation units in this project have dozens of nearly
identical functions, and I would rather not have hundreds of source
code files if I could hint to the linker to remove unnecessary code.
Some programs linking to the static library only need one of those
hundreds of generated functions.

So:

1. variadic function arguments going to called variadic function?
2. HLL shift on Little-Endian?
3. linker hints for unneeded symbols besides compiling into separate
units

Then I have some questions about best practices with signals, Microsoft
SEH or Structured Exception Handling, portability and runtime
dependency of longjmp, and stuff.

Thank you!

Ross F.


Gordon L. Burditt


这篇关于Variadic函数使用参数列表调用可变参数函数,HLL位在LE处理器上移位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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