What does this line in code mean? (array of pointers to chars)? - c

In this code, the "array" is an array of pointers to chars? Or something else?
struct tmep{
char (*array) [SIZE];
}
Thanks in advance :)

It's a pointer to an array of SIZE chars.
Declaration mimics use, so you evaluate the parenthesis first, (*array) gives you a char[SIZE].
To allocate, the stable version is as usual
array = malloc(num_elements * sizeof *array);
to specify the size of each object (char[SIZE] here) in the block by taking the sizeof the dereferenced pointer. You don't need to change that allocation if the type changes e.g. to int (*)[SIZE].
If you want to specify the type,
array = malloc(num_elements * sizeof(char (*)[SIZE]));
This allocates - if malloc succeeds - a block large enough for num_elements arrays of SIZE chars, each of these arrays is accessed with
array[i]
and the chars in the arrays in the block with
array[i][j]

Related

Two dimension arrays and pointer representation

Three questions in 1.
If I have a 2-D array -
int array_name[num_rows][num_columns]
So it consists of num_rows arrays -each of which is an array of size = num_columns. Its equivalent representation using an array of pointers is-
int* array_name[num_rows]
-so the index given by [num_rows] still shows the number of 1-D arrays - somewhere using malloc we can then specify the size of each of the 1-D arrays as num_columns. Is that right? I saw some texts telling
int* array_name[num_columns]
will the indices not get switched in this case ?
For a ID array I specify size dynamically as-
int *p;
p = (int*) malloc (size * sizeof(int))
For 2 D arrays do I specify the size of entire 2-D array or of one 1-D array in malloc -
int*p [row_count];
p = (int*) malloc (row_count * column_count * sizeof(int))
or
p = (int*) malloc (column_count * sizeof(int))
I think it should be the second since p is a pointer to a 1-D array and p+1 is a pointer to a 1-D array etc. Please clarify.
For ques 2 - what if p was defined as -
int **p; rather than
int * p[row_count]
How will the malloc be used then? I think it should be -
p = (int*) malloc (row_count * column_count * sizeof(int))
Please correct, confirm, improve.
Declaring :
int *array_name[num_rows];
or :
int *array_name[num_columns];
is the same thing. Only the name changes, but your variable is still referring to rows because C is a row major so you should name it row.
Here is how to allocate a 2D array :
int (*p)[column] = malloc (sizeof(int[row][column]);
An int ** can be allocated whereas int [][] is a temporary array defined only in the scope of your function.
Don't forget that a semicolon is needed at the end of nearly every line.
You should read this page for a more complete explanation of the subject
(and 2.)
If I have a 2-D array
int array_name[num_rows][num_columns];
So it consists of num_rows arrays -each of which is an array of size = num_columns.
If both num_rows and num_columns are known at compile time, that line declares an array of num_rows arrays of num_columns ints, which, yes, is commonly referred as a 2D array of int.
Since C99 (and optionally in C11) you can use two variables unknown at compile time and end up declaring a Variable-Length Array, instead.
Its equivalent representation using an array of pointers is
int* array_name[num_rows];
So the index given by [num_rows] still shows the number of 1-D arrays - somewhere using malloc we can then specify the size of each of the 1-D arrays as num_columns. Is that right?
Technically, now array_name is declared as an array of num_rows pointers to int, not arrays. To "complete" the "2D array", one should traverse the array and allocate memory for each row. Note that the rows could have different sizes.
Using this form:
int (*array_name)[num_columns];
// ^ ^ note the parenthesis
array_name = malloc(num_rows * sizeof *array_name);
Here, array_name is declared as a pointer to an array of num_columns ints and then the desired number of rows is allocated.
3.
what if p was defined as int **p;
The other answers show how to allocate memory in this case, but while it is widely used, it isn't always the best solution. See e.g.:
Correctly allocating multi-dimensional arrays

Cannot understand the meaning of two lines in C

This program reads a text file into a string array, line by line. I can't understand the meaning of two lines in the code:
char **words = (char **)malloc(sizeof(char*)*lines_allocated);
...
words = (char **)realloc(words,sizeof(char*)*new_size);
...
Please could you help me understand them?
char **words = (char **)malloc(sizeof(char*)*lines_allocated);
Allocates lines_allocated pointers. When you use pointer to pointers you need to allocate space for the pointers, and them for each of those pointers you allocate space for you data, in this case, a char *.
words = (char **)realloc(words,sizeof(char*)*new_size);
This changes the size of the buffer, as the number of lines is unknown before you read the file, then you need to increase the number of pointers you allocate.
words points to a block that will store lines_allocated pointers at first moment and then it will be increased to new_size when needed.
In your code you also have a line like this:
/* Allocate space for the next line */
words[i] = malloc(max_line_len);
Which will allocate each string separately.
Also, don't cast the result of malloc:
Do I cast the result of malloc?
The first line allocates a chunk of dynamic memory (creates space for an array of pointers to char); the second line resizes that chunk.
A better way to write both lines is
char **words = malloc( sizeof *words * lines_allocated); // no cast, operand of sizeof
char **tmp = realloc( words, sizeof *words * new_size );
if ( tmp )
words = tmp;
In C, you don't need to cast the result of either call, and it's considered bad practice to do so. Also, note the operand to sizeof; if you ever change the base type of words (from char to wchar_t, for example), you won't have to change the malloc or realloc calls.
realloc will return NULL if it can't extend the buffer, so it's safer to assign the result to a temporary variable first, otherwise you risk losing your reference to that memory, meaning you won't be able to access or release it.
The first line allocates a pointer to a pointer to character. A pointer to something in C is equivalent to a pointer to an array of that same something, so this is equivalent to saying that it allocates a pointer to an array of pointers to char.
sizeof(char*) is the size of a pointer, and multiplying it by lines_allocated means that the number of pointers in the allocated array will be lines_allocated.
The second line reallocates the array of pointers so that it may now contain new_size pointers instead of lines_allocated pointers. If new_size is larger, the new pointers will be undefined, and must be initialized before being used.

Why am I not getting the correct size after using malloc and printing using sizeof?

This is my code.
#include<stdio.h>
typedef struct {
int a,b;
} integers;
void main() {
integers *ptr = (integers *)malloc(10*sizeof(integers));
printf("%d",sizeof(*ptr)); // prints 8
}
From what I understand about Malloc, the above code should actually reserve 10x8=80 bytes of memory for ptr to point to.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
Because you're using sizeof(*ptr) you're actually asking for the size of the first element in the allocated buffer, thus sizeof will return the size of the first element in ptr (i.e. 2x4 bytes integers on 32bits system) rather than the allocated size.
Also, please note that even if you'd use sizeof(ptr) you'd get the size of the ptr pointer which on 32bits system would be 4 bytes.
Well, I know that this question is pretty outdated but finding no suitable answer, I decided to write one.
When specifying sizeof(*ptr), you're actually trying to reach out for the size of data type you've stored in the variable that the pointer is pointing to( here its the first element of the array). Here, that's quite evidently 8.
Even when you'll try to print sizeof(ptr), you'll be again printing the size of the pointer address which by default is 8 bytes in GCC compilers as the data type is long unsigned int.
Why then does using sizeof(*ptr) give only 8? How do I find the total size being allocated for ptr?
The type of the expression *ptr is integers - thus,
sizeof *ptr == sizeof (integers) == sizeof (int) + sizeof (int)
You cannot determine the size of the allocated buffer by looking at the pointer (it doesn't store any metadata about the buffer size). You will have to keep track of that information separately.
Edit
Note that you can do something like the following:
integers (*foo)[10] = malloc( sizeof *foo );
if ( foo )
printf( "sizeof *foo = %zu\n", sizeof *foo );
and that will give you the result you're expecting. In this case, foo is a pointer to an array of integers, not to a single instance of integers, so sizeof *foo will give you the size of the allocated array. The downside is that you have to expliticly dereference foo before applying the subscript:
(*foo)[i].a = some_value(); // or foo[0][i].a
(*foo)[i].b = some_other_value(); // or foo[0][i].b
This is normally done when you want to allocate an NxM array and make sure all the rows are contiguous:
integers (*foo)[10] = malloc( 10 * sizeof *foo );
will allocate a 10x10 array of integers such that the rows are all adjacent in memory.
Also, a pointer to a 10-element array of integers is not compatible with a pointer to an 11-element array of integers, making it more difficult to write functions that can work with pointers to arrays of different sizes. IOW, if you have a function declared as
void bar( integers (*foo)[10] ) { ... }
it can only work with Nx10 arrays of integers. There are ways around this that involve varying levels of pain, but that's a topic for another day.

Dynamic memory allocation for 2D array

I want to allot memory dynamically for a 2D array.
Is there any difference between these two ?
1)
array = (int**)malloc(size * sizeof(int*));
for (i = 0; i < size; i++) {
array[i] = (int *) malloc(size * sizeof(int));
}
2)
array = (int**)malloc(size *size* sizeof(int));
If yes, what is better to use and why ?
In the first case
array = (int**)malloc(size * sizeof(int*));
for (i = 0; i < size; i++) {
array[i] = (int *) malloc(size * sizeof(int));
}
you are allocating size extents of the size equal to size * sizeof( int ) That is you are allocating size one-dimensional arrays. Accordingly you are allocating size pointers that point to first elements of these one-dimensional arrays.
In the second case expression
(int**)malloc(size *size* sizeof(int))
means allocation of an extent of size * size of objects of type int and the returned pointer is interpretated as int **. So this expression has no sense independing on what is placed in the left side of the assignment. take into account that the size of pointer can be greater than the size of int.
You could write instead
int ( *array )[size] = ( int (*)[size] )malloc(size *size* sizeof(int));
In this case you are indeed allocating a two dimensional array provided that size is a constant expression.
Those two solutions are very different. The first will give you a vector of pointers to vectors. The second will give you a vector of the requested size. It all depends on your use case. Which do you want?
When it comes to releasing the memory, the first can only be freed by calling free for each pointer in the vector and then a final free on the vector itself. The second can be freed with a single call. Don't have that be your deciding reason to use one or the other. It all depends on your use case.
What is the type of the object you want to allocate? Is it an int **, an int *[] or an int[][]?
I want to allot memory dynamically for a 2 dimensional array.
Then just do
int (*arr)[size] = malloc(size * sizeof *arr);
Is there any difference between these two ?
Yes, they are wrong because of different errors. The first attempt does not allocate a 2D array, it allocates an array of pointers and then a bunch of arrays of ints. Hence the result will not necessarily be contiguous in memory (and anyway, a pointer-to-pointer is not the same thing as a two-dimensional array.)
The second piece of code does allocate a contiguous block of memory, but then you are treating it as if it was a pointer-to-pointer, which is still not the same thing.
Oh, and actually, both snippets have a common error: the act of casting the return value of malloc().

C dynamic memory allocation and sizeof()

I'm having some trouble understanding the difference between these two code segments:
I allocate space for an array of integers dynamically within my code with the following statement
int *arr = calloc(cnt, sizeof(int));
In another function, where I pass in arr, I would like to determine the size (number of elements) in arr.
When I call
int arr_sz = sizeof(arr)/sizeof(int);
it only returns 1, which is just the number of bytes in an int for both arguments I am assuming (4/4)=1.
I just assumed it would be the same as using an array
int arr[8];
int arr_sz = sizeof(arr)/sizeof(int);
which returns the actual number of elements in the array.
If anyone could clear this up, that would be great. Thanks!
int *arr; ----> Pointer
int arr[8]; ----> Array
First up what you got there - int *arr is a pointer, pointing to some bytes of memory location, not an array.
The type of an Array and a Pointer is not the same.
In another function where I pass in arr, I would like to determine the size (number elements) in arr. When I call
int arr_sz = sizeof(arr)/sizeof(int);
it only returns 1, which is just the number of bytes in an int for both arguments I am assuming (4/4)=1. I just assumed it would be the same as using an array
Even if it is assumed to be an Array -- that's because Arrays get decayed into pointers when passed into functions. You need to explicitly pass the array size in functions as a separate argument.
Go through this:
Sizeof an array in the C programming language?
There is a difference between a static array and dynamic memory allocation.
The sizeof operator will not work on dynamic allocations.
AFAIK it works best with stack-based and predefined types.
well, int *arr declares a pointer, a variable which keeps the address of some other variable, and its size is the size of an integer because it's a pointer, it just have to keep the address, not the pointee itself.
int arr[8] declares an array, a collection of integers. sizeof(arr) refers to the size of the entire collection, so 8*sizeof(int).
Often you hear that "array and pointers are the same things". That's not true! They're different things.
Mike,
arr is a pointer and as such, on your system at least, has the same number of bytes as int. Array's are not always the same as pointers to the array type.
sizeof(arr) is the same as sizeof(int*), i.e. the size of a single pointer. You can however calculate arr_sz as ... cnt!
*arr is not the same as arr[8] since it's size is not known in compile time, and sizeof is a function of the compiler. So when your arr is *arr sizeof will return the size of the pointer (sizeof(int *))in bytes, while when your arr is arr[8], the sizeof will return the size of array of 8 integers in bytes (which is sizeof(int) * 8).
When you pass a pointer to array to a function, you must specify its size, because the compiler can't do it for you. Another way is to end the array with null element, and perform a while loop.
If you have int arr1[8] the type of arr1 (as far as the compiler is concerned) is an array ints of size 8.
In the example int * arr2 the type of arr2 is pointer to an integer.
sizeof(arr1) is the size of an int array
sizeof(arr2) is the size of an int pointer (4 bytes on a 32 bit system, 8 bytes on a 64 bit system)
So, the only difference is the type which the compiler thinks that variable is.
You can't use sizeof with memory pointers:
int *arr = calloc(cnt, sizeof(int));
But it's ok to use it with arrays:
int arr[8];

Resources