在malloc中输入类型

这个问题在这里已经有了答案:

  • 我输入malloc的结果吗? 27个答案

  • 如果您没有#include d stdlib.hmalloc的返回值在返回到调用代码之前很可能被截断。 从理论上讲,这是未定义的行为。 如果malloc的返回值被截断,则类似于使用:

    int a = 10;
    int* ap = &a;
    int temp = (int)ap;    // This is where you lose the pointer value due to truncation.
    int* bp = (int*)temp;
    

    你的房子宽50英尺。 你的家庭地址是'40,Church st,Newtown'。 说你家旁边有沃尔玛或学校等大型商店。 这是450英尺宽。 但地址是'50,Church St,Newtown'。

    您是否需要使用不同尺寸的纸张来书写这些地址,因为一个纸张比其他纸张大? 当然不是。 指针与地址同义。 它是位置。 那里存储的(在你的情况int 4字节)不会改变地址长度。

    所以最后,x的大小为8,并且将指向4字节的大小。


    让我们看看会发生什么。 假设这个代码:

    #include <stdio.h>
    int main(int argc, char ** argv) {
      printf("sizeof(int) = %zunsizeof(int *) = %zun",
        sizeof(int), sizeof(int *));
      // output:
      // sizeof(int) = 4
      // sizeof(int *) = 8
      int * foo = (int *) malloc(sizeof(int));
      return 0;
    }
    

    在我的系统上用clang ouch.c编译这个结果给出:

    ouch.c:5:23: warning: implicitly declaring library function 'malloc' with type 'void *(unsigned long)'
      int * foo = (int *) malloc(sizeof(int));
                          ^
    ouch.c:5:23: note: include the header <stdlib.h> or explicitly provide a declaration for 'malloc'
    

    在这里,clang足够聪明,能够注意到我调用了malloc ,它是一个已知的库函数,并假定(正确)函数签名为void *(unsigned long) 。 所以一切都很好。 但不是每个编译器都很聪明,我也可以欺骗铛:

    #include <stdio.h>
    int main(int argc, char ** argv) {
      printf("sizeof(int) = %zunsizeof(int *) = %zun",
        sizeof(int), sizeof(int *));
      int * foo = (int *) wrapper();
      return 0;
    }
    

    在一个单独的文件中,我将链接到上面的主文件:

    #include <stdlib.h>
    void * wrapper(void) {
      return malloc(sizeof(int));
    }
    

    运行clang wrapper.c ouch2.c给我:

    ouch2.c:5:23: warning: implicit declaration of function 'wrapper' is invalid in C99 [-Wimplicit-function-declaration]
      int * foo = (int *) wrapper();
                          ^
    ouch2.c:5:15: warning: cast to 'int *' from smaller integer type 'int' [-Wint-to-pointer-cast]
      int * foo = (int *) wrapper();
                  ^
    2 warnings generated.
    

    这很不错,因为如果读取这些警告,那么很容易理解问题的根源并解决它们。 但如果我忽略它们并保持代码的状态,会发生以下情况:

    编译ouch2.c ,clang没有看到任何wrapper声明。 由于我从循环中删除了它的智能库函数检测,因此它别无选择,只能假设这被声明为某处

    int wrapper();
    

    这是一个函数,返回一个int并获取任意数量的参数。 我们看到这样的证据,因为clang(作为一个智能编译器)警告我关于从(返回的) intint *的第二个警告。

    int转换为int *并不是什么坏事。 什么坏的假设,我们得到一个int摆在首位。 假定在wrapper函数中调用malloc返回了这个值:

    0xAABBCCDD11223344
    

    然后会发生什么取决于调用约定。 让我们假设它将这个值作为返回值放入64位寄存器中。

    main调用代码需要一个int ,所以它只能从寄存器中读取32位(可能是下半部分)并使用它。 所以main ,我从wrapper得到这个:

    0x11223344
    

    然后将其转换为(64位) int * ,可能导致:

    0x0000000011223344
    

    然后将其用作内存地址。 访问这个地址可能会(如果你幸运的话)导致分段错误或者(如果你不那么幸运)改变一些随机数据(如果发生在堆栈上,这会变得特别有趣,例如改变返回地址) 。

    所以,最后但并非最不重要的是,如果我离开演员阵容:

    #include <stdio.h>
    int main(int argc, char ** argv) {
      printf("sizeof(int) = %zunsizeof(int *) = %zun",
        sizeof(int), sizeof(int *));
      int * foo = wrapper();
      return 0;
    }
    

    并用clang wrapper.c ouch3.c编译clang wrapper.c ouch3.c我得到:

    ouch3.c:5:15: warning: implicit declaration of function 'wrapper' is invalid in C99 [-Wimplicit-function-declaration]
      int * foo = wrapper();
                  ^
    ouch3.c:5:9: warning: incompatible integer to pointer conversion initializing 'int *' with an expression of type 'int' [-Wint-conversion]
      int * foo = wrapper();
            ^     ~~~~~~~~~
    2 warnings generated.
    

    也是一个警告,但一个不同的警告。 这种(某种)警告更可能由您的编译器生成。

    长话短说:clang能够很好地警告潜在的错误,并且不会抛出返回值,因为如果忘记包含stdlib.h,即使没有用clang编译,你也可以肯定会得到警告:)

    链接地址: http://www.djcxy.com/p/28367.html

    上一篇: Type casting in malloc

    下一篇: Casting errors in malloc for "char" array in C language