用于为unsset提供unsigned char的宏 [英] Macro for supplying memset with an unsigned char

查看:67
本文介绍了用于为unsset提供unsigned char的宏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我正在尝试提供一个完全可移植的宏来提供memset

和unsigned char而不是int。当我走的时候,我要大声思考

。 。 。


我会在开始之前采用一个示例系统:


CHAR_BIT == 16

sizeof (短)== sizeof(int)== 1

假设所有整数类型都没有填充位

符号大小


因此我们有:


UCHAR_MAX == 65535

INT_MIN = -32767

INT_MAX = 32767


假设我们有一个字节数组,我们想将每个字节设置为

65000.我们不能使用:


memset(数据,65000,sizeof数据);


因为从无符号整数类型到有符号整数的转换

types是实现定义的或一个实现定义的信号

被提出如果数字超出范围。


因此我们需要提供一个带有int值的memset,其中,转换为unsigned char的
将产生我们想要的价值。


从签名转换为无签名的规则如下:


|如果新类型未签名,则转换值为
|通过反复添加或减去一个以上的
|可以在

|中表示的最大值新类型,直到值在新类型的范围内。


添加方法更容易理解,所以我们将使用那个。

如果我们从负数开始,比如-1,那么这就是

会发生什么:


char unsigned c = -1;


等于:


infinite_range_int x = -1; / *让我们假装我们有一个签名的

int类型可以保存任何数字* /


while(0 x || UCHAR_MAX< x )x + = UCHAR_MAX +

(infinite_range_int)1;


char unsigned c = x;


所以在我们自己的系统上,这是:


而(0 x || 65535< x)x + = 65536;


显然,如果x = -1,那么它只需要循环的一次迭代来获得65535,即UCHAR_MAX。


因此,如果我们想要UCHAR_MAX-1 ,然后我们将使用(int)-2。

对于UCHAR_MAX-2,我们将使用(int)-3。


整套数据看起来像:


int char unsigned

-1 65535

-2 65534

-3 65533

-4 65532

-5 65531

-6 65530

-7 65529

-8 65528

-9 65527
-10 65526

-11 65525

-12 65524

....

....

-32764 32772

-32765 32771

-32766 32770

-32767 32769

-32768 32768< -


现在我刚刚意识到问题。 unsigned char可以存储65536

不同的组合(即0到65535),但int只能

存储65535个不同的组合(即-32767到32767)如果我们' '

使用除了两个补码以外的东西。我不知道我会做什么

,但是现在我会尝试继续使用另外两个数字

系统:


#if NUMBER_SYSTEM!= SIGN_MAGNITUDE


#define UC_AS_INT(x)/ *无论我们要做什么* /
< br $>
#endif


我的第一个想法是:


#define UC_AS_INT(x)UC_AS_INT_Internal((char) unsigned)(x))


#define UC_AS_INT_Internal(x)(x INT_MAX \

? - (int)(UCHAR_MAX - x) - 1 \\
:(int)x)


无论如何,这是星期五我要做的事情,但是如果有人想完成的话/>
它关闭然后随意! :)


如果我们无法从一个补码中获得所有65536个组合,或者在
级别上获得所有65536个组合,那么我们就可以得到一个宏将其更改为:


char unsigned * p = data;

char unsigned const * const pover = data + sizeof data;

while(pover!= p)* p ++ = c;


Martin


I''m trying to come up with a fully-portable macro for supplying memset
with an unsigned char rather than an int. I''m going to think out loud
as I go along. . .

I''ll take a sample system before I begin:

CHAR_BIT == 16
sizeof(short) == sizeof(int) == 1
Assume none of the integer types have padding bits
Sign-magnitude

Therefore we have:

UCHAR_MAX == 65535
INT_MIN = -32767
INT_MAX = 32767

Let''s say we have an array of bytes and we want to set every byte to
65000. We CANNOT use:

memset(data, 65000, sizeof data);

because the conversion from unsigned integer types to signed integer
types "is implementation-defined or an implementation-defined signal
is raised" if the number is out of range.

Therefore we need to supply memset with an int value, which, went
converted to unsigned char, will yield the value we want.

The rules for converting from signed to unsigned are as follows:

| If the new type is unsigned, the value is converted
| by repeatedly adding or subtracting one more than
| the maximum value that can be represented in the
| new type until the value is in the range of the new type.

The addition method is easier to understand so we''ll go with that one.
If we start off with a negative number like -1, then here''s what will
happen:

char unsigned c = -1;

is equal to:

infinite_range_int x = -1; /* Let''s pretend we have a signed
int type that can hold any number */

while (0 x || UCHAR_MAX < x) x += UCHAR_MAX +
(infinite_range_int)1;

char unsigned c = x;

So on our own system, this is:

while (0 x || 65535 < x) x += 65536;

Clearly, if x = -1, then it only takes one iteration of the loop to
yield 65535, i.e. UCHAR_MAX.

Therefore, if we want UCHAR_MAX-1, then we''d use (int)-2.
For UCHAR_MAX-2, we''d use (int)-3.

The entire set of data looks something like:

int char unsigned
-1 65535
-2 65534
-3 65533
-4 65532
-5 65531
-6 65530
-7 65529
-8 65528
-9 65527
-10 65526
-11 65525
-12 65524
....
....
-32764 32772
-32765 32771
-32766 32770
-32767 32769
-32768 32768 <--

Now I''ve just realised a problem. An unsigned char can store 65536
different combinations (i.e. 0 through 65535), but an int can only
store 65535 different combination (i.e. -32767 through 32767) if we''re
using something other than two''s complement. I don''t know what I''ll do
about that, but for now I''ll try continue with the other two number
systems:

#if NUMBER_SYSTEM != SIGN_MAGNITUDE

#define UC_AS_INT(x) /* Whatever we''re going to do */

#endif

My first thought is something like:

#define UC_AS_INT(x) UC_AS_INT_Internal( (char unsigned)(x) )

#define UC_AS_INT_Internal(x) ( x INT_MAX \
? -(int)(UCHAR_MAX - x) - 1 \
: (int)x )

Anyway it''s Friday an I''ve stuff to do, but if anyone wants to finish
it off then feel free! :)

If we can''t get all 65536 combinations out of one''s complement or sign-
magnitude, then we can just have a macro that changes it to:

char unsigned *p = data;
char unsigned const *const pover = data + sizeof data;
while (pover != p) *p++ = c;

Martin

推荐答案

Martin Wells写道:
Martin Wells wrote:

>

我正在尝试提供一个完全可移植的宏来提供memset

使用unsigned char而不是int。当我走的时候,我要大声思考

。 。 。


我会在开始之前采用一个示例系统:


CHAR_BIT == 16

sizeof (短)== sizeof(int)== 1

假设所有整数类型都没有填充位

符号大小


因此我们有:


UCHAR_MAX == 65535

INT_MIN = -32767

INT_MAX = 32767


假设我们有一个字节数组,我们想将每个字节设置为

65000.我们不能使用:


memset(数据,65000,sizeof数据);


因为从无符号整数类型到有符号整数的转换

types是实现定义的或一个实现定义的信号

被提出如果数字超出范围。
>
I''m trying to come up with a fully-portable macro for supplying memset
with an unsigned char rather than an int. I''m going to think out loud
as I go along. . .

I''ll take a sample system before I begin:

CHAR_BIT == 16
sizeof(short) == sizeof(int) == 1
Assume none of the integer types have padding bits
Sign-magnitude

Therefore we have:

UCHAR_MAX == 65535
INT_MIN = -32767
INT_MAX = 32767

Let''s say we have an array of bytes and we want to set every byte to
65000. We CANNOT use:

memset(data, 65000, sizeof data);

because the conversion from unsigned integer types to signed integer
types "is implementation-defined or an implementation-defined signal
is raised" if the number is out of range.



是否可以将unsigned char设置为65000

是实现定义的,

所以'没有什么不错

有一个实现定义的方式。


-

pete

Whether or not you can set an unsigned char to 65000
is implementation defined,
so there''s nothing wrong
with an implementation defined way of doing it.

--
pete


pete:
pete:

是否可以将unsigned char设置为65000

是实现定义的,

所以没有什么不错

有一个实现定义的方法。
Whether or not you can set an unsigned char to 65000
is implementation defined,
so there''s nothing wrong
with an implementation defined way of doing it.



之所以我提到像65535这样的具体数字而不是
UCHAR_MAX,我认为人们会发现它更容易理解和

掌握。


关键是我们是否可以将65000分配给一个int,而不是

我们是否可以分配(UCHAR_MAX - some_small_number)到int和

在每个可实现的实现上都有相同的结果。


为了清楚起见,我会重写我原来的帖子取出混凝土

数字。请记住,代码是在上下文中写的

它是完全可移植的(例如97位字符和符号量级):

让'假设我们有一个字节数组,我们想将每个字节设置为

(UCHAR_MAX - 4)。我们不能使用:

memset(数据,UCHAR_MAX - 4,sizeof数据);

因为从无符号整数类型到有符号整数的转换

类型是实现定义的或实现定义的信号

被提出如果数字超出范围。 (所以在完全

可移植编程的上下文中,结果int可能有几乎任何值b / b $ b值因为UCHAR_MAX可能大于INT_MAX)。


因此我们需要为memset提供一个int值,这个值转换为unsigned char,将产生我们想要的值。


从签名转换为无签名的规则如下:


|如果新类型未签名,则转换值为
|通过反复添加或减去一个以上的
|可以在

|中表示的最大值新类型,直到值在新类型的范围内。


添加方法更容易理解,所以我们将使用

一个。

如果我们从负数开始,比如-1,那么这就是

会发生什么:

char unsigned c = -1;

等于:

infinite_range_int x = -1; / *让我们假装我们有一个签名的

int类型可以保存任何数字* /

而(0 x || UCHAR_MAX< x)x + = UCHAR_MAX +

(infinite_range_int)1;

char unsigned c = x;

所以这里有一些关于不同会发生什么的样本系统:

while(0 x || 255< x)x + = 256;

while(0 x || 65535< x)x + = 65536;

while(0 x || 4294967295< x)x + = 4294967296;

while(0 x || 18446744073709551615< x)x + =

18446744073709551616;


如果x = -1,那么只需要循环一次迭代就可以在任何实现中产生UCHAR_MAX。 />

因此,如果我们想要UCHAR_MAX-1,那么我们将使用(int)-2。

对于UCHAR_MAX-2,我们将使用( int)-3。

整个数据集如下所示:

int char unsigned

-1 UCHAR_MAX

-2 UCHAR_MAX-1

-3 UCHAR_MAX-2

-4 UCHAR_MAX-3

-5 UCHAR_MAX-4

-6 UCHAR_MAX-5

-7 UCHAR_MAX-6

-8 UCHAR_MAX-7

-9 UCHAR_MAX-8

-10 UCHAR_MAX-9

-11 UCHAR_MAX-10

-12 UCHAR_MAX-11

....

....

现在我刚刚意识到一个问题。想象一个系统,其中unsigned char

的范围是0到65535,其中int有-32767到32767.

前者有65536种可能的组合,而后者只有

65535种组合。我们可能不得不求助于一个循环如果使用

而不是两个补码,但我还不确定。


无论如何这是我现在的代码,我从你的旧帖子中剥夺了一些它的价格:


#define SIGNMAG 0

#define ONES 1

#define TWOS 2


#if -1& 3 == 1

#define NUM_SYS SIGNMAG

#elif -1& 3 == 2

#define NUM_SYS ONES

#else

#define NUM_SYS TWOS

#endif

#if NUM_SYS!= TWOS / * ----------- * /


#include< stddef.h>


static void * uc_memset(void * const pv,char unsigned const val,size_t

const len)

{

char * p = pv;

char const * const pover = p + len;


while(pover!= p)* p ++ = val ;


返回pv;

}


#define UC_MEMSET(p,uc,len)(uc_memset( p,uc,len))


#else / * ------------ * /


# include< string.h>


#define UC_AS_INT(x)UC_AS_INT_Internal((char unsigned)(x))


#define UC_AS_INT_Internal (x)(x INT_MAX \

? - (int)(UCHAR_MAX - x) - 1 \

:(int)x)


#define UC_MEMSET(p,uc,len)(memset((p),UC_AS_INT((uc)),(len)))


#endif / * ----------- * /


#include< limits.h>


int main(无效)

{

char无符号数据[24];


UC_MEMSET(数据,UCHAR_MAX,sizeof数据);


返回0;

}


如果你有更好的方法,可随意进行改动!


Martin


" Martin Wells" < wa **** @eircom.netaécritdansle message de news:
11 ******** @ r29g2000hsg.googlegroups。 com ...

< snip>
"Martin Wells" <wa****@eircom.neta écrit dans le message de news:
11**********************@r29g2000hsg.googlegroups. com...
<snip>

>

现在我刚刚意识到问题。想象一个系统,其中unsigned char

的范围是0到65535,其中int有-32767到32767.

前者有65536种可能的组合,而后者只有

65535种组合。如果使用

而不是两个补码,我们可能不得不求助于循环,但我还不确定。
>
Now I''ve just realised a problem. Imagine a system where unsigned char
has the range 0 through 65535 and where int has -32767 through 32767.
The former has 65536 possible combinations while the latter only has
65535 combinations. We might have to resort to a loop if working with
something other than two''s complement, but I''m not sure yet.



由于这个原因和其他类似的原因,如果不是不可能的话,在一个架构上实现一个完全一致的托管C环境是很困难的。

非二进制补码表示和sizeof(int)== 1同时。


幸运的是,非二进制补码架构只能在博物馆

今天。

For this and other similar reasons, it would be difficult if not impossible
to implement a fully conformant hosted C envirinment on an architecture with
non twos-complement representation and sizeof(int) == 1 at the same time.

Luckily, non twos-complement architectures can only be found in museums
today.


无论如何这里是我现在的代码,我从
中删除了一些代码。
旧帖子你的皮特:


#define SIGNMAG 0

#define ONES 1

#define TWOS 2


#if -1& 3 == 1

#define NUM_SYS SIGNMAG

#elif -1& 3 == 2

#define NUM_SYS ONES

#else

#define NUM_SYS TWOS

#endif
Anyway here''s the code I have at the moment, I robbed some of it from
old posts of yours pete:

#define SIGNMAG 0
#define ONES 1
#define TWOS 2

#if -1 & 3 == 1
#define NUM_SYS SIGNMAG
#elif -1 & 3 == 2
#define NUM_SYS ONES
#else
#define NUM_SYS TWOS
#endif



这些测试不正确有两个原因:


*``-1& 3 == 1''''被解释为``-1& (3 == 1)''''在所有平台上产生0为




*无法保证预处理的执行时间相同

表示为目标体系结构。事实上,嵌入式

目标与不寻常的算术目标通常是交叉编译器的目标

在不同的机器上运行。


令人遗憾的是,整数表示无法在预处理阶段进行充分测试。 sizeof(int)== 1无法评估为

预处理器。


只能测试来自< limits.h>的宏:


#if INT_MIN == -INT_MAX

/ *我们的目标是非二元补码架构* /

#如果INT_MAX< ; UCHAR_MAX

/ *休斯顿,我们有问题! * /

#define MEMSET_IS_INADEQUATE 1

#endif

#define NUM_SYS ONES_OR_SIGNMAG

#else

#define NUM_SYS TWOS

#endif

-

Chqrlie。

These tests are incorrect for two reasons:

* ``-1 & 3 == 1'''' is interpreted as ``-1 & (3 == 1)'''' which yields 0 for
all platforms.

* There is no guarantee that the preprocessing be performed with the same
representation as the target architecture. As a matter of fact, embedded
targets with unusual arithmetics are often targetted by cross compilers
running on different machines.

It is a sad fact that integer representation cannot be adequately tested at
the preprocessing stages. sizeof(int) == 1 cannot be evaluated be the
preprocessor.

One can only test the macros from <limits.h>:

#if INT_MIN == -INT_MAX
/* we are targetting a non twos-complement architecture */
# if INT_MAX < UCHAR_MAX
/* Houston, we have a problem! */
# define MEMSET_IS_INADEQUATE 1
# endif
# define NUM_SYS ONES_OR_SIGNMAG
#else
# define NUM_SYS TWOS
#endif
--
Chqrlie.


这篇关于用于为unsset提供unsigned char的宏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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