【问题标题】:Using memory declared for other types使用为其他类型声明的内存
【发布时间】:2013-11-17 15:58:24
【问题描述】:

如果我要为一个 4 字节的变量初始化内存,我能否将两个 2 字节的变量指向为它存储的内存? 我正在尝试进一步了解内存管理和理论。

我正在研究的一个例子:

int main() {
    short* foo = malloc(4*(foo));    // sizeof(*foo)?
    /*in which sizeof will return 2 so I could say
      * malloc(20)
      * so could I say malloc(2*sizeof(long))?
      */
}

或者是在堆上通常声明为彼此相邻的类型,即一个块是为长类型保留的,一个块是为短类型变量保留的?

编辑 我忘了包括一个问题。 如果我要声明两个彼此相邻的 short 类型的变量(一个数组),我可以安全地将 long 指向第一项,并通过位图访问这两个变量吗?显然这主要是针对理论的,因为我觉得问题会有更好、更明显的答案。

【问题讨论】:

  • 内存不知道它所保存的数据的含义。
  • 是的 short *foo = malloc(4* sizeof *foo); 可能是这里。

标签: c memory types malloc


【解决方案1】:

是的。当您分配内存时,C 并不关心类型 - 它只是一块与您请求一样大的内存。它会让你在里面、上面、下面写……直到发生不好的事情!

如果你想要相邻的值,数组是一个不错的方法:

int *myAllocatedArray = (int*)calloc(2, sizeof(int));

myAllocatedArray[0] = 100;
myAllocatedArray[1] = 200;

calloc 会将每个字节初始化为 0。

【讨论】:

  • calloc 会和 malloc 完全一样吗?指针算术可以正常工作吗?
  • @user2958652:是的,callocmalloc 完全相同。不同之处在于它将分配的内存初始化为0。有点像在使用 malloc 声明的内存上调用 memset
  • @user2958652 根据 calloc() 和 malloc() 查看我的回答。
【解决方案2】:

是的,它会起作用,因为 malloc 接受整数参数,例如: malloc(2*4), 4=sizeof(long), 或类似 malloc(20);

【讨论】:

    【解决方案3】:

    当然,您可以随意访问它。 从手册到 calloc() 和 malloc() 的信息很少:

    SYNOPSIS
           #include <stdlib.h>
    
           void *malloc(size_t size);
           void *calloc(size_t nmemb, size_t size);
           ...
    
    DESCRIPTION
           The  malloc() function allocates size bytes and returns a pointer to 
           the allocated memory.  The memory is not initialized.  If size is 0, 
           then malloc() returns either NULL, or a unique pointer value
           that can later be successfully passed to free().
           ...
           The  calloc() function allocates memory for an array of nmemb elements 
           of size bytes each and returns a pointer to the allocated memory.  The 
           memory is set to zero.  If nmemb or size is 0, then calloc() returns 
           either NULL, or a unique pointer value that can later be successfully 
           passed to free().
           ...
    

    【讨论】:

    • Endianess 无关紧要,因为无论如何 0x1234 始终是 0x1234。
    • @Jocke 好的。为什么我们需要 htons() 和 ntohs()?
    • htons()ntohs() 是必需的,以便两台计算机可以轻松地相互通信。它分别代表主机到网络字节序和网络到主机字节序。在本地确实没有效果。除非您从格式指定为特定字节序的文件中读取,否则您不应该关心字节顺序。
    • [mc]alloc() 函数是跨平台的。因此,如果您编写的跨平台程序使用对内存的低级访问,那么您应该关心字节序,因为在不同的系统中 LSB(例如)可能不同。使用 htons() 还是 ntohs()?尝试它们,您会发现即使在本地它们也有效果。还有 0x1234 != htons(0x1234)。
    • Endianess 在这里完全无关紧要。内存永远不会在计算机之外寻址。
    【解决方案4】:

    是的,正如其他人所说,C 是一种弱类型语言。这意味着它几乎没有或没有类型转换的限制。

    例如:

    void *ptr;
    unsigned int *m;
    unsigned int *e;
    double *d;
    
    ptr = malloc(sizeof(double));
    
    d = ptr;
    
    m = ptr;
    e = ptr + 6;
    
    *d = 123.456f;
    
    printf("mantissa: %u\nexponent: %u\ndouble: %f\n", *m, *e, *d);
    
    /* Output:
     * mantissa: 536870912
     * exponent: 16478
     * double: 123.456001
     */
    

    【讨论】:

    • i = 12345 - 这里必须是非引用 (*i = 12345)?
    • 除了d 是一个指针,所以它应该是printf("%f\n", *d); 你的代码不会打印出12345.0
    • 另外printf() 会调用未定义的行为,因为sizeof (*d)8,并且只分配了sizeof int,它(很可能)是4
    • 它仍然不打印 12345.0。因为 12345 (int) 在内存中不等于 12345.0 (double)。
    猜你喜欢
    • 2019-07-01
    • 2023-03-11
    • 2011-03-16
    • 2011-04-16
    • 2021-02-27
    • 2020-08-12
    • 1970-01-01
    • 1970-01-01
    • 2016-07-03
    相关资源
    最近更新 更多