【问题标题】:Can int store the base address of string in C?int可以在C中存储字符串的基地址吗?
【发布时间】:2014-08-14 20:36:02
【问题描述】:

为什么代码运行没有错误?

#include <stdio.h>
    int main() {
    int i="string"; //the base of string can be stored in a character pointer 
    printf("%s\n",i);
    printf("%d",i);
    return 0;
}

//在ideone.com语言c上编译

输出:

字符串

134513984 //一些垃圾(“字符串”的地址)

请解释c中的指针是否有一些灵活性。我在 c++ 中尝试过,它给出了错误:在初始化中无法将“const char*”转换为“int*”

【问题讨论】:

  • C 是一种宽松的语言,它赋予程序员很大的权力和责任感。如果你想做一些疯狂的事情(像这样),你可以!
  • 您对 C++ 的警告是因为字符串文字在 C++ 中属于 const char [] 类型,但在 C 中属于 char [] 类型(尽管您不得修改它们,即使在 C 中也是如此)。
  • @mafso:不,这不是原因。首先,在 C++ 中,它实际上报告了一个错误,而不是一个警告。其次,虽然您所说的实际类型是正确的,但由于相同的原因,代码在 C 和 C++ 中都被破坏了,const 与它无关。不同语言的诊断消息文本会有所不同,但都必须告知用户问题所在。

标签: c pointers


【解决方案1】:

不,一般情况下您不能假设这一点。部分原因是int 的大小可能与char * 的大小不同(事实上,在许多 64 位编译器上,它的大小不会相同)。

如果要将指针存储为整数,则要使用的适当类型实际上是intptr_t,来自&lt;stdint.h&gt;。这是一个整数,保证能够保存指针的值。

然而,你真正想要这样做的情况很少见,当你这样做时,你还应该包括一个明确的演员:

intptr_t i=(intptr_t)"string"; //the base of string can be stored in a character pointer 

这也使得打印它的值变得复杂,你需要使用一个可移植的宏:

printf("%"PRIiPTR,i);

要打印原始字符串,您还应该强制转换:

printf("%s", (char *)i);

【讨论】:

    【解决方案2】:

    一般来说,不是:C 标准规定从指针到整数的转换是实现定义的。此外,这在 sizeof(char *)sizeof(int) 不同的系统(即 x86-64)上可能会出现问题,原因有两个:

    1. int i = "string"; 可能会丢失信息,例如64 位指针无法容纳 32 位整数。
    2. printf 期望传入一个指针,但得到一个较小的整数。它最终会将一些垃圾读入完整的指针,并可能使您的代码崩溃(或更糟)。

    然而,编译器通常足够“聪明”,可以“修复”printf 的参数。此外,您似乎运行在一个指针和整数 大小相同的平台上,所以你很幸运。

    【讨论】:

      【解决方案3】:

      如果您在编译此程序时出现警告(您应该这样做),您会收到以下投诉:

      main.c:3:9: 警告:指向整数转换的不兼容指针使用“char [7]”类型的表达式初始化“int”[-Wint-conversion] int i="字符串"; //字符串的基数可以存储在字符指针中 ^ ~~~~~~~~ main.c:4:19:警告:格式指定类型“char *”但参数的类型为“int”[-Wformat] printf("%s\n",i); ~~ ^ %d 生成 2 个警告。

      警告通常意味着您正在做的事情可能会导致意外结果。

      【讨论】:

        【解决方案4】:

        大多数 C 编译器都允许您这样做,但这并不是一个好主意。这里,字符数组"string" 的地址存储在i 中。 printf 选项决定如何解释整数(作为地址或整数)。当char*int 的大小不同时(例如,在大多数 64 位机器上),这可能会出现问题。

        C++ 编译器比较挑剔,不会让你编译这样的代码。 C 编译器更愿意,尽管它们通常会生成警告,让程序员知道这是一个坏主意。

        【讨论】:

          【解决方案5】:

          您的代码在 C 和 C++ 中格式错误。这样做是违法的

          int i = "string";
          

          两种语言。在这两种语言中,从指针到整数的转换都需要显式转换。

          你的 C 编译器接受它的唯一原因是它被默认配置为相当松散的错误检查。 (C 编译器的一个相当典型的情况。)收紧你的 C 编译器设置,它应该为上述初始化发出错误。 IE。您可以使用显式转换

          int i = (int) "string";
          

          具有依赖于实现的结果,但您不能合法地隐式执行。

          在任何情况下,您的编译器为上述初始化发出的警告已经足以作为此违规的诊断消息。

          【讨论】:

          • 它在 ideone 和 codeblocks 上运行没有错误,但在 CodeBlocks 中显示警告。
          • @kkr_manit:正如我所说,在默认模式下,此代码通常被 C 编译器接受。但是,在任何情况下都需要诊断消息。如果 ideone 或 codeblocks (GCC) 后面的编译器在没有任何诊断消息的情况下编译它,那么这些编译器就会损坏。 ideone 更有可能故意抑制此类消息,因为默认模式下的 GCC 肯定会警告该问题。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-05-27
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多