指针类型转换:对缓冲区长度的影响?

时间:2010-02-07 18:49:14

标签: c short unsigned-char

Char是1个字节 unsigned short是2个字节

因此,如果我将char *转换为unsigned short *,它会改变缓冲区的长度吗?

例如,我将char *和长度传递给VUMeter函数。该函数将char *转换为unsigned short *

short* pln = (short*) buffer;`

现在我遍历缓冲区,所以我可以使用传递的相同长度吗?

int peak=0;
short* pln = (short*) buffer;
for (int i=0; i<len; i++)
{
  if(abs(pln[i]) > peak)
     peak = abs(pln[i]);
}  

出于某种原因,我在循环中遇到了应用程序错误。

3 个答案:

答案 0 :(得分:1)

如果元素的大小加倍,那么你有一半的元素空间。转换指针不会调整它的大小,基本上假设你知道你在用指针做什么。

所以不,你不能真正把一个char *转换成一个简短的*并希望事情能够发挥作用。如果你需要一个short *,其值与char *相同,你需要分配一个短数组并从char *中单独复制元素。

答案 1 :(得分:0)

unsigned short可能是也可能不是2个字节。让我们看看你的例子的记忆。

+---+---+---+     +---+---+---+
|   |   |   | ... |   |   |   |
+---+---+---+     +---+---+---+

|<-------- len bytes -------->|

如果unsigned short长度为2个字节,则您的空间值为len/2 unsigned short。或者,更一般地说,您有len/n unsigned short个值的空间,其中n等于sizeof(unsigned short)

您无法将unsigned char *强制转换为unsigned char *并期望可以移植的内容。现在,要计算peak,这取决于你想要做什么。如果您想要找到len unsigned char个值的最大值,并将其保存到peak中,则循环显示值将起作用:

size_t i;
unsigned short peak = 0;
for (i=0; i < len; ++i) {
    if (buffer[i] > peak) {
        peak = buffer[i];
    }
}

但是,如果您希望将sizeof(unsigned short)值“合并”为一个unsigned short值,那么您最好的选择是手动计算数字。

假设len可被n和big-endian存储整除,您可以执行以下操作(未经测试):

#include <stdio.h>
#include <limits.h> 

size_t factor = sizeof(unsigned short);
size_t n = len / factor;
size_t i;
unsigned short peak = 0;
if (len % factor != 0) {
    fprintf(stderr, "Extra data at the end\n");
}   
for (i=0; i < n; ++i) {
    size_t j;
    unsigned short test = 0;
    for (j=0; j < factor; ++j) {
        test = (test << CHAR_BIT)  + buffer[i*factor+j];
    }
    if (test > peak) {
        peak = test;
    }
}

答案 2 :(得分:0)

在调用* alloc()之前,分配的内存不会更改。数据类型大小不同的事实只会影响“步长”(“x + 1”将指向x + 2个字节),但是你可以有一半的元素。

就个人而言,我会避免简单地使用指针。它可能会使已经存在于内存块中的数据被误读(现在将两个单独的字节读取为单个值,与填充缓冲区时使用的1字节值完全不同:两个后续值127, 127将成为单个值:65535,那种事情)。而且我认为它也会在编译器中发出警告(至少GCC抱怨这样的演员)。我想你应该做的是:

int x = SOMEVAL;
char * cptr = malloc(x*sizeof(char));
/* some code here - fill cptr with data */
uint16 * sptr = malloc(x*sizeof(uint16));
int i;
for (i = 0; i < x; i++) {
    *(sptr+i) = (uint16)(*(cptr+i));
}
free(cptr);

除非我快速编写的代码中有一些错误(我没有费心去检查),它应该做你想要实现的目标:“cast”从char *到uint16 *的指针,但也安全地复制数据没有改变值(除非chars中有负值,ofc)。