1

What's special about integer pointers (but any pointer type really) is that you can assign to them NULL a non-integer sort of value; whereas an integer has to, no matter what, store an integer, be it a positive or negative one (correct me if I'm wrong), and no NON-integer values.

Could you then make use of this 'special' feature of pointers (that of being a variable that can store integers and a NON-integer value: NULL) to at the same time store integer values (via their literal actual value, like instead of an address, it would store a signed/unsigned integer) and be a sort of boolean -- where a NULL pointer would signify false & a valid pointer (i.e one that is holding an integer) (but not really valid ofc, just one that isn't NULL) would signify true.

Note: The pointer is absolutely never used to access a memory location, just to store an int.

(Ofc this is just for a particular use case, not that you would do this in regular code)


(If you really want to know) I'm trying to make a recursive function, and want the return value of the function to return an integer but also want to keep track of a condition, so I also want it to return a boolean, but you obviously can only return a single argument... so could passing an integer pointer, a variable that can do both at once, be the solution ?

I thought of other ways (stucts, arrays.. ), but curious if doing it w/ an integer pointer could be a plausible way.

AymenTM
  • 529
  • 2
  • 5
  • 17
  • 3
    Wat? You cannot store an *integer* into a *pointer*. You can convert an integer to a pointer, with an explicit cast, and with implementation-defined behaviour. There are **only** drawbacks in your design. You need to rethink your approach. – Antti Haapala -- Слава Україні Jul 29 '18 at 13:40
  • @Antti Haapala Hmm idk man your probably right.. but can't you do this : int *ptr = 5; --- instead of --- int *ptr = &var; ? – AymenTM Jul 29 '18 at 13:43
  • What is an integer pointer? Do you mean `int *` or `intptr_t` or what? – John Kugelman Jul 29 '18 at 13:45
  • Yes, i mean int *, how do u call that (int *) then ? – AymenTM Jul 29 '18 at 13:49
  • it's possible to store integer values in pointers. In fact it's commonly used [to pass a single parameter to threads](https://stackoverflow.com/q/10871427/995714). However I don't get what you want. Why should it be a pointer to store both an integer and boolean? If the returned range of the integer is small you can reserve special values for the bool, otherwise just return a struct or a longer int – phuclv Jul 29 '18 at 13:51
  • Your right @phuclv, but wouldn't you have to allocate memory for the struct either beforehand or in the function ? That's kinda what i want to avoid. – AymenTM Jul 29 '18 at 13:54
  • @notAymen no, small structs are returned in registers (up to [2 registers in x86](https://stackoverflow.com/q/6731140/995714), [more on other architectures](https://stackoverflow.com/q/22957175/995714)). Bigger ones are allocated on stack at the function entry so no need to worry about that. Alternatively return the value from the function and the secondary value via an output pointer parameter (or reference in C++) – phuclv Jul 29 '18 at 14:05
  • 1
    The question is what for? Isn't it easier to store it in the same type object? This is one of the reasons why MISRA was created. To disallow such a ridiculous ideas leading to UBs and extremely hard to find errors. – 0___________ Jul 29 '18 at 14:09
  • @P__J__ ... isn't stackoverflow for this ? To help each other understand our mistakes ? To help each other learn ? To correct each other ? Just write an answer explaining why you wouldn't do this and why it's dangerous.. the community, me included would gladly accept it. I don't know any better that's why I'm asking, i don't have an expert C programmer by my side telling me what to do and what not to do... and note i don't have much experience, as a programmer, so yeah man no hard feelings but please. Like, I didn't even know about MISRA.. and now thanks to your comment I & perhaps others do – AymenTM Jul 29 '18 at 14:22
  • @phuclv *it's possible to store integer values in pointers.* Not in general, even if it works on most platforms. *In fact it's commonly used to pass a single parameter to threads.* That's an implementation-dependent hack. Yes, it's really common, but it's still a hack. – Andrew Henle Jul 29 '18 at 14:27
  • @AndrewHenle of course the int type can't be wider than the pointer type in order to be stored in it. Better use `intptr_t` since it's required to be convertible to void* – phuclv Jul 29 '18 at 14:30
  • @phuclv If available. `intptr_t` is an optional type., – Andrew Henle Jul 29 '18 at 14:43
  • Your design won't work, because `NULL` when cast to an integer is guaranteed to store `0`. So you won't be able to return `0` with `true`. If you don't need to return `0` in your logic, just use plain old `int` and reserve `0` for false. If you do want to return `0`, just reserve a sentinel value for false, like say `INT_MAX`. What value you choose for the sentinel (for the false case) depends on what range of values can be returned for the `true` case. – Ajay Brahmakshatriya Jul 29 '18 at 15:34
  • @Ajay Brahmakshatriya, the `int` takes any value from positive to negative, 0 included, soo... yea; but otherwise, if 0, negatives, or other values weren't part of the range.. yeah it would definitely be the right way to go. – AymenTM Jul 29 '18 at 15:52

4 Answers4

3

There’s nothing special about a pointer with regard to NULL. On modern Intel based implementations not running in 8086 real mode, a pointer is just an unsigned integer, and NULL is 0. You can’t store something “extra” in that way.

If you need to return two values from your function, create a struct containing an int and a bool and have your function return that.

dbush
  • 205,898
  • 23
  • 218
  • 273
  • Ok, @dbush so you'd have to do the struct thing... But, the function is recursive.. so what happens if you malloc the memory for the struct in the function ? Does it keep allocating more and more memory ? or instead would you just have to malloc memory outside the function ? – AymenTM Jul 29 '18 at 13:58
  • 1
    You can actually return the struct by value. The struct will be small, so the overhead is minimal, if any at all. – dbush Jul 29 '18 at 14:00
  • Would your statement about Intel generalize to "architectures where pointers are the size of integers"? – Paul Ogilvie Jul 29 '18 at 14:34
  • 1
    @PaulOgilvie not sure. In the case of real mode, a pointer consist of a segment and an offset, so it actually consists of two 16 bit values. – dbush Jul 29 '18 at 14:37
  • 3
    @PaulOgilvie No. On some, pointers behave like signed integers, on others like unsigned integers, with `NULL` often but not always corresponding to the zero value. There are still other architectures out there, and where you have more complex pointers, enforced pointer-safety (especially if you use a GC or have pointers with different representations) or other interesting things. – Deduplicator Jul 29 '18 at 14:40
3

Is it possible to store a signed integer in an integer pointer (int *)?

Maybe. It might "work". Even the assignment, without de-referencing the pointer, may cause the program to stop. Even with a successful conversion, information may be lost.

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation C11dr §6.3.2.3 5

// Sample implementation
int i = -rand();
printf("i: %d\n", i);
int *iptr = (int *) i;   // implementation-defined
printf("iptr: %p\n", (void*) iptr);

What's special about integer pointers (?)

They are correctly valued to aligned on de-referencing to point to the specific integer type. They may exist in an address space that is not suitable for some other types. C even allows for a int * to be narrower than a void *. (Have not seen a machine take advantage of that in some time though.)


.. an integer has to, no matter what, store an integer ...

Counter examples: Code can store a _Bool in a integer and be recovered unchanged. void * can be save in a integer of type (u)intptr_t and be recovered with an equivalent value.


A integer of the optional type (u)intptr_t can convert to a void* and maintain pointer equivalence. This is not necessarily true with direct casting of other non-character pointers or of function pointers. This is not not necessarily true with other integer types.

some_type_t *some_valid_object_pointer = ...;
intptr_t i = (intptr_t)(void*) some_valid_object_pointer;
some_type_t *some_valid_object_pointer2 = (some_type_t*)(void*)i;
assert(some_valid_object_pointer == some_valid_object_pointer2);

Could you then make use of this 'special' feature of pointers

Not certainly. OP's implementation may work on selective platform, but is it lacks specified behavior and portability.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
0

Maybe I'm mistaken, but why not just use a bool * with stdbool.h?

The only benefit of using NULL and something else would be, that you don't have to malloc/free the bool * but for the cost of bad semantics and the risk of misuse.

Here is an example, how I understand your proposal:

static void foo(int *_dontuse) {
    if (_dontuse != NULL) {
        /* do stuff */
    } else {
        /* do stuff */
    }
}

And _dontuse is only used internally and you never malloc/free it, but let it point to arbitrary memory locations. So potentially risky.

Better idea:

#include stdbool.h

struct Sometype {
    bool done;
    /* other members */
};

static void internalfoo(struct Sometype *data) {
    /* use data, maybe store bool inside struct for ifs */
    if (data->done) return;
    /* do something */
    data->done = true; /* need to set it to true, to terminate */
    internalfoo(data);

}

void foo() {
    struct Sometype data;
    data.done = false;
    internalfoo(&data);
    /* do something with result */
}

Or try to implement this with dynamic programming.

Inrin
  • 322
  • 2
  • 10
  • Yes @Inrin your right that is why I don't want to use anything else, because I'd have to malloc memory for it, and honestly idk if doing that in a recursive function is a good thing, probably not and i don't want to declare a global variable... bla bla.. ---- but, the int is not a constant, and it is not either a NULL or an int; it is, thats the boolean side of it... but the int also changes and i need the different values everytime, cuz i use them. – AymenTM Jul 29 '18 at 13:48
  • My idea was, you wrap the main public call and use internally the `_dontuse`. So you would malloc/`&mainvar` before calling `foo` and `free`/do nothing after your recursive function is over. If your interested in more than true/false use an `int *` or `int **` for single/multiple values. Also in your problem I guess dynamic programming would solve a lot. – Inrin Jul 29 '18 at 13:53
  • Just wanted to add: You don't have to use a `bool`, you just need an termination point. – Inrin Jul 29 '18 at 14:10
0

Yes, you can [if you are working on 32-bit or 64-bit system]. In those cases int size is less or equal to int* size, so there is no any problem of doing that.

NULL is just pointer to RAM segment that you are not able to access (this segment begins with address 0 and continues to some size). That's it, it's just a numerical value of memory segment.

  • 1
    *Yes, you can.* In general, no you can't. *Integer size is less or equal to `int*` size* There's no guarantee [in the C standard](http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) that an `int` value can fit into an `int *` value. – Andrew Henle Jul 29 '18 at 14:24
  • @AndrewHenle Thanks, edited. On 32/64 bit systems is there any probability for `int` to be larger thank `int*`? I can't remember any examples of that :X – Data Chanturia Jul 29 '18 at 14:33