问题描述
我需要知道指针何时穿过整个数组->在它后面的第一个位置。 c中的示例代码:
unsigned int ar[10];
char *pointer = (char*) ar;
while(pointer != (char*) &ar[10]){
*pointer++ = 0xff
}
此示例是否可以将数组的每个元素设置为0xffffffff?
解决方法
原理是正确的,但是您忘了初始化指针,并在错误的位置递增了指针。宁可使用
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,sizeof ar);
另一方面,如果您真的想将unsigned int
设置为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.
}
,
在使用原始二进制文件时,建议使用无符号字符类型,例如uint8_t
而不是char
,因为后者具有实现定义的签名。
然后您可以利用C中的两个特殊规则:
C11 6.3.2.3/7
将对象的指针转换为字符类型的指针时, 结果指向对象的最低寻址字节。的连续增量 结果,直到对象的大小,才产生指向对象剩余字节的指针。
这允许我们使用字符指针检查或修改C中任何类型的原始二进制内容。因此,您确实可以使用字符指针将整数数组的每个字节设置为0xFF。
另一个特殊规则隐藏在加法运算符的工作方式之内,因为[]运算符只是+和取消引用周围的语法糖。 C11 6.5.6 / 8,重点是:
如果指针操作数和结果都指向同一数组对象的元素,或指向数组对象的最后一个元素,则求值不会产生溢出;否则,行为是不确定的。
这使我们可以检查数组末尾的地址1 int
。
但是在字符类型指针和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;
}