import std.stdio;
void main() {
int[] a = [1,2,3,4,5,6,7,8,9,10];
write(a.sizeof);
}
In following code sizeof of static array is equals to 8 byte. I use x86 Windows 8, so pointer is equals to 4 byte.
Why I get 8 byte size of array?
Because int[] is a dynamic array, not a pointer. Arrays in D are not pointers. What they are is essentially
struct(T)
{
T* ptr;
size_t length;
}
So, if you want the underlying pointer, you need to use the array's ptr member, though that's usually only needed when interacting with C/C++ code (since dynamic arrays in C/C++ are just pointers). However, the length member is used all the time and helps make arrays in D far more powerful and pleasant to work with than arrays in C/C++ are. If you want to know more about arrays in D, then you should read this article. It goes into a fair bit of detail about them, and I would consider it a must-read for all D programmers.
Regardless, what sizeof is giving you is the size of ptr and length together, which would be 8 on 32-bit systems, and 16 on 64-bit systems.
A dynamic array (what you have) is behind the scenes actually a struct with a pointer and a size_t length both being 4 on your CPU.
This allows D to carry along the length of the array to avoid out of bounds reading and writing (if you have the check enabled) and a O(1) slice operation.
Related
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
sizeof array clarification
I have 2 arrays declared
GLfloat gCubeVertexData[216] = { list of numbers};
and an array declared:
GLfloat *resultArray = malloc(sizeof(GLfloat) * [arrayOfVerticies count]);
for(int i = 0; i < [arrayOfVerticies count]; i++)
{
resultArray[i] = [[arrayOfVerticies objectAtIndex:i] floatValue];
}
why is it when I do sizeof(gCubeVertexData) I get 864 ( a GLflot is 4 bits so divided by 4 and you get 216)
and when I do sizeof(resultArray) I get 4? event though if I were to print out resultArray[100] I get the correct number, and there is a lot more than 4 numbers stored?
Because gCubeVertexData is an array, and resultArray is a pointer. In the case of an array, the compiler knows how many bytes it is required to allocate for the array, so it explicitly knows a size (in the case of variable-length arrays in C99, it can also be computed easily at runtime, perhaps by messing with the stack pointer).
However, in the case of malloc(), the compiler has no knowledge about the size of the memory pointed by the pointer (that size can be obtained in a non-standard and platform-dependent way only anyways...), so it just returns the size of the variable itself, which is a pointer in this case, so you'll get back sizeof(GLfloat *) in the end.
Because with sizeof(resultArray) you are getting the size of the pointer to the first element.
The type of resultArray is simply GLfloat *, i.e. "pointer to GLfloat, and your machine uses 4 characters to store a pointer. The size information associated with the pointer is not visible to the sizeof operator.
Therefore, sizeof resultArray == sizeof (GLfloat *), which is what you're seeing.
Look at the declaration of gCubeVertexData and resultArray. The first is an array with 216 elements, the latter is just a pointer. C (and thus C++ and Objective-C) allow to use pointers to access arrays, but that does not mean they have the same type.
Out of pure curiosity, I started playing with array's in ways that I have never used before. I tried making a data structure array, and set it equal to another:
typedef struct _test {
float value;
} test;
Simple enough struct, so I tried this:
test struct1[10];
test struct2[20];
struct1 = struct2;
I didn't think this would work, and it didn't even compile. But, this interests me a lot. Is it possible to take an array of 10 and increase the size to 20, while copying the data?
Objective-C
I am actually doing this with Objective-C, so I'd like to hear from the Objective-C people as well. I want to see if it is possible to change the size of struct1 in this file.
#interface Object : NSObject {
test struct1;
}
Remember: This is only out of curiosity, so everything is open to discussion.
Something else that is not exactly pertinent to your question but is interesting nonetheless, is that although arrays cannot be assigned to, structs containing arrays can be assigned to:
struct test
{
float someArray[100];
};
struct test s1 = { /* initialise with some data*/ };
struct test s2 = { /* initialise with some other data */ };
s1 = s2; /* s1's array now contains contents of s2's array */
This also makes it possible to return fixed-length arrays of data from functions (since returning plain arrays is not allowed):
struct test FunctionThatGenerates100Floats(void)
{
struct test result;
for (int i = 0; i < 100; i++)
result.someArray[i] = randomfloat();
return result;
}
As others have said, arrays allocated like that are static, and can not be resized. You have to use pointers (allocating the array with malloc or calloc) to have a resizable array, and then you can use realloc. You must use free to get rid of it (else you'll leak memory). In C99, your array size can be calculated at runtime when its allocated (in C89, its size had to be calculated at compile time), but can't be changed after allocation. In C++, you should use std::vector. I suspect Objective-C has something like C++'s vector.
But if you want to copy data between one array and another in C, use memcpy:
/* void *memcpy(void *dest, const void *src, size_t n)
note that the arrays must not overlap; use memmove if they do */
memcpy(&struct1, &struct2, sizeof(struct1));
That'll only copy the first ten elements, of course, since struct1 is only ten elements long. You could copy the last ten (for example) by changing &struct2 to struct2+10 or &(struct2[10]). In C, of course, not running off the end of the array is your responsibility: memcpy does not check.
You can also you the obvious for loop, but memcpy will often be faster (and should never be slower). This is because the compiler can take advantage of every trick it knows (e.g., it may know how to copy your data 16 bytes at a time, even if each element is only 1 byte wide)
You can't do this in C with static arrays, but you can do it with dynamically allocated arrays. E.g.,
float *struct1, *struct2, *struct3;
if(!(struct1 = malloc(10 * sizeof(float))) {
// there was an error, handle it here
}
if(!(struct2 = realloc(struct1, 20 * sizeof(float))) {
// there was an error, handle it here
// struct1 will still be valid
}
if(!(struct3 = reallocf(struct2, 40 * sizeof(float))) {
// there was an error, handle it here
// struct2 has been free'd
}
In C, I believe that's a good place to use the realloc function. However, it will only work with dynamically allocated arrays. There's no way to change the memory allocated to struct1 by the declaration test struct1[10];.
In C arrays are constants, you can't change their value (that is, their address) at all, and you can't resize them.
Clearly if you declare your array with a fixed size, test struct1[10] then it cannot be resized. What you need to do is to declare it as a pointer:
test *struct1;
Then you must use malloc to allocate the array and can use realloc to resize it whilst preserving the contents of the original array.
struct1 = malloc(10*sizeof(*struct1));
//initialize struct1 ...
test *struct2 = realloc(struct1, 20*sizeof(*struct1));
If you're using Objective C, you know you can just use NSMutableArray, which automatically does the realloc trick to reallocate itself to store however many objects you put in it, up the limit of your memory.
But you're trying to do this with struct? What would that even mean? Suppose you increase the amount of memory available to struct1 in Object. It's still a struct with one member, and doesn't do anything more.
Is the idea to make Object be able to contain an expanded struct?
typedef struct _test2 {
float value;
NSObject *reference;
} test2;
But then you still can't access reference normally, because it's not a known part of Object.
Object *object2;
...
NSLog(#"%#", object2.struct1.reference); // does not compile
If you knew you had one of your modified objects, you could do
Object *object2;
...
NSLog(#"%#", ((test2)(object2.struct1)).reference);
And also you could still presumably pass object2 to anything that expects an Object. It only has any chance of working if struct1 is the last member of Object, and don't mess with subclassing Object either.
Some variety of realloc trick might then work, but I don't think realloc in particular, because that's intended to be used on objects that are allocated with malloc, and the details of what C function is used to allocate objects in not exposed in Objective C, so you shouldn't assume it's malloc. If you override alloc then you might be able to make sure malloc is used.
Also you have to watch out for the fact that it's common in Objective C for more than one pointer to an object to exist. realloc might move an object, which won't be semantically correct unless you correct all the pointers.
I'm having a issue getting the size of a struct pointer after allocating the memory using malloc or realloc. I've worked around this by keeping track of the memory in a separate counter, but I would like to know if this is a bug or if there is a way to properly query the size of a struct pointer.
Sample code demonstrates that no matter how much memory I allocate to the struct pointer it always returns 4 when querying using the sizeof() method.
typedef struct {
int modelID;
int bufferPosition;
int bufferSize;
} Model;
Model *models = malloc(10000 * sizeof(Model));
NSLog(#"sizeof(models) = %lu", sizeof(models)); //this prints: sizeof(models) = 4
4 is the correct answer, because "models" is a pointer, and pointers are 4 bytes. You will not be able to find the length of an array this way. Any reason you're not using NSArray?
If I understand you correctly you want to get at the size of the allocated buffer.
sizeof if the wrong way to go since it is evaluated at compile time. The size of the buffer is a runtime concept.
You would need a way to query you C library to return the allocation size for the pointer to the buffer.
Some systems have a way to get that kind of information, for instance malloc_size on Mac OS.
4 is the correct answer.
Pointers point to a memory location which could contain anything. When you are querying the size of a pointer, it gives the size of the memory location which holds the pointer, which in your case is 4.
For example
int *a = pointing to some large number;
int *b = pointing to a single digit number;
In the above case, both a and b have the same size irrespective of where they are pointing to.
For more information, have a look at this post size of a pointer
sizeof(myvar) will return size of pointer. in 32bit environment it equals to 4(bytes).
why don't you use sizeof (Model) instead?
I know this has been asked previously but one thing that these other questions didn't touch upon is why
Allow me to explain. I just ran through a tutorial that outputted integers and pointers to show you how to do it.
int anInteger = 50;
int *anIntPointer = &anInteger;
So, to set up a pointer I assign a variable value as normal, and then I assign that variable to a pointer. This I understand, but as I've already said, this is the how not the why.
If I wanted to return the value 50 I could just NSLog anInteger so why would I need a pointer. Why would I need to NSLog *anIntPointer if I could just NSLog anInteger which does exactly the same thing?
Okay, I know this is very trivial and there are probably perfect circumstances to use a pointer, but so far no tutorial that I've read or watched will give me a perfect circumstance. They all deal with the how
Please help me find the why.
Pointers have many uses. One obvious one is that you want to call a function and have it modify one of your variables:
void f(int *i) { *i = 42; }
int g() { int i; f(&i); return i; }
Another is to return a large struct without a huge amount of copying:
struct big_struct *f() {
big_struct *bs = malloc(sizeof(big_struct));
// Populate the big_struct;
return bs;
}
Yet another is to manage arrays who's size you don't know at compile:
struct item *fetch_items(int n) {
item *i = malloc(n*sizeof(item));
load_items(i, n);
return i;
}
Still another is recursive data types, such as linked lists:
struct node {
int value;
struct node *next;
};
And this is just a sampling. Pointers are like nails to a carpenter. They are a key tool in almost any non-trivial programming problem.
The main reasons why we use pointers (in C and C-derived languages) are:
To mimic pass-by-reference semantics
To track dynamically-allocated memory
To create self-referential and dynamic data structures
Because sometimes the language forces you to
To mimic pass-by-reference semantics: In C, all function arguments are passed by value. The formal parameters and the actual parameters are different objects in memory, so writing to the formal parameter has no effect on the actual parameter. For example, given the code
void swap(int a, int b)
{
int tmp = a; a = b; b = tmp;
}
int main(void)
{
int x = 2, y = 3;
printf("before swap: x = %d, y = %d\n", x, y);
swap(x, y);
printf("after swap: x = %d, y = %d\n", x, y);
return 0;
}
a and x are physically distinct objects; writing to a does not affect x or vice versa. Thus, the before and after output in the program above will be the same. In order for swap to modify the contents of x and y, we must pass pointers to those objects and dereference the pointers in the function:
void swap(int *a, int *b)
{
int tmp = *a; *a = *b; *b = tmp;
}
int main(void)
{
int x = 2, y = 3;
printf("before swap: x = %d, y = %d\n", x, y);
swap(&x, &y);
printf("after swap: x = %d, y = %d\n", x, y);
return 0;
}
a and x are still distinct objects in memory, but the expression *a refers to the same memory as the expression x; thus, writing to *a updates the contents of x and vice versa. Now the swap function will exchange the contents of x and y.
Note that C++ introduced the concept of a reference, which sort of acts like a pointer but doesn't require an explicit dereference:
void swap(int &a, int &b)
{
int tmp = a; a = b; b = tmp;
}
int main(void)
{
int x = 2, y = 3;
std::cout << "before swap: x = " << x << ", y = " << y << std::endl;
swap(x, y);
std::cout << "after swap: x = " << x << ", y = " << y << std::endl;
return 0;
}
In this case, the expressions a and x do refer to the same memory location; writing to one does affect the other. This is a C++-ism, though.
I'm not familiar enough with Obj-C to know if they have a similar mechanism.
To track dynamically-allocated memory: The C memory allocation functions malloc, calloc, and realloc, along with the C++ operator new all return pointers to dynamically allocated memory. If you have to allocate memory on the fly, you have to use pointers to refer to it. Again, I'm not familiar enough with Obj-C to know if they use a different memory allocation mechanism.
To create self-referential and dynamic data structures: Aggregate types such as struct or union types cannot contain an instance of themselves; for example, you can't do something like
struct node
{
int value;
struct node next;
};
to create a linked list node. struct node is not a complete type until the closing }, and you cannot declare objects of an incomplete type. However, a struct can contain a pointer to an instance of itself:
struct node
{
int value;
struct node *next;
};
You can declare a pointer to an incomplete type, so this works. Each node in the list can refer to the node immediately following it. And since you're dealing with pointers, you can add or delete nodes from the list reasonably easily; you just have to update the pointer values, instead of physically moving data around.
I can pretty much guarantee that any container type in Obj-C uses pointer manipulation under the hood.
Because sometimes the language forces you to: In C and C++, an expression of array type will implicitly be converted to a pointer type in most circumstances. Array subscripting is done in terms of pointer arithmetic; the expression a[i] is evaluated as though it were written *(a + i). IOW, you find the address of the i'th element after a and dereference it.
Pointers are not specific to Objective-C, in fact they are used in C and [usually not so much C++]. Basically, it is how you pass objects by reference.
void thisFunctionModifiesItsArgs(int *x, int *y, int *z)
{
*x = 4;
*y = *z;
*z = 100;
}
int main()
{
int a = 0;
int b = 1;
int c = 2;
thisFunctionModifiesItsArgs(&a, &b, &c);
// now, a = 4, b = 2, and c = 100
}
the most obvious reasons:
1) you want the object pointed to to live beyond the scope of its use, so you create an allocation. accessing the int's address beyond its scope is asking for trouble -- the address is likely used by something else at that point. if you create a unique memory location for it, that problem is solved (or... maybe displaced).
2) you want to pass it by reference/pointer/address. this is useful to mutate an object, or as an optimization when the type is large.
3) support for polymorphism and/or opaque types
4) pointer to implementation (abstraction, dependency reduction)
and on... (i wouldn't expect you to understand all those cases at this stage)
so, the example you show is so trivial that it does not represent (any of) those cases -- it only attempts to introduce the syntax.
there are many cases, and they are used regularly in real world C, C++, ObjC, etc. programs for many different reasons.
A simple answer: because there are variables that are more complex than simple integers. The tutorial is giving you a very simple case to explain the concept, but the simple case they describe would almost never be used.
Justin's answer is spot on for what you're asking. If you need a good tutorial then I recommend chapter 5 of "Beginning Mac Programming" which explains how the memory addressing works and how this is essential for working with pointers, and the reasons why.
Computer Science 001
Computers (the computer chip) can only do three things, but they can do them million or even billions of times per second.
They can store information (a number) into memory.
They can do arthimetic on those numbers.
They can make simple decsions based on the arthimetic, like if a = b then go to address X.
Thats it.
A very simple analogy I use to explain pointers to beginners in assembler programming is to think of memory like a row of mailboxes. The first mailbox has address 0 and the next is one plus and so forth.
When a computer starts up, it is told to go to mailbox 0 and get the content.
The content can be information or a command, mailbox 0 always holds a command. The command might be Go to mailbox 1 and get its content.
The content of a mailbox can only hold so much information, just like a real mailbox can only hold so much information. If the postman need to deliver a package for example, he will put a notice in the mailbox to go to the post office to pick it up. The notice is like a pointer. The pointer does not hold the information, the real information is located where the pointer says it is located, in this case the post office.
You could even get to the post office to find out there is nothing but another pointer to another location. We would call that a "handle" or a pointer to a pointer.
If you want to copy a byte sequence from one place to other place, (naturally) you have to know the source and destination addresses. To express it in the language's abstraction level, you can use pointers, which represents the memory locations.
Beside notes has been written already, in lower levels, pointers are very often used. A very simple example: Writing to the 80x25 screen. For example the base address of the screen is 0xb8000, where the first character of the screen is stored. You can use pointers, with wich you can write a character to the appropriate position in the screen. e.g. : unsigned short* sc = (unsigned short*)0xb8000; *sc = 'A' | (attr) << 8; . And so on...
N.B.: Pointers embodies indirection, and it is possible, you can have "multiple" pointers: ** (imagine the C main functions signature, and the char** in it!). Or e.g. you want to create a list structure with malloc in a separate function. Then you can pass a struct list** or what have you parameter and in the function you can assign a value (a memory address) to the list, which means you have created the list in the memory.
This is a somewhat of a follow up to this posting but with a different question so I felt I should ask in a separate thread.
I am at the point where I have four consecutive bytes in memory that I have read in from a file. I'd like to store these as a bit array (the actual int value of them does not matter until later). When I print out what is in my int, I notice that it seems to be stored in reverse order (little endian).
Does anyone have a good method for reversing the order of the bytes. Then once reversed, picking out consecutive bits spanning two bytes and converting back to an int?
unsigned char data[] = { 0x00, 0x02, 0x45, 0x28 };
NSInteger intData = *((NSInteger *)data);
NSLog(#"data:%08x", intData); // data:28450200
Cocoa (or to be exact the Foundation framework) has functions to swap the endianness of bytes: NSSwapInt, NSSwapShort, NSSwapLong, and NSSwapLongLong. These swap around the bytes no matter what - they make big-endian integers from small-endian integers and vice versa.
If you know which format you have there are other functions that swap it to the native endianness: NSSwapLittleIntToHost and NSSwapBigIntToHost. There are also the reverse functions which swap from the native format to little or big endian format: NSSwapHostIntToLittle and NSSwapHostIntToBig. Those are available for the other integer types and floating point types as well. What they do is they call the primitive swap functions on the values if necessary. So NSSwapLittleIntToHost doesn’t do anything while NSSwapBigIntToHost returns the result of NSSwapInt on a little endian machine.
Note that these take parameters of the compilers integer types and not the NSInteger type. So depending on wether you’re generating 32bit or 64bit code you have to use different functions if you are using NSInteger.
You also should not cast your byte array to an integer pointer and dereference that. It would be better to assemble the integer using bit shift operations. Your code will only work if NSInteger is 32 bit wide. If it is 64 bit then your number will be garbage or your program might even crash. But even if you are using an integer type that is always 32 bit wide (int32_t from the C99 <stdint.h> header for example) this might not work as expected.