4

我正在将输入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. 鉴于我别无选择,只能坚持使用函数它们存在,是否有将 s 数组转换为unsigned chars的“安全”方法char

4

3 回答 3

6

unsigned char *转换为char *(反之亦然)的唯一问题是它应该是一个错误。用石膏固定它。

display((char *) buff, len);

注意:此演员表是不必要的:

printf("char = %c", (char) i);

这可以:

printf("char = %c", i);

%c格式化程序以argint开头,因为无论如何都不可能将 a 传递charprintf()(它总是会转换为int,或者在极不可能的情况下,unsigned int.)

于 2013-02-07T08:46:53.830 回答
3

您似乎非常担心不需要的类型安全。由于这是 C 而不是 C++,因此没有强类型系统。只要从未设置“符号位”,从unsigned chartochar的转换通常是无害的。避免问题的关键是真正理解它们。C中存在以下问题/功能:

  • 默认char类型具有实现定义的签名。永远不应该对它的符号性做出任何假设,也不应该在任何类型的算术中使用它,尤其是按位运算。char应该只用于存储/打印 ASCII 字母。它不应该与十六进制文字混合,否则可能会出现细微的错误。
  • C 中的整数提升隐式地将所有小整数类型(其中charunsigned char)提升为可以保存其结果的整数类型。这在实践中总是如此int
  • 形式上,不同类型之间的指针转换可能是未定义的行为。但是 unsigned char 和 char 之间的指针转换实际上是安全的。
  • 字符文字 '\0' 等是intC中的类型。
  • printf 和类似函数默认将所有字符参数提升为 int。

您还在转换 malloc 的 void* 结果,这在 C 中完全没有意义,并且在 C 标准的旧版本中可能有害,如果没有可见的函数原型,则将函数转换为“默认 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;
}
于 2013-02-07T09:46:37.723 回答
1

保证从任何整数类型到任何其他相同或更大的整数类型的 C/C++ 强制转换不会产生数据丢失。有符号和无符号字段之间的强制转换通常会产生上溢和下溢的危险,但您要转换的缓冲区实际上指向的原始数据的类型实际上是 void*。

于 2013-02-07T08:44:38.120 回答