繁体   English   中英

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

[英]Casting from unsigned into signed char in C

我正在使用lame将输入raw pcm流转换为mp3 该库中的编码函数返回类型为unsigned char的数组中的mp3编码样本。 这个mp3编码的流现在需要放在一个flv容器中,该容器使用一个在char数组中写入编码样本的函数。 我的问题是我将数组从lameunsigned 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数组转换为char

unsigned char *转换为char * (反之亦然)的唯一问题是它应该是一个错误。 用演员表修复它。

display((char *) buff, len);

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

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

这可以:

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

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

你似乎很担心没有必要的类型安全。 由于这是C而不是C ++,因此没有强大的打字系统。 unsigned charchar转换通常是无害的,只要从未设置“符号位”即可。 避免问题的关键是真正理解它们。 C中存在以下问题/特征:

  • 默认的char类型具有实现定义的signedness。 一个人不应该对其签名做任何假设,也不应该在任何类型的算术中使用它,特别是不要按比特操作。 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;
}

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM