Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pointer comparisons in C. Are they signed or unsigned?

Hi I'm sure this must be a common question but I can't find the answer when I search for it. My question basically concerns two pointers. I want to compare their addresses and determine if one is bigger than the other. I would expect all addresses to be unsigned during comparison. Is this true, and does it vary between C89, C99 and C++? When I compile with gcc the comparison is unsigned.

If I have two pointers that I'm comparing like this:

char *a = (char *) 0x80000000; //-2147483648 or 2147483648 ?  
char *b = (char *) 0x1; 

Then a is greater. Is this guaranteed by a standard?


Edit to update on what I am trying to do. I have a situation where I would like to determine that if there's an arithmetic error it will not cause a pointer to go out of bounds. Right now I have the start address of the array and the end address. And if there's an error and the pointer calculation is wrong, and outside of the valid addresses of memory for the array, I would like to make sure no access violation occurs. I believe I can prevent this by comparing the suspect pointer, which has been returned by another function, and determining if it is within the acceptable range of the array. The question of negative and positive addresses has to do with whether I can make the comparisons, as discussed above in my original question.

I appreciate the answers so far. Based on my edit would you say that what I'm doing is undefined behavior in gcc and msvc? This is a program that will run on Microsoft Windows only.

Here's an over simplified example:

char letters[26];  
char *do_not_read = &letters[26];  
char *suspect = somefunction_i_dont_control(letters,26);  
if( (suspect >= letters) && (suspect < do_not_read) )  
    printf("%c", suspect);  



Another edit, after reading AndreyT's answer it appears to be correct. Therefore I will do something like this:

char letters[26];  
uintptr_t begin = letters;  
uintptr_t toofar = begin + sizeof(letters);  
char *suspect = somefunction_i_dont_control(letters,26);  
if( ((uintptr_t)suspect >= begin) && ((uintptr_t)suspect < toofar ) )
    printf("%c", suspect);  


Thanks everyone!

like image 501
test Avatar asked Jul 15 '11 02:07

test


People also ask

Is pointer arithmetic signed or unsigned in C?

A pointer is neither signed nor unsigned. Pointer arithmetic has its own rules. element[minus1] attempts to access an element that's waaaay off the upper end of the array, so the program has undefined behavior.

What is unsigned pointer in C?

In C, unsigned is also one data type in which is a variable type of int this data type can hold zero and positive numbers. There is also a signed int data type in which it is a variable type of int data type that can hold negative, zero, and positive numbers.

Can we compare two pointers in C?

Master C and Embedded C Programming- Learn as you go We can compare pointers if they are pointing to the same array. Relational pointers can be used to compare two pointers. Pointers can't be multiplied or divided.

Can unsigned int be compare signed int?

while comparing a>b where a is unsigned int type and b is int type, b is type casted to unsigned int so, signed int value -1 is converted into MAX value of unsigned**(range: 0 to (2^32)-1 )** Thus, a>b i.e., (1000>4294967296) becomes false.


2 Answers

Pointer comparisons cannot be signed or unsigned. Pointers are not integers.

C language (as well as C++) defines relative pointer comparisons only for pointers that point into the same aggregate (struct or array). The ordering is natural: the pointer that points to an element with smaller index in an array is smaller. The pointer that points to a struct member declared earlier is smaller. That's it.

You can't legally compare arbitrary pointers in C/C++. The result of such comparison is not defined. If you are interested in comparing the numerical values of the addresses stored in the pointers, it is your responsibility to manually convert the pointers to integer values first. In that case, you will have to decide whether to use a signed or unsigned integer type (intptr_t or uintptr_t). Depending on which type you choose, the comparison will be "signed" or "unsigned".

like image 68
AnT Avatar answered Oct 23 '22 22:10

AnT


The integer-to-pointer conversion is wholly implementation defined, so it depends on the implementation you are using.

That said, you are only allowed to relationally compare pointers that point to parts of the same object (basically, to subobjects of the same struct or elements of the same array). You aren't allowed to compare two pointers to arbitrary, wholly unrelated objects.

like image 20
James McNellis Avatar answered Oct 23 '22 22:10

James McNellis