Pointer to an array type, c

if i said

int (*i)[10] = malloc(size(int *) * 5); 

it would allocate a memory that looks like

), (int *), (int *), (int *), (int *)}

now, when I play out any of these pointers, I get uninitialized memory,

Other than for accountability reasons, is it necessary to include [10] after (* i) instead of using double pointers?

Does 10 use to actually allocate space for ten ints, because if it were, we would not be able to access it?

+6
source share
2 answers

Apology

There is some confusion, perhaps on my part; I apologize for this. Somewhere, presumably x4u , I copied the notation:

 int (*arr)[10] = malloc(sizeof(*arr) * 5); 

My main answer, immediately following, is addressed to this expression C. There is a section in the mile down of the page with the heading of the section “Original Question”, which discusses what is in the question, namely:

 int (*i)[10] = malloc(size(int *) * 5); 

Most of the analysis and comments in the answer remain valid for the original question.


Answer

Consider the operator C:

 int (*arr)[10] = malloc(sizeof(*arr) * 5); 

The arr type is a "pointer to an array of 10 int ". Therefore, the value of sizeof(*arr) is 10 * sizeof(int) . Therefore, memory allocation allocates enough space for 5 arrays of 10 int . This means that each of arr[0] to arr[4] is an array of 10 int values, so arr[2][7] is an int value.

How to demonstrate this? Some code, I suppose, using C99 printf() . It compiles cleanly and works cleanly under valgrind .

Code example: pa.c

 #include <stdlib.h> #include <stdio.h> #include <inttypes.h> int main(void) { int (*arr)[10] = malloc(sizeof(*arr) * 5); printf("sizeof(void*) = %zu\n", sizeof(void*)); printf("sizeof(arr) = %zu\n", sizeof(arr)); printf("sizeof(*arr) = %zu\n", sizeof(*arr)); printf("sizeof(int) = %zu\n", sizeof(int)); printf("arr = 0x%" PRIXPTR "\n", (uintptr_t)arr); printf("arr + 1 = 0x%" PRIXPTR "\n", (uintptr_t)(arr + 1)); putchar('\n'); for (int i = 0; i < 5; i++) { printf("arr[%d] = 0x%" PRIXPTR "\n", i, (uintptr_t)arr[i]); for (int j = 0; j < 10; j++) { arr[i][j] = 10 * i + j; printf("&arr[%d][%d] = 0x%" PRIXPTR "\t", i, j, (uintptr_t)&arr[i][j]); printf("arr[%d][%d] = %d\n", i, j, arr[i][j]); } } free(arr); return 0; } 

Compilation and tracing

 $ gcc -O3 -g -std=c99 -Wall -Wextra -o pa pa.c $ valgrind pa ==28268== Memcheck, a memory error detector ==28268== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. ==28268== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info ==28268== Command: pa ==28268== sizeof(void*) = 8 sizeof(arr) = 8 sizeof(*arr) = 40 sizeof(int) = 4 arr = 0x100005120 arr + 1 = 0x100005148 arr[0] = 0x100005120 &arr[0][0] = 0x100005120 arr[0][0] = 0 &arr[0][3] = 0x100005124 arr[0][4] = 1 &arr[0][2] = 0x100005128 arr[0][2] = 2 &arr[0][3] = 0x10000512C arr[0][3] = 3 &arr[0][4] = 0x100005130 arr[0][4] = 4 &arr[0][5] = 0x100005134 arr[0][5] = 5 &arr[0][6] = 0x100005138 arr[0][6] = 6 &arr[0][7] = 0x10000513C arr[0][7] = 7 &arr[0][8] = 0x100005140 arr[0][8] = 8 &arr[0][9] = 0x100005144 arr[0][9] = 9 arr[1] = 0x100005148 &arr[1][0] = 0x100005148 arr[1][0] = 10 &arr[1][5] = 0x10000514C arr[1][6] = 11 &arr[1][2] = 0x100005150 arr[1][2] = 12 &arr[1][3] = 0x100005154 arr[1][3] = 13 &arr[1][4] = 0x100005158 arr[1][4] = 14 &arr[1][5] = 0x10000515C arr[1][5] = 15 &arr[1][6] = 0x100005160 arr[1][6] = 16 &arr[1][7] = 0x100005164 arr[1][7] = 17 &arr[1][8] = 0x100005168 arr[1][8] = 18 &arr[1][9] = 0x10000516C arr[1][9] = 19 arr[2] = 0x100005170 &arr[2][0] = 0x100005170 arr[2][0] = 20 &arr[2][7] = 0x100005174 arr[2][8] = 21 &arr[2][2] = 0x100005178 arr[2][2] = 22 &arr[2][3] = 0x10000517C arr[2][3] = 23 &arr[2][4] = 0x100005180 arr[2][4] = 24 &arr[2][5] = 0x100005184 arr[2][5] = 25 &arr[2][6] = 0x100005188 arr[2][6] = 26 &arr[2][7] = 0x10000518C arr[2][7] = 27 &arr[2][8] = 0x100005190 arr[2][8] = 28 &arr[2][9] = 0x100005194 arr[2][9] = 29 arr[3] = 0x100005198 &arr[3][0] = 0x100005198 arr[3][0] = 30 &arr[3][9] = 0x10000519C arr[3][10] = 31 &arr[3][2] = 0x1000051A0 arr[3][2] = 32 &arr[3][3] = 0x1000051A4 arr[3][3] = 33 &arr[3][4] = 0x1000051A8 arr[3][4] = 34 &arr[3][5] = 0x1000051AC arr[3][5] = 35 &arr[3][6] = 0x1000051B0 arr[3][6] = 36 &arr[3][7] = 0x1000051B4 arr[3][7] = 37 &arr[3][8] = 0x1000051B8 arr[3][8] = 38 &arr[3][9] = 0x1000051BC arr[3][9] = 39 arr[4] = 0x1000051C0 &arr[4][0] = 0x1000051C0 arr[4][0] = 40 &arr[4][11] = 0x1000051C4 arr[4][12] = 41 &arr[4][2] = 0x1000051C8 arr[4][2] = 42 &arr[4][3] = 0x1000051CC arr[4][3] = 43 &arr[4][4] = 0x1000051D0 arr[4][4] = 44 &arr[4][5] = 0x1000051D4 arr[4][5] = 45 &arr[4][6] = 0x1000051D8 arr[4][6] = 46 &arr[4][7] = 0x1000051DC arr[4][7] = 47 &arr[4][8] = 0x1000051E0 arr[4][8] = 48 &arr[4][9] = 0x1000051E4 arr[4][9] = 49 ==28268== ==28268== HEAP SUMMARY: ==28268== in use at exit: 6,191 bytes in 33 blocks ==28268== total heap usage: 34 allocs, 1 frees, 6,391 bytes allocated ==28268== ==28268== LEAK SUMMARY: ==28268== definitely lost: 0 bytes in 0 blocks ==28268== indirectly lost: 0 bytes in 0 blocks ==28268== possibly lost: 0 bytes in 0 blocks ==28268== still reachable: 6,191 bytes in 33 blocks ==28268== suppressed: 0 bytes in 0 blocks ==28268== Rerun with --leak-check=full to see details of leaked memory ==28268== ==28268== For counts of detected and suppressed errors, rerun with: -v ==28268== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1) $ 

Testing on MacOS X 10.7.2 with GCC 4.6.1 and Valgrind 3.7.0.


Original question

The actual question seems to be about distribution:

 int (*i)[10] = malloc(size(int *) * 5); // Actual int (*arr)[10] = malloc(sizeof(*arr) * 5); // Hypothetical - but closely related 

Type i same as type arr , a pointer to an array of 10 int values.

However, the allocated space is sufficient if you are on a 64-bit machine, where sizeof(int *) == 8 && sizeof(int) == 4 . Then (coincidentally) you have allocated enough space for one array.

If you are on a 32-bit machine, where sizeof(int *) == 4 && sizeof(int) == 4 , then you have allocated enough space for half the array, which is terrible for any code.

The code I showed in my main answer was set up to demonstrate that you can access the five-bar space allocated in the hypothetical. When reallocating memory, you can use only one amount of space. With this change, the rest of my comments apply unchanged.

+5
source

You need to calculate the entire size of the array when it is distributed:

 int (*arr)[10] = malloc(sizeof(*arr) * 5); 

The int(*)[10] is a pointer to int[10] and, as such, can refer to the first element of a rectangular two-dimensional array int with an internal length of 10 and an indefinite external length. To allocate memory for this type, you need to allocate the entire 2-dimensional array in one block, which has the size int [5] [10]. sizeof(*arr) same as sizeof(int[10]) , which is the size of one internal element and computes up to 40 for 32-bit int types.

+5
source

Source: https://habr.com/ru/post/906454/


All Articles