以下代码计算数组'buf'中值为'1'的位数:
long bit_count(long *arr, int size)
{
int w,b;
unsigned long word=0;
long n = 0;
for(w = 0; w<size ; w++){
word = arr[w];
while(word != 0){
n += word & 1;
word >>= 1;
}
}
return n;
}
int main() {
char buf[] = {"There is always one more!"}; //(1)
int length = strlen(buf)>>3; //(2)
long *a = (long*) (buf + length); //(3)
//char * b = (char *)a; // this is a comment. //(4)
int len = strlen((char*)a); //(5)
long total_count = bit_count((long*) buf, length); //(6)
*a = (*a) & (((long)1<<(len*8))-1); //(7)
char *c = (char*)a; //(8)
total_count += bit_count(a,1); //(9)
printf("bits number %ld\n",total_count); //(10)
return 0;
}
这是我对代码的理解:(如果我错了,请纠正我,我想在最深层次上理解它)
在第(2)行中,它们计算出buf中25个字母的字符数,相当于25个字节。导致char的大小是1个字节。然后通过将该3位向右移动它们将其除以8,8定义8字节= 1长类型。所以这个buf数组包含多少“long”。
第(3)行 - 'a'指向一个值,该值包含将行的其余部分转换为(long *)
- 在第(4)行中,我看到b *值将是“!” 这正好是数组中1个字节的剩余部分。但我真的不明白,(long *)
如果我检查,铸造到我得到的价值是不同的
long check = (long) (buf + length);
那么当我做什么时会发生什么 - {(long*)buf}
是我的第一个问题。
在第(6)行中,我对数组第一部分的位进行计数(按长整数),并在行(9)中对余数中的位进行计数。
我不明白的是 - 第(7)行发生了什么?
发布于 2018-06-26 15:45:22
(2) int length = strlen(buf)>>3;
这条线计算出long
适合字符串的整个对象数量,假设它long
是八个字节(/ sizeof(long)
应该用来代替>>3
),并且它int
足够大以容纳数字(size_t
应该用来代替int
)。
(3) long *a = (long*) (buf + length);
这似乎打算设置a
为指向不足以包含另一个long
对象的字符串末尾的片段。但是,因为length
是一些long
对象并buf
充当指针char
,所以其算术运算不正确。它计算buf
加上length
char
对象时,它打算计算buf
加length
long
对象。它应该使用(long *) buf + length
。此外,它假设char *
任意对齐可以明智地转换为a long *
,这是C标准所不能保证的。
(5) int len = strlen((char*)a);
这将计算片段中的字节数。这是一种浪费,因为代码先前计算了字符串的长度。它可以节省那么长的时间,并将商数和余数取模为大小long
而不是strlen
再次调用。
(6) long total_count = bit_count((long*) buf, length);
这将计算在缓冲区的主要部分中设置的位数,也就是被视为一些整数long
对象的部分。与之前的转换一样,它假设a char *
可以转换为a long *
,并且进一步调用的例程使用该指针long
从未定义为数组的对象中读取对象long
,从而违反了C别名规则。
(7) *a = (*a) & (((long)1<<(len*8))-1);
回想一下,a
指向字符串中的一些尾部字节数。(long)1<<(len*8)
假设字节是8位(CHAR_BIT
应该用来代替8
),移动一点到略高于该字节数。(例如,如果有两个字节,则会创建值10000 16)。然后减去1将为字节创建一个位掩码(示例中为FFFF 16)。然后*a
尝试long
从字符串的末尾读取一个字符串,之后应用掩码&
将读取的值减少为字符串中的字节。这不仅违反了C的别名规则,而且还在内存之外读取buf
,这具有未定义的行为。最后,该语句将更新的值写入*a
,这更糟糕 - 如果你不在阅读范围之外buf
,现在代码在外面写buf
,导致某处不明的腐败。
(8) char *c = (char*)a;
这条线是无用的,因为c
从来没有使用过。
(9) total_count += bit_count(a,1);
这将计算long
在(7)中更新的位数。
在bit_count
例程中,我们发现代码正在逐个计数位。这是荒谬的。如果使用特定的C实现允许使用未对齐的地址进行别名,则违反关于别名的C规则可能对于处理整个long
对象而不是单个char
对象有一定的性能好处。但是这个代码只是逐位处理; 它不会从处理器上的某些位计数(也称为总体计数)指令中获得任何优势。
此外,bit_count
例行程序认识到它应该unsigned long
用于位计数,因为它定义word
为unsigned long
。但它没有认识到它应该在unsigned long
整个过程中使用,因为它long
可能有陷阱表示会导致代码失败。
它也定义b
而不用它。
https://stackoverflow.com/questions/-100005523
复制相似问题