简体   繁体   中英

Will casting a char/unsigned char be safe?

Will it be safe to fix the warning below with casting, or could I simple change the prototype to return a u_char instead?

warning: returning 'u_char [256]' from a function with result type 'char *' converts between pointers to integer types with different sign [-Wpointer-sign]

char   * whatever(unsigned char *text)
{
        static u_char retval[256];
        int pos = 0;

        *retval = 0;
        if (!text)
                return retval;

        for (; *text && (pos < 254); text++, pos++) {
                if (*text < 32) {
                        retval[pos++] = '^';
                        retval[pos] = *text + 64;
                } else if (*text == 127) {
                        retval[pos++] = '^';
                        retval[pos] = '?';
                } else
                        retval[pos] = *text;
        }

        retval[pos] = 0;
        return retval;
}

I'm open to other possibilities as well.

Of course you should change the return type, if you consider the data to be unsigned.

Your code, in general, is a bit scary-looking since it seems to hardcode assumptions about characters based on ASCII values. This is not something I'd recommend doing, look at the isprint() function and friends for portable ways of inspecting characters. And text is typically assumed to be const char * , not const unsigned char * .

Lastly, of course it can be slightly dangerous to return a pointer to a static buffer too, the code is not thread-safe and if multiple calls are done it's hard to keep track externally of the return value and realize when it becomes overwritten by subsequent calls.

Since your function takes an unsigned char* for the input, it would seem reasonable for it to return unsigned char* for the output, unless part of the intended purpose of the function is to convert from unsigned char to char . If that's part of the purpose, then retval should be an array of char , not an array of u_char .

Converting from unsigned char to char is likely to be a no-op on 2's complement implementations (approximately all of them). But it's not actually guaranteed to be, even on 2's complement. For values greater than CHAR_MAX (usually 127), the conversion is permitted to change the bit pattern or even raise a signal. On implementations where converting from unsigned char to char isn't a no-op (approximately none of them), casting from unsigned char* to char* isn't safe, hence the warning.

So in effect, the warning tells you that you need to decide (and document) what kind of characters your function is dealing in. Don't avoid that decision with a cast.

There are millions of lines of code that treat char* and unsigned char* as interchangeable, while the C standard doesn't mandate that they are interchangeable. Whether that is "safe" depends on what you mean by the word ... it's not "safe" if you think you might port your code to one of the currently non-existent conforming implementations where they aren't interchangeable, or if you subscribe to the pedantry that says that anything not conforming to the C standard might wipe out your hard drive.

But it's far better practice to write properly type-safe code, in which case the question doesn't even arise. In other words, don't avoid a cast because it's "unsafe", avoid it because it's bad coding practice. And part of the badness is that any cast can hide a bug ... suppose, for instance, that what you thought was a char* that you're casting to unsigned char* was actually some other type, say an int or an int* ... you have just prevented the compiler from telling you about it. types and type safety are powerful tools for avoiding bugs by catching them early ... at compile time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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