Result of 'sizeof' on array of structs in C? - c

In C, I have an array of structs defined like:
struct D
{
char *a;
char *b;
char *c;
};
static struct D a[] = {
{
"1a",
"1b",
"1c"
},
{
"2a",
"2b",
"2c"
}
};
I would like to determine the number of elements in the array, but sizeof(a) returns an incorrect result: 48, not 2. Am I doing something wrong, or is sizeof simply unreliable here? If it matters I'm compiling with GCC 4.4.

sizeof gives you the size in bytes, not the number of elements. As Alok says, to get the number of elements, divide the size in bytes of the array by the size in bytes of one element. The correct C idiom is:
sizeof a / sizeof a[0]

sizeof a / sizeof a[0];
This is a compile-time constant, so you can use it to, for example, create another array:
#define N sizeof a / sizeof a[0]
int n_a[N];

sizeof returns the size in memory of the passed element. By dividing the size of an array by a single element size, you get the elements count.
Note that the element size may include some padding bytes as well. For this reason, a padded struct (e.g. when a char member is followed by a pointer) will have a sizeof value greater than it members size sum.
On the other hand, don't let it bother you when counting elements in an array: sizeof(a) / sizeof(a[0]) will still work as smooth as expected.

ssize_t portfoySayisi = sizeof(*portfoyler);
THIS ONE WORKS

Related

Use array annotation with pointers

I have currently trouble understanding the following scenario:
I have a multidimensional array of Strings and I want to address it by using pointers only but I always get a Segmentation Fault when using the array annotation on the pointer. This is just an example code I want to use the 3D array in a pthread so I want to pass it in via a structure as a pointer but it just doesn't work and I would like to know why? I thought pointers and arrays are functionally equivalent? Here is the sample code:
#include <stdio.h>
void func(unsigned char ***ptr);
int main() {
// Image of dimension 10 times 10
unsigned char image[10][10][3];
unsigned char ***ptr = image;
memcpy(image[0][0], "\120\200\12", 3);
// This works as expected
printf("Test: %s", image[0][0]);
func(image);
return 0;
}
void func(unsigned char ***ptr) {
// But here I get a Segmentation Fault but why??
printf("Ptr: %s", ptr[0][0]);
}
Thanks in advance for your help :)
I think maybe strdup confuses the issue. Pointers and arrays are not always equivalent. Let me try to demonstrate. I always avoid actual multi-dimension arrays, so I may make a mistake here, but:
int main()
{
char d3Array[10][10][4]; //creates a 400-byte contiguous memory area
char ***d3Pointer; //a pointer to a pointer to a pointer to a char.
int i,j;
d3Pointer = malloc(sizeof(char**) * 10);
for (i = 0; i < 10; ++i)
{
d3Pointer[i] = malloc(sizeof(char*) * 10);
for (j = 0; j < 4; ++j)
{
d3Pointer[i][j] = malloc(sizeof(char) * 4);
}
}
//this
d3Pointer[2][3][1] = 'a';
//is equivalent to this
char **d2Pointer = d3Pointer[2];
char *d1Pointer = d2Pointer[3];
d1Pointer[1] = 'a';
d3Array[2][3][1] = 'a';
//is equivalent to
((char *)d3Array)[(2 * 10 * 4) + (3 * 4) + (1)] = 'a';
}
Generally, I use the layered approach. If I want contiguous memory, I handle the math myself..like so:
char *psuedo3dArray = malloc(sizeof(char) * 10 * 10 * 4);
psuedo3dArray[(2 * 10 * 4) + (3 * 4) + (1)] = 'a';
Better yet, I use a collection library like uthash.
Note that properly encapsulating your data makes the actual code incredibly easy to read:
typedef unsigned char byte_t;
typedef struct
{
byte_t r;
byte_t g;
byte_t b;
}pixel_t;
typedef struct
{
int width;
int height;
pixel_t * pixelArray;
}screen_t;
pixel_t *getxyPixel(screen_t *pScreen, int x, int y)
{
return pScreen->pixelArray + (y*pScreen->width) + x;
}
int main()
{
screen_t myScreen;
myScreen.width = 1024;
myScreen.height = 768;
myScreen.pixelArray = (pixel_t*)malloc(sizeof(pixel_t) * myScreen.height * myScreen.width);
getxyPixel(&myScreen, 150, 120)->r = 255;
}
In C, you should allocate space for your 2D array one row at a time. Your definition of test declares a 10 by 10 array of char pointers, so you don't need to call malloc for it. But to store a string you need to allocate space for the string. Your call to strcpy would crash. Use strdup instead. One way to write your code is as follows.
char ***test = NULL;
char *ptr = NULL;
test = malloc(10 * sizeof(char **));
for (int i = 0; i < 10; i++) {
test[i] = malloc(10 * sizeof(char *));
}
test[0][0] = strdup("abc");
ptr = test[0][0];
printf("%s\n", ptr);
test[4][5] = strdup("efg");
ptr = test[4][5];
printf("%s\n", ptr);
Alternatively, if you want to keep your 10 by 10 definition, you could code it like this:
char *test[10][10];
char *ptr = NULL;
test[0][0] = strdup("abc");
ptr = test[0][0];
printf("%s\n", ptr);
test[4][5] = strdup("efg");
ptr = test[4][5];
printf("%s\n", ptr);
Your problem is, that a char[10][10][3] is something very different from a char***: The first is an array of arrays of arrays, the later is a pointer to a pointer to a pointer. The confusions arises because both can be dereferenced with the same syntax. So, here is a bit of an explanation:
The syntax a[b] is nothing but a shorthand for *(a + b): First you perform pointer arithmetic, then you dereference the resulting pointer.
But, how come you can use a[b] when a is an array instead of a pointer? Well, because...
Arrays decay into pointers to their first element: If you have an array declared like int array[10], saying array + 3 results in array decaying to a pointer of type int*.
But, how does that help to evaluate a[b]? Well, because...
Pointer arithmetic takes the size of the target into account: The expression array + 3 triggers a calculation along the lines of (size_t)array + 3*sizeof(*array). In our case, the pointer that results from the array-pointer-decay points to an int, which has a size, say 4 bytes. So, the pointer is incremented by 3*4 bytes. The result is a pointer that points to the fourths int in the array, the first three elements are skipped by the pointer arithmetic.
Note, that this works for arrays of any element type. Arrays can contain bytes, or integers, or floats, or structs, or other arrays. The pointer arithmetic is the same.
But, how does that help us with multidimensional arrays? Well, because...
Multidimensional arrays are just 1D arrays that happen to contain arrays as elements: When you declare an array with char image[256][512]; you are declaring a 1D array of 256 elements. These 256 elements are all arrays of 512 characters, each. Since the sizeof(char) == 1, the size of an element of the outer array is 512*sizeof(char) = 512, and, since we have 256 such arrays, the total size of image is 256*512. Now, I can declare a 3D array with char animation[24][256][512];...
So, going back to your example that uses
char image[10][10][3]
what happens when you say image[1][2][1] is this: The expression is equivalent to this one:
*(*(*(image + 1) + 2) + 3)
image being of type char[10][10][3] decays into a pointer to its first element, which is of type char(*)[10][3] The size of that element is 10*3*1 = 30 bytes.
image + 1: Pointer arithmetic is performed to add 1 to the resulting pointer, which increments it by 30 bytes.
*(image + 1): The pointer is dereferenced, we are now talking directly about the element, which is of type char[10][3].
This array again decays into a pointer to its first element, which is of type char(*)[3]. The size of the element is 3*1 = 3. This pointer points at the same byte in memory as the pointer that resulted from step 2. The only difference is, that it has a different type!
*(image + 1) + 2: Pointer arithmetic is performed to add 2 to the resulting pointer, which increments it by 2*3 = 6 bytes. Together with the increment in step 2, we now have an offset of 36 bytes, total.
*(*(image + 1) + 2): The pointer is dereferenced, we are now talking directly about the element, which is of type char[3].
This array again decays into a pointer to its first element, which is of type char*. The size of the element is now just a single byte. Again, this pointer has the same value as the pointer resulting from step 5, but a different type.
*(*(image + 1) + 2) + 1: Pointer arithmetic again, adding 1*1 = 1 bytes to the total offset, which increases to 37 bytes.
*(*(*(image + 1) + 2) + 1): The pointer is dereferenced the last time, we are now talking about the char at an offset of 37 bytes into the image.
So, what's the difference to a char***? When you dereference a char***, you do not get any array-pointer-decay. When you try to evaluate the expression pointers[1][2][1] with a variable declared as
char*** pointers;
the expression is again equivalent to:
*(*(*(pointers + 1) + 2) + 3)
pointers is a pointer, so no decay happens. Its type is char***, and it points to a value of type char**, which likely has a size of 8 bytes (assuming a 64 bit system).
pointers + 1: Pointer arithmetic is performed to add 1 to the resulting pointer, which increments it by 1*8 = 8 bytes.
*(pointers + 1): The pointer is dereferenced, we are now talking about the pointer value that is found in memory at an offset of 8 bytes of where pointers points.
Further steps depending on what actually happened to be stored at pointers[1]. These steps do not involve any array-pointer-decay, and thus load pointers from memory instead.
You see, the difference between a char[10][10][3] and a char*** is profound. In the first case, the array-pointer-decay transforms the process into a pure offset computation into a multidimensional array. In the later case, we repeatedly load pointers from memory when accessing elements, all we ever have are 1D arrays of pointers. And it's all down to the types of pointers!

How to know the array length and put it in an integer variable in C?

How can I know the array length and put it in an integer variable in C?
int array []={1,2,3,4,5};
int arrayLength = ???????? ;
int i;
for (i = 0; i < arrayLength ;i++){
printf("the i is :%i \n", i );
}
I would use:
const size_t arrayLength = sizeof array / sizeof *array;
The first sizeof array is the size (in bytes) of all of array, the second is the size of the first element and when divided that becomes the number of elements.
Sizes are good to keep as size_t, and of course it's const since it's not going to be changing.
Note that this code won't work if the array is passed into a function, since arrays decay into pointers in that case so you need a separate argument for the size.
array size is constant. and it must be known at compile time. so you know it and you can use it in your program.

C realloc not changing array

So, to start off I've already looked at a few questions including this one and none of them seem to help.
I'm simply trying to write a function that extends the size of an array using realloc().
My code currently looks like this:
unsigned char *xtnd = malloc(4);
xtndc(&xtnd, 4);
// sizeof(*xtnd) should now be 8
void xtndc ( unsigned char ** bytesRef , uint8_t count ) {
*bytesRef = realloc(*bytesRef, (sizeof(**bytesRef)) + count);
}
But no matter what I do it seems that the size of xtnd is always 4. After running xtndc() on it it should now be 8 bytes long.
Any suggestions?
The type of **bytesRef is unsigned char, so sizeof(**bytesRef) is 1. sizeof doesn't keep track of dynamic allocations, it's a compile time tool that gives you the size of a type, in this case unsigned char.
You have to keep track of the array size manually to calculate the new required size.
Your program does in fact change the size of the memory block. It changes the size of your original memory block from 4 bytes to 5 bytes. It changes to 5 bytes because you are essentially doing sizeof(unsigned char) + 4 which 1 + 4 = 5. If you want to double the size instead, do count*sizeof(unsigned char) + count. There are two points to be noted here:
The sizeof function returns the size of the data type, not the size of the allocated bytes. There is no way to know the size of the dynamically allocated memory.
The function realloc (and malloc and calloc as well) is not always guaranteed to return the requested reallocation. It may or may not succeed all the time.
I fixed the problem with the following code.
typedef struct CArrPtr {
unsigned char* ptr;
size_t size;
} CArrPtr;
void xtndc ( CArrPtr *bytesRef, uint8_t count );
. . .
CArrPtr xtnd = { .ptr = malloc(4), .size = 4 };
xtndc( &xtnd, 4 );
// xtnd.size is now 8 bytes
. . .
void xtndc ( CArrPtr *bytesRef, uint8_t count ) {
unsigned char *nptr;
if((nptr = realloc(bytesRef->ptr, bytesRef->size + count)) != 0)
{
bytesRef->ptr = nptr;
bytesRef->size = bytesRef->size + count;
}
}
As I am somewhat new to C, what I learned from this is that malloc specifically creates a pointer to a memory block, but you have no direct access to information about the memory block. Instead, you must store the size of the array that you created with malloc somewhere as well.
Since in the past I'd been initializing arrays with unsigned char arr[size]; and then using sizeof on it, I was under the impression that sizeof returned the size of the array, which is of course wrong as it gives you the size of a type.
Glad I could learn something from this.
sizeof is used to calculate size of data type or array. Pointer and array are very similar, but they are different things. For int *ap, sizeof(ap) will return 4 on x86, sizeof(*ap) will return 4; for int a[10], sizeof(a) will return 40.
sizeof expression is processed at compile time, so it will be a constant written into the executable file before you run the program.
malloc and realloc don't maintain size.
If realloc succeeds, it will reallocate the requested size. So you don't need to check the size after realloc returns, but you should check the return value of realloc to ensure that realloc succeeds.

size of each element of a struct array in c

First, I have a struct here:
//Space to store the results for analysis map
struct Analysis analysis_space[32];
Each element of analysis_space array is for one file to store the results by some calculations;
So, my question is
If I want to get the size of each one of analysis_space,
It should be sizeof(analysis_space[0]) which returns the size of each element.
And sizeof(analysis_space) returns the whole array size?
Additional question:
Since analysis_space is an array, I suppose to initialize it before I store results into it?
Something like: analysis_space[0] = '\0' ?
... to get the size of each one of analysis_space, It should be sizeof(analysis_space[0]) which returns the size of each element.
sizeof(analysis_space[0]) returns the value of the char size of analysis_space[0]. The type returned is size_t and the matching printf() specifier is "%zu", "%zX" and others. When using the sizeof operator, code needs to use () with types. () are optional with objects.
printf("One element size %zu\n", sizeof analysis_space[0]);
And sizeof(analysis_space) returns the whole array size?
Yes,
printf("Array size %zu\n", sizeof analysis_space);
I suppose to initialize it before I store results into it? Something like: analysis_space[0] = '\0' ?
analysis_space[0] = '\0' is an assignment, not initialization. Further, struct Analysis expects a structure assignment/initialization, not scalar. Initialization is not required before writing
to it. #pm100
struct Analysis {
int a;
double b;
};
// Sample initialization
struct Analysis analysis_space[32] = {
{0, 0.0}, {1, 1.0} , {2, 2.0} }; // remainder zero initialized.
To compute the array element count:
// the type of the quotient is size_t
#define analysis_space_N (sizeof analysis_space / sizeof analysis_space[0])

Adding elements to front and back of char array of unknown size? [duplicate]

Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
See the following example
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt;
Serial.println(sizeof(testInt) / sizeof(int)); // returns 3
Serial.println(sizeof(point) / sizeof(int)); // returns 1
(This is a snipplet from Arduino Code - I'm sorry, I don't "speak" real C).
The easy answer is no, you cannot. You'll probably want to keep a variable in memory which stores the amount of items in the array.
And there's a not-so-easy answer. There's a way to determine the length of an array, but for that you would have to mark the end of the array with another element, such as -1. Then just loop through it and find this element. The position of this element is the length. However, this won't work with your current code.
Pick one of the above.
Also doing an Arduino project here...
Everybody on the internet seems to insist it's impossible to do this...
and yet the oldest trick in the book seems to work just fine with null terminated arrays...
example for char pointer:
int getSize(char* ch){
int tmp=0;
while (*ch) {
*ch++;
tmp++;
}return tmp;}
magic...
You can infer the length of an array if you have an array variable.
You cannot infer the length of an array if you have just a pointer to it.
You cannot and you should not attempt deduce array length using pointer arithmetic
if in C++ use vector class
You can if you point the the whole array and NOT point to the first element like:
int testInt[3];
int (*point)[3];
point = testInt;
printf( "number elements: %lu", (unsigned long)(sizeof*point/sizeof**point) );
printf( "whole array size: %lu", (unsigned long)(sizeof*point) );
Is there a way to get the length of an Array when I only know a pointer pointing to the Array?
Technically yes, there is a way when code has a true pointer to an array as the array size is in the type as with int (*array_pointer)[3].
This differs from OP's code as the pointer point is not a pointer to an array, but a pointer to an int.
The line point = testInt; converts the array testInt to the address of the first element of the array (which is an int *) and assigns that to point. Thus the array size info is lost.
int testInt[3];
testInt[0] = 0;
testInt[1] = 1;
testInt[2] = 1;
int* point;
point = testInt; // Get the address of testInt[0]
int (*array_pointer)[3] = &testInt; // Get the address of the array
printf("%zu\n", sizeof(testInt) / sizeof(int));
printf("%zu\n", sizeof(point) / sizeof(int));
printf("%zu\n", sizeof(*point) / sizeof(int));
printf("%zu\n", sizeof(*array_pointer) / sizeof(int));
printf("%p\n", (void *) testInt);
printf("%p\n", (void *) point);
printf("%p\n", (void *) array_pointer);
Sample output
3
2
1
3
0xffffcbc4
0xffffcbc4
0xffffcbc4
Pointers point and array_pointer both have values that point to the same location in memory, but the pointers differ in type.
With C99 or later that support variable length arrays, code could have been the below and achieved similar results without explicitly coding a 3 in the pointer definition.
int (*array_pointer_vla)[sizeof testInt/sizeof testInt[0]] = &testInt;
printf("%zu\n", sizeof(*array_pointer_vla) / sizeof(int));
Output
3
I see now see similarities to #user411313 answer. Perhaps the deeper explanation and VLA discussion will be useful.

Resources