0

我需要知道指针何时穿过整个数组 -> 位于它后面的第一个位置。c中的示例代码:

unsigned int ar[10];
char *pointer = (char*) ar;
while(pointer != (char*) &ar[10]){
*pointer++ = 0xff
}

此示例是否可以将数组的每个元素设置为 0xffffffff?

4

2 回答 2

1

原理是正确的,但是您忘记初始化指针并在错误的位置递增它。而是使用

unsigned int ar[10];
unsigned char *pointer = (unsigned char *)ar;
unsigned char *end = (unsigned char *)&ar[10];
while (pointer != end) { 
    *pointer++ = 0xff;
}

如果您在比较中增加指针,那么您将不会设置第一个字节并将写入一个字节超出限制。

但永远不要重新发明轮子。<string.h>为此有一个功能:

unsigned int ar[10];
memset(ar, 0xff, 10 * sizeof (int));

// or if a static array,
memset(ar, 0xff, sizeof ar);

另一方面,如果您真的想将unsigned ints 设置为 UINT_MAX,那么您可以明确:

for (size_t i = 0; i < 10; i++) {
    ar[i] = UINT_MAX; // or you could use `-1` as well, as it is guaranteed to result in `UINT_MAX` after conversion.
}
于 2020-09-04T10:18:46.910 回答
0

使用原始二进制文件时,我建议使用无符号字符类型,例如uint8_t代替char,因为后者具有实现定义的符号。

然后,您可以利用 C 中的两个特殊规则:

C11 6.3.2.3/7

当指向对象的指针转换为指向字符类型的指针时,结果指向对象的最低寻址字节。结果的连续增量,直到对象的大小,产生指向对象剩余字节的指针。

这允许我们使用字符指针检查或修改 C 中任何类型的原始二进制内容。因此,您确实可以使用字符指针将整数数组的每个字节设置为 0xFF。

另一个特殊规则隐藏在加法运算符的工作原理中,因为 [] 运算符只是 + 和取消引用的语法糖。C11 6.5.6/8,强调我的:

如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则计算不应产生溢出;否则,行为未定义。

这允许我们检查int超出数组末尾的地址 1。

然而,字符类型指针和int指针之间的转换会创建未对齐的指针,并且(至少在理论上)会调用未定义的行为和可能的指令陷阱。因此,您不能只将字符指针转换为整数指针并进行比较。

所以完全正确的方法是增加字符指针,sizeof(int)然后在循环中每圈设置 4 个字节。

这意味着以下是设置数组中所有字节的明确定义(但繁琐且难以阅读)的方式:

#include <stdio.h>
#include <stdint.h>

int main (void)
{
  unsigned int arr[10];
  
  for(uint8_t* i = (uint8_t*)arr; (unsigned int*)i != &arr[10]; i+=sizeof(unsigned int))
  {
    i[0] = 0xFF;
    i[1] = 0xFF;
    i[2] = 0xFF;
    i[3] = 0xFF;
  }
  
  for(size_t i=0; i<10; i++)
  {
    printf("%X\n", arr[i]);
  }

  return 0;
}
于 2020-09-04T10:23:00.860 回答