What is difference between sizeof(int)*10 and sizeof(40) - c

A
int *numptr = malloc(sizeof(int)*10);
B
int *numptr = malloc(sizeof(40));
it's on the 32bit
i can't understand what is difference.
there is no information in the book i have.
is A and B 100% same thing?

You're allocating a different amount of space in each case.
For case A, you have first have sizeof(int). Presumably, an int is 4 bytes on your system, so this expression evaluates to 4. So malloc(sizeof(int)*10) is allocating space for 4 * 10 = 40 bytes.
For case B, you have sizeof(40). This is giving you the size of the constant 40 whose type is int, so sizeof(40) is 4. This then means that malloc(sizeof(40)) is allocating space for 4 bytes.

An int isn’t guaranteed to be 4 bytes wide. It’s only guaranteed to represent values in the range [-32767..32767], so it’s only guaranteed to be 16 bits (2 bytes) wide.
Yes, it’s 4 bytes on most modern desktop platforms, but it doesn’t have to be.
Besides, 10 * sizeof (int) more clearly conveys that you’re allocating space for 10 int objects.

40 is an integer, so sizeof(40) should return the same thing as sizeof(int). Thus, sizeof(int) * 10 is the size of 10 integers, but sizeof(40) is the size of a single integer.

Related

Explanation for cryptic double pointer assignment

I'm reading the c code:
void **alignedData = (void **)(((size_t)temp + aligned - 1)&-aligned);
I do not known the means, especially the &- part.
Can anyone explain it?
Thanks!
When using this, aligned should be an unsigned type (or the C implementation should be using two’s complement) and have a value that is a power of two. Then this code calculates an amount of memory to be allocated:
(size_t) temp converts temp to the unsigned type size_t, which is suitable for working with sizes. This will be a number of bytes to be allocated.
(size_t) temp + aligned - 1 adds enough bytes to guarantee a multiple of aligned falls somewhere between the numbers temp and temp + aligned - 1, inclusive. For example, if temp is 37 and aligned is 8, then between 37 and 44 (37+8−1), there is a multiple of 8 (40).
-aligned makes a bit mask with 1 in each bit position that is a multiple of aligned and 0 in the lower bits. For example, if aligned is 8, then the bits that represent -aligned are 111…111000, because the 000 bits at the end represent values of 1, 2, and 4, while the other bits represent values of 8, 16, 32, and so on.
The & (bitwise AND) of (size_t) temp + aligned - 1 with -aligned then clears the low bits, leaving only bits that are multiples of aligned. Thus, it produces the multiple of aligned that is in the interval. For example, with the values of 37 and 8 mentioned before, ((size_t) temp + aligned - 1) & -aligned produces 40.
Thus, this expression produces the value of temp rounded up to the next multiple of aligned. It says “Calculate the number of bytes we need to allocate that is at least temp bytes and is a multiple of aligned.”
After this, the code converts this number to the type void ** and uses it to initialize void **alignedData. That is bad C code. There is generally no good reason for it. A number of bytes like this should not be used as any kind of pointer. The code may be attempting to “smuggle” this value through a data type it is compelled to use by some other software, but there is likely a better way to do it, such as by allocating memory to hold the value and supplying a pointer to that memory instead of trying to convert the value directly. Finding a better solution requires knowing more context of the code.

Why do these two instructions vary in size?

Here are two instructions:
int p = 0;
int size_1 = (int*)(&p+1)-(int*)&p;
int size_2 = (char*)(&p+1)-(char*)&p;
I found that size_1 is 1 and size_2 is 4. I was wondering why they vary this way
This is basic pointer arithmetic. Oversimplifying a little bit, subtracting two int* produces the number of ints that fit between the two pointers (one), while subtracting two char* produces the number of chars that fit between the pointers (on your system, it happens to be four, because an int is four-byte wide).
The root cause is that an int is 4 bytes on your system, while a char is 1 byte. The code (&p+1) will return a pointer to the memory address 4 bytes (the sizeof(int)) after p. Then when you assign to size_1 you are asking for your answer in terms on int sizes, thus you get 1. For size_2, you are asking the difference between the address in char sizes, which gives 4.

Is it possible to allocate huge array in c?

Hi all i want to use the following :
int i;
unsigned short int **graph;
graph = (unsigned short int**)malloc (sizeof(unsigned short int *) * 65535);
if (graph == NULL ) fprintf(stderr, "out of memory\n");
for (i = 0; i < 65535; i++){
graph[i] = (unsigned short int*)malloc (sizeof(unsigned short int) *65535);
if (graph[i] == NULL ) fprintf(stderr, "out of memory\n");
}
the size 65535 is constant
i need to build this size of graph
is it possible?
will it help if i will split it ?
Thanks!
There are four different issues to consider here:
1) The size of the argument of malloc. It is of type size_t, which is an unsigned integer type that is at least 16 bits and large enough to hold the size of any object or the index of any array. In practice it tends to be the platform's native word size, i.e., 32 bits for 32-bit platforms, and 64 bits for 64-bit platforms, so you are likely to need at least a 32-bit platform, but this almost certainly the case unless developing for embedded (or very retro) systems.
One should also remember that the argument may overflow and you can silently end up successfully allocating less memory than you thought you'd get (e.g., you may effectively call malloc(65534) when you thought you were calling malloc(2 * 65535)). But in this case it is very unlikely to be an issue for any platform capable of allocating this amount of memory.
2) Whether the malloc calls succeed. You are already checking for this, so simply running the code will answer this. You are allocating over 8 GB† of memory here, so it is likely that it will fail unless compiled for 64 bits (since the maximum addressable memory for 32 bits is 4 GB).
3) Whether you can actually use all the memory you've allocated. Some operating systems will overcommit memory and allow you to allocate much more memory than is actually available. You may run into trouble if you actually try to use all the memory you've allocated. This depends on the OS and the amount of memory actually available, possibly including swap.
4) Whether it is practical for the machine the program is run on to actually have that much data in memory. Even if the malloc calls succeed and the OS lets you use the memory allocated, it is still over 8 GB, which means that a typical machine should probably have at least 12 GB of RAM installed to accommodate this, the OS, and other programs. Otherwise it may swap like crazy, despite theoretically working.
You have revealed in comments that you are running a 64-bit machine with 4 GB of RAM installed, so if you compile for 64 bits the first two points are not an issue, but point 3 may be, and point 4 almost certainly will be. So, either install more RAM or figure out a different way to handle the data (e.g., if you are storing a graph as per the variable name, perhaps it is often sparse enough that you don't need to allocate for the worst case).
† “over 8 GB” comes from 65535 * sizeof(short *) + 65535 * 65535 * sizeof(short), where sizeof(short) is very likely to be 2, and sizeof(short *) (the pointer size) either 4 or 8. There is also some extra overhead for malloc's bookkeeping, but still it rounds to “over 8 GB”.
Some stylistic observations:
It would be better style to use one of the types from stdint.h if you want specifically 16 bits, e.g., uint16_t or uint_least16_t
You should not cast the return value of malloc in C (unlike in C++)
You can replace sizeof(unsigned short int *) with sizeof(*graph) and sizeof(unsigned short int) with sizeof(**graph) to avoid repetition (and allow you to change the type of graph without changing the malloc calls)
You don't need the int in unsigned short int
Max allowed size will be range of integer. So if you are using 16 bit OS max size is 65535, if you are using 32 bit OS size will be 4,294,967,295.
The maximum size of non-arrayed data is SIZE_MAX. SIZE_MAX is at least 65535.
SIZE_MAX is type size_t which is often the same type as unsigned but may be different.
The single largest allocation available using malloc() is SIZE_MAX.
void *malloc(size_t size);
sizeof(unsigned short int *) * 65535 may fail due to integer math overflow.
To allocate an array larger than SIZE_MAX (but each element is still <= SIZE_MAX), use calloc().
void *calloc(size_t nmemb, size_t size);
unsigned short int **graph = calloc(65535u, sizeof *graph);

Some pointer clarification [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C question with pointers
I need some help with pointers, specifically the following example:
#include <stdio.h>
int main()
{
int *i, *j;
i = (int *) 60;
j = (int *) 40;
printf("%d", i - j);
return 0;
}
This code generates 10 as output. I just need to know what exactly i - j does here.
i and j point to memory locations 60 and 40, respectively.
What you're doing here is pointer subtraction. If i and j were byte pointers (char *), i-j would be 20, as one might expect.
However, with other pointers, it returns the number of elements between the two pointers. On most systems, (int *)60 - (int *)40 would be 5, as there is room for five 4-byte integers in those twenty bytes. Apparently, your platform has 16 bit integers.
The program is probably supposed to print the pointer difference between 60 and 40, cast to pointer to int. The pointer difference is the number of ints that would fit in the array from address 40 to address 60 (exclusive).
That said, the program violates the C standard. Pointer arithmetic is undefined except with pointers pointing into the same (static, automatic or malloc'd) array, and you cannot reliably print a pointer difference with %d (use %td instead).
This is pointer arithmetic, the code i - j subtracts two pointers to int. Such arithmetic is aware of the data sizes involved, and so in this case will return the number of ints between the two addresses.
A result of 10 indicates that you're running this on a system with 2-byte integers: 20 memory addresses between i and j, and your code prints 10, so there are 10 2-byte ints between the two addresses.
But on another system, with 4-byte integers, this would print 5: 20 memory addresses between i and j, so there are 5 4-byte ints between the two addresses.
printf("%d",i-j); return 0;
both i and j are pointer to an integer.So they follow pointer arithematics.
As per pointer mathematics pointer to an integer always shift sizeof(int).I
think you use gcc compiler where sizeof int is 4.So 60-40=20 but as unit is 4 so out put is
5.
but if you use turbo c where sizeof int is 2.then out put is 10.
NOTE
if pointers are included in some expression evaluation then they follow pointer arithematics.
i an j are the pointer to int variable, that means which is going to store virtual address of an int variable.
If we do any pointer arithmatic on this variable it will preform based on size of the type of variable which is pointing. For example i++ will increase the value from 60 to 64 if size of int is 4 bytes.
So you are getting 10 for i - j, that means size of int is 2 in your environment. Always i - j will give you how much element(of type int) that can accomodate in that range.
So between 60 and 40, we can store 10 elements of type int if size of int is 2 bytes.
First, two integer pointers are declared which are called i and j. Note that their values are memory addresses to where pointers are stored, not integers themselves (the concept of a pointer).
Next, the pointers i & j are changed to 60 and 40, respectively. Now this represents a spot in memory and not the integers sixty and forty because i and j was never dereferenced.
Then it prints the memory address of i-j which will subtract that two memory addresses.

Memory alignment and size of structure

Let's say that I define the following structure:
struct MyData {
int a;
char b;
int c;
byte d;
byte e;
}
I vaguely remember reading that the size of that structure not only depends on the data type but also memory alignment. On a 32bits CPU, the MyData structure would be 4 bytes + 1 byte + 4 bytes + 1 byte + 1 byte = 11 bytes. Here's my question, is memory alignement increases the size of the structure: 4 bytes + 1 byte (+3 bytes padding) + 4 bytes + 1 byte (+3 bytes padding) + 1 byte (+3 bytes padding) = 20 bytes.
Is this wrong? Am I missing something? Is this something language specific? Can I pack the structure? If so, what would be the advantages and disadvantages?
Thanks!
The compiler can pad the structure as it sees fit. Typically, the two last bytes would not be separated by padding, so the size would become 4 (int) + 1 (char) + 3 (padding) + 4 (int) + 1 (byte) + 1 (byte) + 2 (padding) = 16.
Many compilers allow packing the struct per a pragma. The advantage of that is less memory usage, the disadvantage slower reads for the non-aligned int members.
You are not wrong in stating that memory alignment can increase the size of the structure; however, any guesses as to how the memory will be aligned are not valid for all platforms. This is strictly platform specific.
Basically, most platforms tend to align on ${WORDSIZE}, or if the data type is smaller than ${WORDSIZE}, then it aligns on the next available fraction of ${WORDSIZE}
For example, if you have a 32 bit word, and you are storing 16 bit shorts, they might align on bits zero and sixteen within a word. But that's not a guarantee, as it is truly platform specific.
To tweak your structs for smaller waste due to padding, order the elements by data type, with the larger data types first. This tends to allow multiple bytes to be packed into the same word (if possible) and the larger than word items will nicely terminate on word boundaries as they tend to be clean multiples of a word (quadword, doubleword, ...)
There is unspecified padding between and after struct members. There is no padding before the first struct member, that is:
struct MyData bla;
int val = (char *) &bla == (char *) &bla.a; // val is 1
A pointer to the structure (suitably converted) points to the first structure member.
The size of the structure object takes into account the padding and is equal to the sum of the size of the members + the sum of the size of the unspecified paddings.
Yes, compilers will naturally align types on boundaries that match their size. You can force structure packing using compiler pragmas such as
#pragma pack(1)
You can also avoid some padding by reordering your declarations to put your ints at the beginning and single bytes after that.
You can easily test this by printing sizeof(struct MyData)

Resources