我正在使用raw pcm
将输入mp3
流转换为lame
。该库中的编码函数返回mp3
类型数组中的unsigned char
个编码样本。这个mp3编码的流现在需要放在flv
容器中,该容器使用在char
数组中写入编码样本的函数。我的问题是我将数组从lame
(类型unsigned char
)传递到flv
库。以下代码(仅符号)说明了我的问题:
/* cast from unsigned char to char. */
#include <stdio.h>
#include <stdlib.h>
void display(char *buff, int len) {
int i = 0;
for(i = 0; i < len; i++) {
printf("buff[%d] = %c\n", i, buff[i]);
}
}
int main() {
int len = 10;
unsigned char* buff = (unsigned char*) malloc(len * sizeof(unsigned char));
int i = 0;
for(i = 65; i < (len + 65); i++) {
buff[i] = (unsigned char) i;
printf("char = %c", (char) i);
}
printf("Displaying array in main.\n");
for(i = 0; i < len; i++) {
printf("buff[%d] = %u\n", i, 'buff[i]');
}
printf("Displaying array in func.\n");
display(buff, len);
return 0;
}
我的问题:
1.下面代码中的隐式类型转换(通过将buff
传递给函数display
来证明是否安全?是否可能发生一些奇怪的行为?
2.鉴于我没有其他选择,只能坚持现有的功能,是否有一种“安全”的方式将unsigned char
s数组转换为char
s?
答案 0 :(得分:5)
将unsigned char *
转换为char *
(反之亦然)的唯一问题是假设是错误。用演员表修复它。
display((char *) buff, len);
注意:此演员表是不必要的:
printf("char = %c", (char) i);
这很好:
printf("char = %c", i);
%c
格式化程序首先需要int
arg,因为无论如何都无法将char
传递给printf()
(它始终会转换为{{ 1}},或者在极不可能的情况下,int
。)
答案 1 :(得分:3)
在没有必要的情况下,您似乎非常担心类型安全问题。由于这是C而不是C ++,因此没有强大的打字系统。只要未设置“符号位”,从unsigned char
到char
的转换通常无害。避免问题的关键是真正理解它们。 C:
char
类型具有实现定义的签名。一个人不应该对其签名做任何假设,也不应该在任何类型的算术中使用它,特别是不要按比特操作。 char
仅应用于存储/打印ASCII字母。它永远不应该与十六进制文字混合,否则可能存在微妙的错误。char
和unsigned char
)提升为可以保存其结果的整数类型。实际上,这将始终为int
。int
。你也在使用malloc的void *结果,这在C语言中是完全没有意义的,并且在旧版本的C标准中可能有害,如果没有可见的函数原型,则将函数转换为“default int”。
然后你有各种奇怪的逻辑相关的错误和不良做法,我已经修复但不会详细评论。使用此修改后的代码:
#include <stdio.h>
#include <stdlib.h>
void display(const char *buff, int len) {
for(int i = 0; i < len; i++) {
printf("buff[%d] = %c\n", i, buff[i]);
}
}
int main() {
int len = 10;
unsigned char* buff = malloc(len * sizeof(unsigned char));
if(buff == NULL)
{
// error handling
}
char ch = 'A';
for(int i=0; i<len; i++)
{
buff[i] = (unsigned char)ch + i;
printf("char = %c\n", buff[i]);
}
printf("\nDisplaying array in main.\n");
for(int i = 0; i < len; i++) {
printf("buff[%d] = %u\n", i, buff[i]);
}
printf("\nDisplaying array in func.\n");
display((char*)buff, len);
free(buff);
return 0;
}
答案 2 :(得分:1)
C / C ++从任何整数类型转换为任何其他相同或更大的整数类型,保证不会产生数据丢失。有符号和无符号字段之间的转换通常会产生溢出和下溢的危险,但是您转换的缓冲区实际上指向的类型实际上是无效的原始数据*。