首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何用C打印1位(不仅是最不重要的位)?

如何用C打印1位(不仅是最不重要的位)?
EN

Stack Overflow用户
提问于 2022-04-09 05:50:16
回答 3查看 119关注 0票数 0

我正在编写一个发送TCP报头的程序(模拟3次握手).我有一个变量,这个变量包含数据偏移(3位)、保留(4位)和9标志(9位)。我使用按位操作来设置位。问题是,我如何打印每一个这些比特?

  1. 假设我从2到4(从左到右):ex存储数据偏移量。0111000000000000

我怎么打印这3位呢?变量:

代码语言:javascript
复制
u_int16_t reserved_ofs_flags;

我发现这个问题类似,但答案只适用于最不重要的问题:我怎么打印一点?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2022-04-09 07:31:21

要从从位置N开始的unsigned值中提取P位,从0中提取最小有效位数,可以使用以下表达式:

代码语言:javascript
复制
unsigned x = (value >> P) & ((1U << (N - 1) << 1) - 1);

备注:

  • 从左到右对位进行编号是一个令人困惑的惯例。在软件中,首选的编号方法是从最小有效位(数字0)到最重要位(示例中的数字15 )。
  • 如果N是编译时间常数,则在编译时计算表达式((1U << (N - 1) << 1) - 1)
  • 表达式假定N至少是1,最多是unsigned类型中的位数。
  • 如果((1U << N) - 1)N类型中的位数,则更简单的表达式unsigned具有未定义的行为。
  • 例如,P12N3,所以您可以编写:unsigned x = (value >> 12) & 7;
票数 5
EN

Stack Overflow用户

发布于 2022-04-09 06:11:03

您可以使用按位运算获取所需的位。

例如:

代码语言:javascript
复制
unsigned int a = 22;           // 10110 in binary
printf("%d\n", a & 1);         // get the bit in the 1's place (0)
printf("%d\n", (a >> 1) & 1);  // get the bit in the 2's place (1)
printf("%d\n", (a >> 2) & 1);  // get the bit in the 4's place (1)
printf("%d\n", (a >> 3) & 1);  // get the bit in the 8's place (0)
printf("%d\n", (a >> 4) & 1);  // get the bit in the 16's place (1)

// 3 in decimal is 11 in binary
printf("%d\n", a & 3);         // get the bits in the 1's and the 2's places
                               // (2 in decimal, 10 in binary)
printf("%d\n", (a >> 1) & 3);  // get the bits in the 2's and the 4's places
                               // (3 in decimal, 11 in binary)
票数 4
EN

Stack Overflow用户

发布于 2022-04-09 09:19:08

如果我理解您的问题,并且您希望能够提取N位数的值(从1sizeof(type) * CHAR_BIT),从P位置开始(从0sizeof(type) * CHAR_BIT - 1),那么您可以使用以下方法提取该位的子集:

代码语言:javascript
复制
/** extract N bits from value starting at position P, 
 *  counting from 0 for the least significant bit
 */
unsigned nbitsatp (unsigned value, unsigned N, unsigned P)
{
  /* mask is N 1's bits */
  unsigned mask = ~0u >> ((sizeof mask * CHAR_BIT) - N); 
  
  return (value >> (P - N + 1)) & mask;
}

(注意:表示4字节unsignedN132P是基于零的从031的范围)

上面,mask以所有比特1 (~0u)开始,然后从位的总数减去N (留下N 1的比特)。然后,valueP - N + 1移位,这样您就可以在P位置用相应的1位位数来AND所需的位数。由于两者都被移动,所以值开始于最小有效位,因此结果是N位在P位置的值。

这就避免了硬编码您想要的每一个位的数量和个别位位置。

在您的示例中,您希望从0111000000000000 (28672)中提取前3位,这将是positon P == 15上的3位N == 3,其结果是011 (3)。

--一个简短的示例

下面的示例使用unsigned作为类型,只要它在硬件上至少是2字节,对于uint16_t类型就足够了。

代码语言:javascript
复制
#include <stdio.h>
#include <limits.h>

/** extract N bits from value starting at position P, 
 *  counting from 0 for the least significant bit
 */
unsigned nbitsatp (unsigned value, unsigned N, unsigned P)
{
  /* mask is N 1's bits */
  unsigned mask = ~0u >> ((sizeof mask * CHAR_BIT) - N); 
  
  return (value >> (P - N + 1)) & mask;
}

int main (void) {

  unsigned v, n, p;
  
  fputs ("enter v, n, p : ", stdout);    /* prompt for v, n, p */
  
  /* read/validate positive int value */
  if (scanf ("%u%u%u", &v, &n, &p) != 3) {
    fputs ("error: invalid unsigned integer input.\n", stderr);
    return 1;
  }
  
  /* output result */
  printf ("\nvalue of %u bits at pos %u in %u is : %u\n", 
          n, p, v, nbitsatp (v, n, p));
}

示例使用/输出

您希望3位开始于28672的15位置的具体示例

代码语言:javascript
复制
$ ./bin/nbitsatp
enter v, n, p : 28672 3 15

value of 3 bits at pos 15 in 28672 is : 3

或者让我们把前4位放在第15位,0111 (7):

代码语言:javascript
复制
$  ./bin/nbitsatp
enter v, n, p : 28672 4 15

value of 4 bits at pos 15 in 28672 is : 7

或从第15位置开始的前5位:

代码语言:javascript
复制
$ ./bin/nbitsatp
enter v, n, p : 28672 5 15

value of 5 bits at pos 15 in 28672 is : 14

或者,在您的示例中,9-标志(9位,位置8)的值将为零。

代码语言:javascript
复制
$ ./bin/nbitsatp
enter v, n, p : 28672 9 8

value of 9 bits at pos 8 in 28672 is : 0

使用预定义的宏检索想要的位

使用nbitsatp()函数检索您感兴趣的位的一种方便方法是为您想要获得的每一组位设置一个#define宏。例如,要获得数据偏移量的3位、保留的4位和9位标志集,您可以定义三个宏,这些宏设置位数和位置,允许您将TCP头值简单地作为参数传递。

代码语言:javascript
复制
/* macros for 3-bit offset, 4-bit reserved, 9-bit flags */
#define HDR_OFFSET(TCPHDRVAL) nbitsatp ((TCPHDRVAL), 3, 15)
#define HDR_RESERVED(TCPHDRVAL) nbitsatp ((TCPHDRVAL), 4, 12)
#define HDR_FLAGS(TCPHDRVAL) nbitsatp ((TCPHDRVAL), 9, 8)

要获得所需的位,只需调用传递TCP标头值的宏作为参数。

代码语言:javascript
复制
int main (void) {

  unsigned v;
  
  fputs ("enter TCP hdr value : ", stdout);   /* prompt TCP HDR VAL */
  
  /* read/validate TCP header value */
  if (scanf ("%u", &v) != 1) {
    fputs ("error: invalid unsigned integer input.\n", stderr);
    return 1;
  }
  
  /* output result */
  printf ("\n   data offset bits : %u\n"
          "   reserved bits    : %u\n"
          "   flag bits        : %u\n", 
          HDR_OFFSET (v), HDR_RESERVED (v), HDR_FLAGS (v));
}

输出

代码语言:javascript
复制
$ /bin/nbitsatp_macro
enter TCP hdr value : 28672

   data offset bits : 3
   reserved bits    : 8
   flag bits        : 0

如果需要,可以以简单的方式输出3 (011)、8 (1000)和标志(000000000)的填充二进制表示。请参阅函数中的binprnpad()函数

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71805577

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档