I am converting an input raw pcm
stream into mp3
using lame
. The encoding function within that library returns mp3
encoded samples in an array of type unsigned char
. This mp3-encoded stream now needs to be placed within an flv
container which uses a function that writes encoded samples in char
array. My problem is that I am passing the array from lame
(of type unsigned char
) into the flv
library. The following piece of code (only symbolic) illustrates my problem:
/* 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;
}
My question(s):
1. Is the implicit type conversion in the code below (as demonstrated by passing of buff
into function display
safe? Is some weird behaviour likely to occur?
2. Given that I have little option but to stick to the functions as they are present, is there a "safe" way of converting an array of unsigned char
s into char
s?
The only problem with converting unsigned char *
into char *
(or vice versa) is that it's supposed to be an error. Fix it with a cast.
display((char *) buff, len);
Note: This cast is unnecessary:
printf("char = %c", (char) i);
This is fine:
printf("char = %c", i);
The %c
formatter takes an int
arg to begin with, since it is impossible to pass a char
to printf()
anyway (it will always get converted to int
, or in an extremely unlikely case, unsigned int
.)
You seem to worry a lot about type safety where there is no need for it. Since this is C and not C++, there is no strong typing system in place. Conversions from unsigned char
to char
are usually harmless, as long as the "sign bit" is never set. The key to avoiding problems is to actually understand them. The following problems/features exist in C:
char
type has implementation-defined signedness. One should never make any assumptions of its signedness, nor use it in arithmetic of any kind, particularly not bit-wise operations. char
should only be used for storing/printing ASCII letters. It should never be mixed with hex literals or there is a potential for subtle bugs.char
and unsigned char
, to an integer type that can hold their result. This will in practice always be int
.int
in C.You are also casting the void* result of malloc, which is completely pointless in C, and potentially harmful in older versions of the C standard that translated functions to "default int" if no function prototype was visible.
And then you have various weird logic-related bugs and bad practice, which I have fixed but won't comment in detail. Use this modified code:
#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;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With