The size of data of an address - c

The address that pointed by a pointer in c language contains how much data (byte , 2 byte ) , or is it dependent on the data type that point to ?

I'm not entirely sure what you mean by "The address that pointed by a pointer". I'll assume you're referring to the object it points to, not to the size of the pointer itself.
The answer to your question can depend on just what you mean by "address".
A C pointer value is not just a raw memory address (though it's usually implemented that way). A pointer value refers to an object of a specific type, and that type specifies among other things, the size of the pointed-to object. And the C standard fairly consistently uses the word "address" to refer to a (non-null) C pointer value.
On the other hand, the word "address" is commonly used to refer to a raw memory address, which can be thought of as pointing to a single byte. But on the other hand, even on the machine code level, what size of data an address refers to can depend on what you do with it. (I've even worked on systems where a machine address can only point to a 64-bit word; byte operations were done entirely in software.)
A pointer of type int* points to an int object. The size of that object is, by definition, sizeof (int) bytes (commonly 4 bytes, but it could be 8, or 2, or even 1 if a byte is at least 16 bits). Similarly, a pointer of type struct foo* points to a struct foo object, which could be of just about any arbitrary size.
An int* pointer doesn't just point to the first byte of an int object, it points to the entire int object. (But if you convert an int* pointer to char*, the result will point to the "first" byte.)
And as a special case, a pointer of type void* points to some location in memory, but does not specify the size of the object it points to. You can't dereference it until you convert it to some other pointer type.
Recommended reading: Section 4 of the comp.lang.c FAQ.

This is quite a philosophic question, let me give you three completely incompatibel answers:
The pointer itself obviously points to exactly 1 byte
depending on the type of the pointer, the pointer points to the first byte of a chunk of data the size of which is defined by the pointer type
the pointer points to the first byte of some data, the usable length of which is neither deterministic nor determinable from inside the program
While I consider all three answers to be technically correct, the second one is what you would use while programming in C.
Edit
For the details if what an "address" can, may or should be, please look at #KeithThompson's input in the comments below!

Related

Does storing a pointer take more memory than the byte that it's pointing to?

My questions are how where are the pointer values stored and do they take up more space in memory than the things they point to. For example, if I have a 64 bit pointer which i use to point to a byte of information in memory; where is the value of the pointer stored and does it take up more space than the data itself?
An example of my question written in C
char data = 10;
char* charPointer = &data;
doesn't charPointer take up more space than the data since the pointer is 64 bit and the data is 8 bit?
PS: I'm currently trying to learn the basics of C.
where is the value of the pointer stored
The pointer's value is stored where you declared it to be stored; e.g. if you declared the pointer as a local variable, then it will be stored on the stack; OTOH if you allocated the pointer on the heap (or, more commonly, you included the pointer as a member-variable of an object that you allocated on the heap) then the pointer will be in the heap.
and does it take up more space than the data itself?
In this case, it does.
You can actually check for yourself how much space a value takes up:
printf("data takes up %zu bytes\n", sizeof(data));
printf("charPointer takes up %zu bytes\n", sizeof(charPointer));
If you are on a 64-bit machine, you should find that a pointer takes up 8 bytes, as you would expect.
The char that the pointer points to takes up one byte, but in many cases there will also be some padding bytes inserted to keep the alignment of the next item on the stack optimal for the CPU to access efficiently.
A pointer to a char takes more space than a char in practically every C implementation. (The C standard permits them to be the same size, but such implementations are at best rare and are more likely archaic or nonexistent.)
Nonetheless:
One may need a pointer to point to one of a selection of objects or to manage objects or to connect them in various ways.
A pointer may point to objects much larger than a char.
A pointer may point to the first of many elements in an array, so one pointer can provide access to many objects.

c fixed memory pool implementation

I'm trying to implement a fixed memory pool (first-fit free list)
my struct is:
struct mempool {
void* data;
int offset;
};
data is divided into 8byte blocks, 4 bytes pointing to next offset and 4 bytes data. offset points to the first free block. I'm trying to understand why accessing the first block is done by:
int* address = (int*)((int)&pool->data + pool->offset);
especially the (int)&pool->data part. Isn't pool->data already a pointer? why do I need its address to perform arithmetic and shift to the offset?
I'm trying to understand why accessing the first block is done by:
int* address = (int*)((int)&pool->data + pool->offset);
especially the (int)&pool->data part. Isn't pool->data already a
pointer?
Yes, pool->data is a pointer. And one can obtain the address of a pointer, so there's nothing inherently wrong with that. The result in this case has type void **.
Moreover, given that data is the first member of struct mempool, &pool would point to the same address. Although the latter has a different type (struct mempool *), that's probably mooted by the fact that the code performs a conversion to type int.
why do I need its address to perform arithmetic and shift to
the offset?
The effect is to compute an address relative to the location of the data pointer itself, rather than relative to its target. Furthermore, the cast to type int suggests that the offset is measured in bytes. That aspect of it is a bit unsafe, however, because it is not guaranteed that type int is large enough to support round-trip conversion from pointer to int to pointer.
This all seems consistent with your characterization of the pool having metadata adjacent to the data, but it remains unclear what purpose the data pointers serve.
Overall, although I'm not convinced of the correctness or efficacy of the minimal code presented. If it in fact serves the purpose for which it is intended, relative to the structure definition presented, then this variation should do so better and more clearly:
int* address = (int*)((char *)&pool + pool->offset);
That avoids the question of an integer type that can represent pointers (although there is one in the form of intptr_t). The cast to char * accounts for the fact that pointer arithmetic is performed in units the size of the pointed-to type, and the offset seems to be expressed in one-byte units.
You code does not seem correct. You are adding pool->offset to the address of pool->data field rather that to the address stored in pool->data field. I would suggest fixing like this:
int* address = (int *)pool->data + pool->offset;
in case your offset is in 4-byte chunks, or like this:
int* address = (int *)((char *)pool->data + pool->offset);
in case your offset is in bytes.
pool->data + pool->offset wouldn't be possible because you can't do pointer arithmetic on void pointers - that isn't valid C. Pointer arithmetic also assumes that the underlying type of this all is an array.
&pool->data gives the address of the pointer itself, which happens to be the address of the struct. The type void**. You can't do arithmetic on that either.
Therefore the naive, bad solution here is to cast the pointer to an int and then do simple addition. That doesn't work either, because int is not guaranteed to be able to hold the contents of a pointer. uintptr_t should have been used instead of int.
And finally, accessing that chunk of memory through int* then de-referencing it is only possible if what's stored there is already regarded as type int by the compiler. If not, it invokes undefined behavior, What is the strict aliasing rule?.
Summary: this is quite questionable code and there's many better ways to implement it.

Dereferenced vs non Dereferenced pointers ( and the explanation behind them ) [duplicate]

This question already has answers here:
Why Use Pointers in C?
(4 answers)
Closed 5 years ago.
Why is it we have to dereference a pointer ( that has already been linked to another variable ) every time we want to work on the variable its linked to? If there's a pointer that's linked to a variable ( an int for example ) isn't dereferencing it on-top of everything else a bit redundant? Do standard ( non-dereferenced ) pointers serve their own separate purposes? What can we do with a pointer that hasn't been dereferenced?
example : pPrice vs *pPrice
I'm learning my first programming language C and I've been wondering this for some time.
When working with people who haven't worked with pointers before, I like to point out that a pointer isn't special compared to other primitive types; it's simply an integer, just like ints or chars. What's special about it is how we interpret its value - specifically, we interpret its value as the location (address) of another value. This is a little bit similar to how even though chars are really just integers, we interpret them to be characters based the ASCII encoding. Simply because we interpret a pointer's value to be an address, we can perform operations such as reading or writing the memory at the address it's specifying.
Like you said, we can still access the pointed to memory as usual, but now we have some additional benefits.
For example, we can change the pointer's value, thereby pointing it to a different place in memory. This might be useful if we want to write a generic function that modifies a given object, but you want to dynamically decide which object to pass to it.
Also, the pointer itself is a constant, defined size (usually 32 or 64 bits), yet it could point to an object of any arbitrary size (e.g. a vector, string, or a user defined type). This makes it possible for us to pass around or store a handle to the object without passing/storing the entire object, which might be expensive.
I'm sure there are a million more use cases that I'm leaving out, but these are a couple to get you started.
tl;dr: An integer variable is distinct from a reference to an integer variable.
In C, the idea of a "variable" is very specific. In reality, it is the area in memory which holds the value of a variable. The symbol is a convenient symbol name by which the C code can refer to the value, to the content of the memory area. A "reference" is the address of the memory location. Since C is strongly typed, each symbol indicates how to interpret the memory to which it is associated. (Whew!)
So,
int i;
i refers to a memory location which holds an integer.
i=5;
fills that memory location with the binary representation for 5.
int *p;
means p is associated with a memory location which contains a pointer (aka address) to an integer location. So we can write,
p = &i;
where &i is the explicit address of the memory location of the integer value. So, p and i refer to quite different kinds of things. Since p is the address of an integer, we can dereference it (i.e., follow the address) to get to the actual integer value at the address location (the one assocated with i).
*p = 6;
i = 6;
Both assignment statements are functionally equivalent (they both set the same memory location to integer 6) since both i and the dereferenced p, *p, refer to the same memory location. Noteably, i is inextricably tied to the memory location, while *p can point elsewhere (though, p is inextricably to the integer-pointer memory location that refers to integers).
pPrice may be modified to point to a different price.
int a = 1,
b = 2,
*p = &a;
printf("%d\n", *p);
p = &b;
printf("%d\n", *p);

Does pointer only store memory address?

I am learning C programming language these days. I have a question about pointer.
The textbook said pointer stores memory address, and using printf("%p",pointer) we can show where this pointer points in our memory.
But every pointer alse has a type, like int *pointer, long *p and so on. int *pointer means "p is a pointer to int".
My question if we write
int *p,i;
p=&i;
*p=99;
if the pointer only contains the address information, how could the programme know how many digits should be used for storing integer 99? Because an integer could be 16 bits int or 32 bits long.
So I was wondering if an int pointer in memory not only stores address information, but also stores the type information?
Because an integer could be 16 bits int or 32 bits long.
An integer could, but an int could not. Regardless of how large that is exactly in your environment, its size is set in stone (within that environment) and doesn't change at run time. An int * only points to an int, not to a long. Note that if there were any such problems, they would affect int x; equally.
So a pointer really only stores the memory address. Information about the size of the pointee is in the type (just as a non-pointer variable's type tells the compiler how large that variable is).
Make sure you don't confuse what the hardware does with what the compiler does. A pointer is an address to a memory location as far as the hardware is concerned. What that memory location contains, and how long that data is, does not matter. A pointer does not store anything either. It points to a location and that's all. In assembly, this would be similar to using a register that points to a memory location.
The compiler is what tracks the type of data contained at that pointed to location. It is the compiler's job to save you from making type errors. This is where some people complain that you can shoot yourself in the foot with C. It's possible to have a pointer point to a data location where that data can be most anything and any length.
So I was wondering if an int pointer in memory not only stores address information, but also stores the type information?
No, a pointer is a memory address (or in some cases, a value analogous to a memory address). A pointer doesn't contain the data -- it points to the data. In your example, the data is stored in another location (given the name i), and p contains the address of i.
how could the programme know how many digits should be used for storing integer 99?
All the bits (binary digits) of the value type are used to store the stored value. Any given type (like int) has a fixed size. int can have different sizes depending on the system being used, but the size is always determined when the code is compiled. That is, the type int could be 16 bits, 32 bits, 64 bits, or some other size, but the compiler will always use a single size for compiling an entire program.
The type information is retained in the source code code and is used by the compiler to perform type checking and to generate appropriate code, the type is implicit in the generated code rather than explicitly stored as data.

How does pointer type casting work in c

I understand that in c, a pointer points to a memory address. In the following code
char *cp;
someType *up; // Assuming that someType is a union of size 16 bytes
cp = sbrk(nu * sizeof(someType));
// Here is what confuses me
up = (someType *)cp;
According to this link http://en.wikibooks.org/wiki/C_Programming/Pointers_and_arrays
If cp points to an address of 0x1234, so 0x1234 should be the beginning of the newly allocated memory, right?
So when "cp" is casted to a pointer to someType and assigned to "up", it actually says "up" is a pointer that points to 0x1234, assumes in 32-bits system, each memory address takes 4 bytes, a someType object will use 4 memory address to store its value, so the addresses 0x1234, 0x1235, 0x1236, 0x1237 collectively store a someType object, is this correct?
Thanks in advance.
Pointer type casting doesn't do anything at the machine level. The value in memory is still just a plain old value in memory.
At the language level, that value is used as an address. In other words it is often used as the value passed to operations that require memory locations, such as the assembly "load" operation.
At the language level, extra constructs are added to the machine operations, and one of those "extras" are data types. The compiler is responsible for checking if type-rule violations exist, but at run time there is not such a constraint.
As a result, the cast does nothing at run time, but at compile time it directs the compiler to not emit an error as the type of the pointer's value will now be considered a compatible type to the variable holding the address.
Even on a 32-bit system, a memory address typically refers to a single byte, not four. So your Header will be covering the 16 memory addresses between 0x1234 and 0x1243.
To answer your questions:
cp points to the beginning of the newly allocated memory.
However, up will contain the same address as cp. Note it is bad form to try and assign a pointer from one type to a different type without "casting" it first - just to tell the compiler you really meant to do such a dangerous thing.
Typically assigning between types can cause all kinds of problems - as a result compilers will throw warnings if you do this without casting. The casting, however, doesn't actually have any effect on the program code itself - it is more a method of the programmer telling the compiler they really meant what they did.
By the way, the pointer up is allocated on the stack in your function. Assigning a value to up actually places the value in the memory location on the stack. So by assigning cp to up you are merely copying the value of the pointer in cp to the location in the stack assigned to up. There is nothing placed into the memory allocated by the sbrk() call.
First of all, remember that a pointer is an abstraction of a memory address; do not assume a one-to-one correspondence between a pointer value and a physical location in RAM. Pointers also have type semantics associated with them; adding 1 to a pointer value advances it to point to the next object of the pointed-to type:
char *cp;
int *ip;
struct huge *hp;
cp = cp + 1; // advances cp to the address of the next char (1 byte)
ip = ip + 1; // advances ip to the address of the next int (anywhere
// from 2 to 8 bytes depending on the architecture)
hp = hp + 1; // advances hp to the address of the next struct huge (however
// many bytes struct huge takes up)
This is exactly how array indexing works; the expression a[i] is treated as *(a + i); you offset i elements of whatever size from the base address, not i bytes.
As far as the cast is concerned...
A pointer to char is a different, incompatible type than a pointer to Header. They may have different sizes and representations depending on the underlying architecture. Because of this, the language won't allow an implicit conversion of one to the other through a simple assignment; you must use a cast to convert the rhs value to the type expected by the lhs.
If cp points to a address of 0x1234, so 0x1234 should be the beginning of the newly allocated memory, right?
Right.
So when cp is casted to a pointer to Header and assigned to up, it actually says up is a pointer that points to 0x1234, assumes in 32-bits system, each memory address takes 4 bytes, a Header object will use 4 memory address to store its value, so the addresses 0x1234, 0x1235, 0x1236, 0x1237 collectively store a Header object, is this correct?
Wrong. C is strictly byte addressed. The Header object will occupy addresses 0x1234 through 0x1234 + sizeof(Header) - 1, inclusive, whatever sizeof(Header) is (perhaps 16 in this case). To confuse the issue, adding 1 to any pointer increments its numeric value by the sizeof whatever it points to, so it is the case that up + 1 points beyond the end of allocated memory. However cp + 1 points to the second byte in the representation of the header object, whatever that is. (sizeof(char) is 1 by definition.)
This has nothing to do with your question, but I must warn you that calling sbrk with a nonzero argument will cause your program to crash at some indefinite point after the next call to malloc, realloc or free, and that nearly all standard library functions are allowed to call those functions "under the hood". If you want to make a large allocation directly from the operating system, use mmap.

Resources