4

I have an array of strings like such

char *T[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};

When I do it like this, however, where each string is an array of unsigned chars

unsigned char *T[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};

I get the error "Initializing 'unsigned char *' with an expression of type 'char[5]' converts between pointers to integer types with different sign." I'm guessing that means that some of the representations of "0" and "1" that are getting used are signed, but I'm not sure why/how to deal with that. I'd like to have an array of strings where each string is an array of unsigned chars rather than signed chars. Can someone help with that?

Note: this is for a HW problem, but is not the actual problem, and is just a minor step in one of many possible solutions. However, it would be good if you could help me understand it without giving me an explicit answer. Thanks.

7
  • 5
    To simply put it, string literals are of type char* not unsigned char*. Commented Sep 15, 2012 at 12:13
  • 3
    @tuğrulbüyükışık I strongly recommend against casting to break type-safety. Commented Sep 15, 2012 at 12:15
  • then an array of unions of char + unsigned char works well because each will be 1-byte so endianness will not be a problem. Aliasing? Commented Sep 15, 2012 at 12:17
  • Is there a need to make the characters unsigned? What sort of comparisons would you perform with them? Commented Sep 15, 2012 at 12:17
  • 1
    Mysticial is correct on string literals being const char*. I think you are trying to do the conversion for a wrong reason; could you describe the broader problem that you are solving? Commented Sep 15, 2012 at 12:18

1 Answer 1

4

C strings, one of many ways one could represent a string, consist of arrays of char terminated by a trailing char which has the null value. That's what you get type-wise when you have "0000" in your code.

What you want is to assign "0000" to be an array of unsigned char terminated by a trailing unsigned char which has the null value. Considering what you are starting with, you will have to cast, or perhaps represent your initial data in a manner that doesn't require casting.

unsigned char T[][] = { { 0x30, 0x30, 0x30, 0x30, 0x00 }, 
               { 0x30, 0x30, 0x30, 0x31, 0x00 }, 
               { 0x30, 0x30, 0x31, 0x30, 0x00 }, 
               { 0x30, 0x30, 0x31, 0x31, 0x00 }, 
               { 0x30, 0x31, 0x30, 0x30, 0x00 }, 
               { 0x30, 0x31, 0x30, 0x31, 0x00 }, 
               { 0x30, 0x31, 0x31, 0x30, 0x00 }, 
               { 0x30, 0x31, 0x31, 0x31, 0x00 }, 
               { 0x31, 0x30, 0x30, 0x30, 0x00 }, 
               { 0x31, 0x30, 0x30, 0x31, 0x00 }, 
               { 0x31, 0x30, 0x31, 0x30, 0x00 }, 
               { 0x31, 0x30, 0x31, 0x31, 0x00 }, 
               { 0x31, 0x31, 0x30, 0x30, 0x00 }, 
               { 0x31, 0x31, 0x30, 0x31, 0x00 }, 
               { 0x31, 0x31, 0x31, 0x30, 0x00 }, 
               { 0x31, 0x31, 0x31, 0x31, 0x00 }
              };

The main problem I see with this approach is that it removes most of the advantage of having a C style string in the first place. With an unsigned char "string", you have none of the standard string libraries at your disposal, so you will have to cast back to signed char string types if you want to use printf, or any other string oriented function.

Really, you are only using two values for each possible character position "0" and "1". Unless there is a compelling reason to do it in a string, consider an array of boolean values to reduce the chance of a string like "0hello" working it's way into the code, or better yet if you have been introduced to bit fields, use the bits within an unsigned char as bit fields (discarding any concept that you're dealing with strings).

The advantages to the last technique include using less memory and the inability for the value to be other than 0 or 1; however, you will have to write a small collection of routines to translate the packed bits into something human readable.

unsigned char[] = { 0x00, 0x01, 0x02, 0x03, 0x04,
                    0x05, 0x06, 0x07, 0x08, 0x09,
                    0x0A, 0x0B, 0x0C, 0x0D, 0x0E,
                    0x0F };

void displayChar(unsigned char value) {
  switch (value) {
    case 0x00: printf("0000"); break;
    case 0x01: printf("0001"); break;
    case 0x02: printf("0010"); break;
    case 0x03: printf("0011"); break;
... and so on ...
Sign up to request clarification or add additional context in comments.

4 Comments

What would that solution using bit-fields look like? How do you use the bits within an unsigned char as bit fields?
@Willwsharp bit fields are just numbers treated like bits. To type a bit literal constant, one would use (warning, standard dependent / compiler dependent) 0b00100101 It won't make the "type" a bit field, that will still be an unsigned char (because C doesn't have "bit field" types. It would only be useful if the bit positions were significant, and the code formatting was such that it highlighted item. That's why so many people use constants in C to specify flags 8 == 0b1000 == CAN_READ and now (flags & CAN_READ) can be compared to zero (to determine if the CAN READ flag was set)
Hmm all that makes sense; I think I'm just missing how that would be used in the above example
@Willwsharp replace the char[] above with unsigned char[] = { 0b00000000, 0b00000001, 0b00000010, 0b00000011, ... and so on. 0x07 is not a "hexadecimal type" it's a "unsigned char" type, where the bits are specified as hexadecimal numbers. by doing 0b00000111, again it's not a "binary type" it's an "unsigned char" type, where the bits are specified as binary numbers. By doing 'a', again it's not a "char type" it's a an "unsigned char" type, where the bits are specified with as a character. They type is attached to the variable. The initializating data only promotes to a matching type.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.