【问题标题】:Is it possible to store a signed integer in an integer pointer (int *)?是否可以将有符号整数存储在整数指针(int *)中?
【发布时间】:2018-07-29 13:28:36
【问题描述】:

整数指针(但实际上是任何指针类型)的特别之处在于您可以为它们分配NULL 一个非整数类型的值;而一个整数无论如何都必须存储一个整数,无论​​是正数还是负数(如果我错了,请纠正我),并且没有非整数值。

然后你能不能利用指针的这个“特殊”特性(作为一个可以存储整数和非整数值的变量:NULL)来同时存储整数值(通过它们的字面量实际值,而不是地址,它将存储有符号/无符号整数)并且是一种boolean - 其中NULL pointer 将表示falsevalid pointer(即持有整数的人)(但不是真正有效的 ofc,只是不是NULL)将表示true

注意:指针绝对不会用于访问内存位置,只是为了存储一个 int。

(Ofc 这只是针对特定用例,而不是您会在常规代码中执行此操作)


(如果你真的想知道) 我正在尝试做一个递归函数,并希望函数的返回值返回一个整数,但也想跟踪一个条件,所以我也希望它返回一个布尔值,但你显然只能返回一个参数......所以可以传递一个整数指针,一个可以同时执行两者的变量,是解决方案吗?

我想到了其他方法(结构、数组..),但很好奇使用整数指针是否可行。

【问题讨论】:

  • 什么?您不能将 integer 存储到 pointer 中。您可以使用显式强制转换和实现定义的行为将整数转换为指针。您的设计只有个缺点。你需要重新考虑你的方法。
  • @Antti Haapala 嗯,你可能是对的.. 但你不能这样做:int *ptr = 5; --- 而不是 --- int *ptr = &var; ?
  • 什么是整数指针?你的意思是int *intptr_t 还是什么?
  • 是的,我的意思是int *,那你怎么称呼它(int *)?
  • 问题是为了什么?将它存储在同一类型的对象中不是更容易吗?这是创建 MISRA 的原因之一。不允许这种导致 UB 和极难发现错误的荒谬想法。

标签: c pointers integer boolean


【解决方案1】:

关于 NULL 的指针没有什么特别之处。在不以 8086 实模式运行的基于 Intel 的现代实现中,指针只是一个无符号整数,NULL 为 0。您不能以这种方式存储“额外”的东西。

如果您需要从函数中返回两个值,请创建一个包含 intbool 的结构并让您的函数返回。

【讨论】:

  • 好的,@dbush 所以你必须做 struct 的事情......但是,这个函数是递归的......所以如果你 malloc 函数中的 struct 内存会发生什么?它是否不断分配越来越多的内存?还是你只需要在函数之外分配内存?
  • 您实际上可以按值返回结构。结构会很小,因此开销很小(如果有的话)。
  • 您关于英特尔的陈述是否会概括为“指针为整数大小的架构”?
  • @PaulOgilvie 不确定。在实模式的情况下,一个指针由一个段和一个偏移量组成,所以它实际上由两个 16 位的值组成。
  • @PaulOgilvie 不。在某些情况下,指针的行为类似于有符号整数,在另一些情况下则类似于无符号整数,NULL 通常但并不总是对应于零值。还有其他的架构,你有更复杂的指针,强制指针安全(特别是如果你使用 GC 或有不同表示的指针)或其他有趣的东西。
【解决方案2】:

是否可以将有符号整数存储在整数指针(int *)中?

也许吧。它可能会“工作”。即使没有取消引用指针的赋值,也可能导致程序停止。即使转换成功,信息也可能丢失。

整数可以转换为任何指针类型。除先前规定外, 结果是实现定义的,可能没有正确对齐,可能不指向 引用类型的实体,可能是陷阱表示 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);

整数指针有什么特别之处(?)

它们被正确地赋值为在取消引用时对齐以指向特定的整数类型。它们可能存在于不适合某些其他类型的地址空间中。 C 甚至允许int *void * 窄。 (虽然已经有一段时间没有看到机器利用这一点了。)


.. 无论如何,一个整数必须存储一个整数...

反例:代码可以将_Bool 存储在一个整数中,并且可以原封不动地恢复。 void * 可以保存为 (u)intptr_t 类型的整数,并使用 equivalent 值恢复。


可选类型(u)intptr_t 的整数可以转换为void* 并保持指针等价。对于其他非字符指针或函数指针的直接转换,这不一定是正确的。其他整数类型不一定如此。

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);

你能不能利用指针的这个“特殊”功能

不一定。 OP 的实现可能在选择性平台上工作,但它缺乏指定的行为和可移植性。

【讨论】:

    【解决方案3】:

    也许我弄错了,但为什么不直接使用 bool *stdbool.h

    使用NULLsomething else 的唯一好处是,你没有 对bool *进行malloc/free,但代价是语义不佳和滥用风险。

    这是一个例子,我是如何理解你的提议的:

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

    _dontuse 只在内部使用,你永远不会 malloc/free 它,而是让它指向任意内存位置。所以有潜在的风险。

    更好的主意:

    #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 */
    }
    

    或者尝试使用dynamic programming 来实现。

    【讨论】:

    • 是的@Inrin你的权利,这就是为什么我不想使用其他任何东西,因为我必须为它分配内存,老实说,如果在递归函数中这样做是一个好的事情,可能不是,我不想声明一个全局变量...... bla bla .. ---- 但是,int 不是常量,它既不是 NULL 也不是 int;是的,这就是它的布尔值......但是 int 也会改变,我每次都需要不同的值,因为我使用它们。
    • 我的想法是,你包装主要的公共电话并在内部使用_dontuse。所以你会 malloc/&mainvar 在调用 foofree/ 在递归函数结束后什么都不做。如果您对 true/false 感兴趣,请使用 int *int ** 获取单个/多个值。同样在您的问题中,我想动态编程会解决很多问题。
    • 只是想补充一点:你不必使用bool,你只需要一个终止点。
    【解决方案4】:

    是的,您可以 [如果您在 32 位或 64 位系统上工作]。在这些情况下,int 的大小小于或等于int* 的大小,所以这样做没有任何问题。

    NULL 只是指向您无法访问的 RAM 段的指针(该段从地址 0 开始并持续到一定大小)。就是这样,它只是内存段的一个数值。

    【讨论】:

    • 是的,你可以。一般来说,不,你不能。 整数大小小于或等于int* 大小 不能保证in the C standardint 值可以适合int * 值。
    • @AndrewHenle 谢谢,已编辑。在 32/64 位系统上,int 是否有可能更大,谢谢int*?我不记得有任何例子:X
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-09
    • 2021-11-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多