从无符号转换为C中的signed char

时间:2013-02-07 08:41:02

标签: c casting char unsigned-char

我正在使用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?

3 个答案:

答案 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 charchar的转换通常无害。避免问题的关键是真正理解它们。 C:

中存在以下问题/特征
  • 默认char类型具有实现定义的签名。一个人不应该对其签名做任何假设,也不应该在任何类型的算术中使用它,特别是不要按比特操作。 char仅应用于存储/打印ASCII字母。它永远不应该与十六进制文字混合,否则可能存在微妙的错误。
  • C中的整数提升隐式地将所有小整数类型(包括charunsigned char)提升为可以保存其结果的整数类型。实际上,这将始终为int
  • 形式上,不同类型之间的指针转换可能是未定义的行为。但是unsigned char和char之间的指针转换实际上是安全的。
  • 字符文字'\ 0'等在C中的类型为int
  • printf和类似函数默认将所有字符参数提升为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 ++从任何整数类型转换为任何其他相同或更大的整数类型,保证不会产生数据丢失。有符号和无符号字段之间的转换通常会产生溢出和下溢的危险,但是您转换的缓冲区实际上指向的类型实际上是无效的原始数据*。