确定在C中创建时间后的动态阵列的长度

发布于 2025-02-08 04:12:56 字数 366 浏览 3 评论 0 原文

int *p = malloc(sizeof(int)*10);
size_t val = sizeof(p)/sizeof(int);

printf("this array (p) can content %lu elements \n",val);

大家好,

  1. 我一直在尝试使此程序打印“此数组(P)可以满足10个元素”。但这无效。 (对我而言,val的值被认为是此数组的长度。p除以p的一个元素的总元素的大小)

  2. 的一个元素,当我尝试在malloc之后打印sizeof(p)时,它不是等于4*10(40);

有人可以告诉我出了什么问题吗?

int *p = malloc(sizeof(int)*10);
size_t val = sizeof(p)/sizeof(int);

printf("this array (p) can content %lu elements \n",val);

Hi everyone,

  1. I've been trying to make this program print "this array (P) can content 10 elements". But it doesn't work. ( for me, the value of val is suppose to be the length of this array. size of total elements of p divided by one element of p)

  2. and when i try to print the sizeof(p) after malloc, it's not equal to 4*10 (40);

May someone tell me what's going wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

同尘 2025-02-15 04:12:56

p 是指指针, sizeof(p)不是由 malloc()分配的数组的大小,而是大小指针本身,根据平台的不同(除其他外来的可能性),这可能是4或8。

表达式 sizeof(a)/sizeof(a [0])仅适用于数组,定义为 int a [10]; 或可能在编译时间确定的长度来自Intializer: int a [] = {0,2,4};

没有可移植的方法可以从指针中检索由 malloc()分配的块的大小。您必须单独跟踪大小。

p is a pointer, sizeof(p) is not the size of the array that was allocated by malloc(), it is just the size of the pointer itself, which may be 4 or 8 depending on the platform (among other more exotic possibilities).

The expression sizeof(a) / sizeof(a[0]) only works for arrays, defined as int a[10]; or possibly with a length determined at compile time from the intializer: int a[] = { 0, 2, 4 };.

There is no portable way to retrieve the size of the block allocated by malloc() from the pointer. You must keep track of the size separately.

绮筵 2025-02-15 04:12:56

请参阅其他答案,以及问题下的评论。您必须自己跟踪尺寸。这是一个基本演示:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    const size_t NUM_INTS = 10;
    
    int *p = (int*)malloc(sizeof(int)*NUM_INTS);
    printf("p can hold %zu integers\n", NUM_INTS);

    return 0;
}

输出:

  p可以容纳10个整数
 

如何在C

1中容器化一个动态分配的数组。制作 array_int_t_t int> int s”的数组“容器”

让它更进一步,然后将其作为整数数组将其作为整数。

容器:

/// A container represending a dynamically-allocated array of integers
typedef struct array_int_s
{
    /// Pointer to the first element in a dynamically-allocated array
    /// of ints
    int * start;

    /// Number of elements in the array
    size_t size;
} array_int_t;

用法:

array_int_t array_int;
array_int.start = (int*)malloc(sizeof(int)*NUM_INTS);
array_int.size = NUM_INTS;
    
printf("array_int can hold %zu integers\n", array_int.size);

2。添加 array_int_create()构造函数或“出厂”功能以创建 int s的数组

,然后再进一步:

添加创建功能:

/// Dynamically create and return an array of `num_elements` of type `int`.
array_int_t array_int_create(size_t num_elements)
{
    array_int_t dynamic_array = 
    {
        .start = (int*)malloc(sizeof(int)*num_elements),
        .size = num_elements,
    };
    
    return dynamic_array;
}

并使用它:

array_int_t array_int2 = array_int_create(NUM_INTS);
printf("array_int2 can hold %zu integers\n", array_int2.size);

3。[最佳]更新 array_of_int_create()“ factory”功能以完全动态地分配数组容器加上阵列空间,然后将PTR返回到容器

中这很正确,因为它没有完全动态分配。相反,它需要每个 array_int_t 才能静态分配,然后仅动态地分配数组的内存,而不是容器本身。实际上,我们需要动态分配容器和数组内存,因此让我们解决这个问题。

这是一个完整而健壮的例子,并提供详细的评论。在此示例中,我可能更改了一些变量名称。

来自 in我的

#include <stdio.h>
#include <stdlib.h>
#include <string.h> // `memset()`


/// A container representing a dynamically-allocated array of integers
typedef struct array_of_int_s
{
    /// Pointer to the first element in a dynamically-allocated array
    /// of ints
    int * data;

    /// Number of elements in the array
    size_t size;
} array_of_int_t;

/// "Zero", or "clear", an array by setting all of its data elements to zero!
void array_of_int_zero(array_of_int_t* array_of_int)
{
    if (array_of_int == NULL)
    {
        printf("ERROR: null ptr\n");
        return;
    }

    // debugging; sample output: 40
    // printf("array_of_int->size*sizeof(array_of_int->data[0]) = %zu\n",
    //     array_of_int->size*sizeof(array_of_int->data[0]));

    memset(&array_of_int->data[0], 0,
        array_of_int->size*sizeof(array_of_int->data[0]));
}

/// A "factory" function to dynamically create and return a ptr to a
/// dynamically-allocated object containing an array of `num_elements` of type
/// `int`.
///
/// The data in the array is zeroed by this function.
///
/// See also this answer which helped me to some extent:
///     https://stackoverflow.com/a/65270682/4561887
/// and my answer where I shared this code:
///     https://stackoverflow.com/a/72653068/4561887
///
/// Returns NULL if malloc() fails due to "out of memory".
array_of_int_t* array_of_int_create(size_t num_elements)
{
    // Allocate memory for the entire struct, as well as the actual array space
    // that the `.data` member will point to, which will be located just
    // **after** the `array_of_int_t` object.
    // - Note: `sizeof(*(array_of_int->data))` is the equivalent to `sizeof
    //   (int)` in this case, except that it's more robust because if you
    //   change the `data` type in the `array_of_int_t` struct from `int*` to
    //   something else, you do NOT also have to change this `malloc()` call
    //   here!. It could also be written like this:
    //   `sizeof(array_of_int->data[0])`.
    //
    // // debugging; is 56 bytes
    // size_t num_bytes = sizeof(array_of_int_t) + num_elements*sizeof(int);
    // printf("num_bytes = %zu\n", num_bytes);
    array_of_int_t *array_of_int = (array_of_int_t*)malloc(sizeof(*array_of_int)
        + num_elements*sizeof(*(array_of_int->data)));

    if (array_of_int == NULL)
    {
        printf("ERROR: out of memory\n");
        return array_of_int;
    }

    // Set the array data to point to the first byte just past the end of the
    // `array_of_int_t` struct, which data has also been `malloc`ed just above
    // for exactly this purpose. Note that in "pointer arithmetic", doing
    // `array_of_int + 1` jumps one "element" forward, where "element" is one
    // entire `array_of_int_t` struct. Therefore, that jumps forward to point
    // to the first byte **after** the `array_of_int` object.
    //
    // I then cast it to an `int*` to point the `->data` member to it. I could
    // also cast it to a `void*` to make this code generic if I wanted, but
    // casting to `void*` can also be more error-prone because it makes the
    // compiler no longer verify the pointer type of the variable being
    // assigned, since **any** pointer can point to a `void*` type. So, I'll
    // avoid casting to `void*` here.
    array_of_int->data = (int*)(array_of_int + 1);

    array_of_int->size = num_elements;
    array_of_int_zero(array_of_int);

    return array_of_int;
}

/// Print all elements in an array
void array_of_int_print(const array_of_int_t* array_of_int)
{
    if (array_of_int == NULL)
    {
        printf("ERROR: null ptr\n");
        return;
    }

    printf("array data: {");
    for (size_t i = 0; i < array_of_int->size; i++)
    {
        printf("%i", array_of_int->data[i]);
        if (i < array_of_int->size - 1)
        {
            printf(", ");
        }
    }
    printf("}\n");
}

int main()
{
    const size_t NUM_INTS = 10;


    // 1. Basic demo

    int *p = (int*)malloc(sizeof(int)*NUM_INTS);
    printf("p can hold %zu integers\n", NUM_INTS);

    // write some data to this array
    for (size_t i = 0; i < NUM_INTS; i++)
    {
        p[i] = i;
    }

    // print the data out now
    for (size_t i = 0; i < NUM_INTS; i++)
    {
        printf("p[%zu] = %i\n", i, p[i]);
    }
    printf("\n");


    // 2. Containerized demo

    array_of_int_t array_of_int;
    // Note: `sizeof(array_of_int->data[0])` is the same as `sizeof(int)` in
    // this case, except it is more-robust since it doesn't require changing
    // the code here if you ever change the type of `.data` from `int*` to
    // something else.
    //
    // // debugging: is 40 bytes
    // size_t num_bytes = sizeof(array_of_int.data[0])*NUM_INTS;
    // printf("num_bytes = %zu\n", num_bytes);
    array_of_int.data = (int*)malloc(sizeof(array_of_int.data[0])*NUM_INTS);
    array_of_int.size = NUM_INTS;
    printf("array_of_int_t can hold %zu integers\n", array_of_int.size);

    // write all zeros to this array, then write a few values, then print the
    // whole array
    array_of_int_zero(&array_of_int);
    array_of_int.data[2] = 123;
    array_of_int.data[7] = 456789;
    array_of_int_print(&array_of_int);
    printf("\n");


    // 3. [BEST!] A fully containerized demo, with a factory "create" function
    // to dynamically make an array object! Also, with full error checking to
    // ensure `malloc()` actually worked!

    array_of_int_t * array_of_int2 = array_of_int_create(NUM_INTS);
    if (array_of_int2 == NULL)
    {
        printf("ERROR: array_of_int_create() failed (out of memory)!\n");
        exit(EXIT_FAILURE);
    }

    printf("array_of_int2 can hold %zu integers\n", array_of_int2->size);
    // the `array_of_int_create()` function already zeroed all the data, so
    // let's just write in some values then print out the whole array!
    array_of_int2->data[1] = 1;
    array_of_int2->data[5] = 5;
    array_of_int2->data[9] = 9;
    array_of_int_print(array_of_int2);
    printf("\n");


    return 0;
}

ercaguy_hello_world

eRCaGuy_hello_world/c$ gcc -Wall -Wextra -Werror -O3 -std=gnu17 containers_array_dynamic_array_of_int_with_factory_create_func.c -o bin/a -lm && bin/a
p can hold 10 integers
p[0] = 0
p[1] = 1
p[2] = 2
p[3] = 3
p[4] = 4
p[5] = 5
p[6] = 6
p[7] = 7
p[8] = 8
p[9] = 9

array_of_int_t can hold 10 integers
array data: {0, 0, 123, 0, 0, 0, 0, 456789, 0, 0}

array_of_int2 can hold 10 integers
array data: {0, 1, 0, 0, 0, 5, 0, 0, 0, 9}

See the other answer, and the comments under the question. You must keep track of the size yourself. Here is a basic demo:

#include <stdio.h>
#include <stdlib.h>

int main()
{
    const size_t NUM_INTS = 10;
    
    int *p = (int*)malloc(sizeof(int)*NUM_INTS);
    printf("p can hold %zu integers\n", NUM_INTS);

    return 0;
}

Output:

p can hold 10 integers

How to containerize a dynamically-allocated array in C

1. Make an array_int_t "array of ints" container

Let's take it one step further and containerize it as an array of integers.

Container:

/// A container represending a dynamically-allocated array of integers
typedef struct array_int_s
{
    /// Pointer to the first element in a dynamically-allocated array
    /// of ints
    int * start;

    /// Number of elements in the array
    size_t size;
} array_int_t;

Usage:

array_int_t array_int;
array_int.start = (int*)malloc(sizeof(int)*NUM_INTS);
array_int.size = NUM_INTS;
    
printf("array_int can hold %zu integers\n", array_int.size);

2. Add an array_int_create() constructor or "factory" function to create an array of ints

And one step further:

Add a create function:

/// Dynamically create and return an array of `num_elements` of type `int`.
array_int_t array_int_create(size_t num_elements)
{
    array_int_t dynamic_array = 
    {
        .start = (int*)malloc(sizeof(int)*num_elements),
        .size = num_elements,
    };
    
    return dynamic_array;
}

And use it:

array_int_t array_int2 = array_int_create(NUM_INTS);
printf("array_int2 can hold %zu integers\n", array_int2.size);

3. [BEST] Update the array_of_int_create() "factory" function to fully dynamically allocate an array container plus the array space, and return a ptr to the container

BUT, that factory function above technically isn't quite right, as it's not fully dynamically allocated. Rather, it requires each array_int_t to be statically allocated, and then it simply dynamically allocates the memory for the array only, but not the container itself. We actually need to dynamically allocate both the container and the array memory, so let's fix that.

Here is a full and robust example, with detailed comments. I may have changed some of the variable names in this example.

From containers_array_dynamic_array_of_int_with_factory_create_func.c in my eRCaGuy_hello_world repo:

#include <stdio.h>
#include <stdlib.h>
#include <string.h> // `memset()`


/// A container representing a dynamically-allocated array of integers
typedef struct array_of_int_s
{
    /// Pointer to the first element in a dynamically-allocated array
    /// of ints
    int * data;

    /// Number of elements in the array
    size_t size;
} array_of_int_t;

/// "Zero", or "clear", an array by setting all of its data elements to zero!
void array_of_int_zero(array_of_int_t* array_of_int)
{
    if (array_of_int == NULL)
    {
        printf("ERROR: null ptr\n");
        return;
    }

    // debugging; sample output: 40
    // printf("array_of_int->size*sizeof(array_of_int->data[0]) = %zu\n",
    //     array_of_int->size*sizeof(array_of_int->data[0]));

    memset(&array_of_int->data[0], 0,
        array_of_int->size*sizeof(array_of_int->data[0]));
}

/// A "factory" function to dynamically create and return a ptr to a
/// dynamically-allocated object containing an array of `num_elements` of type
/// `int`.
///
/// The data in the array is zeroed by this function.
///
/// See also this answer which helped me to some extent:
///     https://stackoverflow.com/a/65270682/4561887
/// and my answer where I shared this code:
///     https://stackoverflow.com/a/72653068/4561887
///
/// Returns NULL if malloc() fails due to "out of memory".
array_of_int_t* array_of_int_create(size_t num_elements)
{
    // Allocate memory for the entire struct, as well as the actual array space
    // that the `.data` member will point to, which will be located just
    // **after** the `array_of_int_t` object.
    // - Note: `sizeof(*(array_of_int->data))` is the equivalent to `sizeof
    //   (int)` in this case, except that it's more robust because if you
    //   change the `data` type in the `array_of_int_t` struct from `int*` to
    //   something else, you do NOT also have to change this `malloc()` call
    //   here!. It could also be written like this:
    //   `sizeof(array_of_int->data[0])`.
    //
    // // debugging; is 56 bytes
    // size_t num_bytes = sizeof(array_of_int_t) + num_elements*sizeof(int);
    // printf("num_bytes = %zu\n", num_bytes);
    array_of_int_t *array_of_int = (array_of_int_t*)malloc(sizeof(*array_of_int)
        + num_elements*sizeof(*(array_of_int->data)));

    if (array_of_int == NULL)
    {
        printf("ERROR: out of memory\n");
        return array_of_int;
    }

    // Set the array data to point to the first byte just past the end of the
    // `array_of_int_t` struct, which data has also been `malloc`ed just above
    // for exactly this purpose. Note that in "pointer arithmetic", doing
    // `array_of_int + 1` jumps one "element" forward, where "element" is one
    // entire `array_of_int_t` struct. Therefore, that jumps forward to point
    // to the first byte **after** the `array_of_int` object.
    //
    // I then cast it to an `int*` to point the `->data` member to it. I could
    // also cast it to a `void*` to make this code generic if I wanted, but
    // casting to `void*` can also be more error-prone because it makes the
    // compiler no longer verify the pointer type of the variable being
    // assigned, since **any** pointer can point to a `void*` type. So, I'll
    // avoid casting to `void*` here.
    array_of_int->data = (int*)(array_of_int + 1);

    array_of_int->size = num_elements;
    array_of_int_zero(array_of_int);

    return array_of_int;
}

/// Print all elements in an array
void array_of_int_print(const array_of_int_t* array_of_int)
{
    if (array_of_int == NULL)
    {
        printf("ERROR: null ptr\n");
        return;
    }

    printf("array data: {");
    for (size_t i = 0; i < array_of_int->size; i++)
    {
        printf("%i", array_of_int->data[i]);
        if (i < array_of_int->size - 1)
        {
            printf(", ");
        }
    }
    printf("}\n");
}

int main()
{
    const size_t NUM_INTS = 10;


    // 1. Basic demo

    int *p = (int*)malloc(sizeof(int)*NUM_INTS);
    printf("p can hold %zu integers\n", NUM_INTS);

    // write some data to this array
    for (size_t i = 0; i < NUM_INTS; i++)
    {
        p[i] = i;
    }

    // print the data out now
    for (size_t i = 0; i < NUM_INTS; i++)
    {
        printf("p[%zu] = %i\n", i, p[i]);
    }
    printf("\n");


    // 2. Containerized demo

    array_of_int_t array_of_int;
    // Note: `sizeof(array_of_int->data[0])` is the same as `sizeof(int)` in
    // this case, except it is more-robust since it doesn't require changing
    // the code here if you ever change the type of `.data` from `int*` to
    // something else.
    //
    // // debugging: is 40 bytes
    // size_t num_bytes = sizeof(array_of_int.data[0])*NUM_INTS;
    // printf("num_bytes = %zu\n", num_bytes);
    array_of_int.data = (int*)malloc(sizeof(array_of_int.data[0])*NUM_INTS);
    array_of_int.size = NUM_INTS;
    printf("array_of_int_t can hold %zu integers\n", array_of_int.size);

    // write all zeros to this array, then write a few values, then print the
    // whole array
    array_of_int_zero(&array_of_int);
    array_of_int.data[2] = 123;
    array_of_int.data[7] = 456789;
    array_of_int_print(&array_of_int);
    printf("\n");


    // 3. [BEST!] A fully containerized demo, with a factory "create" function
    // to dynamically make an array object! Also, with full error checking to
    // ensure `malloc()` actually worked!

    array_of_int_t * array_of_int2 = array_of_int_create(NUM_INTS);
    if (array_of_int2 == NULL)
    {
        printf("ERROR: array_of_int_create() failed (out of memory)!\n");
        exit(EXIT_FAILURE);
    }

    printf("array_of_int2 can hold %zu integers\n", array_of_int2->size);
    // the `array_of_int_create()` function already zeroed all the data, so
    // let's just write in some values then print out the whole array!
    array_of_int2->data[1] = 1;
    array_of_int2->data[5] = 5;
    array_of_int2->data[9] = 9;
    array_of_int_print(array_of_int2);
    printf("\n");


    return 0;
}

Sample output:

eRCaGuy_hello_world/c$ gcc -Wall -Wextra -Werror -O3 -std=gnu17 containers_array_dynamic_array_of_int_with_factory_create_func.c -o bin/a -lm && bin/a
p can hold 10 integers
p[0] = 0
p[1] = 1
p[2] = 2
p[3] = 3
p[4] = 4
p[5] = 5
p[6] = 6
p[7] = 7
p[8] = 8
p[9] = 9

array_of_int_t can hold 10 integers
array data: {0, 0, 123, 0, 0, 0, 0, 456789, 0, 0}

array_of_int2 can hold 10 integers
array data: {0, 1, 0, 0, 0, 5, 0, 0, 0, 9}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文