I'm trying to access the next element in dynamically allocated by adding the size of placeholder array to the first element. Size of placeholder array is 4 bytes, so if I add 4 bytes to it first element with address 2147549788, I should be looking at next memory location 2147549792. But, instead I'm looking at an address in 16 bytes 2147549804. If I read the address of array elements directly I get the right address. Wondering why adding size of placeholder gives different results ?
Also, if I access the location of second element outside the for loop, the location is off by another 16 bytes i.e 2147549820
#include "stdio.h"
#include "time.h"
#include <stdlib.h>
#include <string.h>
typedef struct Section {
int numOfStudents;
} Section;
typedef struct School {
int schoolId;
Section sections[1]; //placeholder
} School;
int main(void)
{
School *schoolA_p;
Section section1;
int sizeOffset = 0;
int i,sectionSize;
int sizeOfSchool = sizeof(School) - sizeof(Section) + (sizeof(Section)*2);
schoolA_p = (struct School *) malloc(sizeOfSchool);
for(i=0;i<2;i++)
{
sectionSize = sizeof(Section);
printf("\nsize of section = %d\n", sizeof(Section));
printf("Number of bytes to add to first element to access the next element = %d\n", sizeOffset);
printf("In Loop Location of schoolA_p->sections[%d]= 0x%lx\n",i, &(schoolA_p->sections[0]) + sizeOffset);
sizeOffset += sectionSize;
}
printf("\n Location of schoolA_p->sections[0]= 0x%lx\n",&(schoolA_p->sections[0]));
printf("\n Location of schoolA_p->sections[1]= 0x%lx\n",&(schoolA_p->sections[1]));
printf("\n Outside of lopop Location of schoolA_p->sections[0]= 0x%lx\n", &(schoolA_p->sections[0])+ sizeOffset);
free(schoolA_p);
return 0;
}
Pointer arithmetic works like this: If p is a pointer to an array element a[n], then p + i is a pointer to a[n + i]. In other words, pointer arithmetic moves in units of whatever base type the pointer is declared as, not bytes.
C pointer arithmetic takes into account the size of the data pointed to when you increment a pointer.
So if p is a pointer to data of 4 bytes, p + 1 calculates the address 4 bytes after p.
In other words, your doing too much work. C does this bookkeeping for you, and that's why you're getting incorrect results.
As a side note, this is why you cannot use pointer arithmetic on void* pointers. The size of the data pointed to is not specified.
Related
First things first, this is for a college class. The problem is to run malloc 1001 times with size 4, storing each returned pointer as a char *, then get the different between the first and last pointer to calculate total memory used. The instructions also state this number will be much higher than one might expect.
This is what I have so far, but I don't think it is working properly(and even it is I would appreciate if someone could show me how to do it more efficiently):
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Init variables
int size = 4;
char *ptrs[1001];
// Allocate memory
for (int i = 0; i <= 1001; i++)
{
ptrs[i] = malloc(size);
}
// Get first and last address
int *first_ptr = (int*)&ptrs[0];
int *last_ptr = (int*)&ptrs[sizeof(ptrs) / sizeof(*ptrs) - 1];
int diff = (int)last_ptr - (int)first_ptr;
// Print first and last address
printf("First pointer's address: %d\n", first_ptr);
printf("Last pointer's address: %d\n", last_ptr);
printf("Memory used: %d\n", diff);
free(*ptrs);
return 0;
}
So far the first and last addresses are always large negative values(this could be fine, I'm not certain), and the difference is always 4000, even if I change size to 16 or 32.
Any help would be greatly appreciated.
Your code has errors:
Following cycle should have this condition: i < 1001 and not i <= 1001 as
char *ptrs[1001] have 1001 elements (indexed form 0 to 1000) and not 1002.
// Allocate memory
for (int i = 0; i <= 1001; i++)
{
ptrs[i] = malloc(size);
}
If you want to know difference between addresses of allocated memory and not of elements of your array then just use values of your array:
int difference = (int)(ptrs[1000] - ptrs[0])
In your case you are calculating difference between addresses in array and it dependent on size of array element (size of pointer) and not on contents of its elements
// Get first and last address
int *first_ptr = (int*)&ptrs[0];
int *last_ptr = (int*)&ptrs[sizeof(ptrs) / sizeof(*ptrs) - 1];
Difference between first and last element is not guaranteed to be actual used memory size. It depends on how memory allocation works.
In general, i'm trying to allocate values of first.a and first.b
to a array's in struct secon.
typedef struct {
int a;
int b;
} firs;
//secon is my struct which contains dynamic array
//can i use int here ?
typedef struct {
int *aa;
int *bb;
} secon;
//pointer to secon intialised to NULL;
secon* sp=NULL;
int main()
{
firs first;
//plz assume 2 is coming from user ;
sp=malloc(sizeof(secon)*2);
//setting values
first.a=10;
first.b=11;
/* what i'm trying to do is assign values of first.a and first.b to my
dynamically created array*/
/* plz assume first.a and first.b are changing else where .. that means ,not
all arrays will have same values */
/* in general , i'm trying to allocate values of first.a and first.b
to a array's in struct second. */
for(int i=0; i<2; i++) {
*( &(sp->aa ) + (i*4) ) = &first.a;
*( &(sp->bb ) + (i*4) ) = &first.b;
}
for(int i=0; i<2; i++) {
printf("%d %d \n", *((sp->aa) + (i*4) ),*( (sp->bb) +(i*4) ) );
}
return 0;
}
MY output :
10 11
4196048 0
Problems with my code:
1. whats wrong with my code?
2. can i use int inside struct for dynamic array?
3. what are the alternatives?
4. why am i not getting correct answer?
Grigory Rechistov has done a really good job of untangling the code and you should probably accept his answer, but I want to emphasize one particular point.
In C pointer arithmetic, the offsets are always in units of the size of the type pointed to. Unless the type of the pointer is char* or void* if you find yourself multiplying by the size of the type, you are almost certainly doing it wrong.
If I have
int a[10];
int *p = &(a[5]);
int *q = &(a[7]);
Then a[6] is the same as *(p + 1) not *(p + 1 * sizeof(int)). Likewise a[4] is *(p - 1)
Furthermore, you can subtract pointers when they both point to objects in the same array and the same rule applies; the result is in the units of the size of the type pointed to. q - p is 2, not 2 * sizeof(int). Replace the type int in the example with any other type and the p - q will always be 2. For example:
struct Foo { int n ; char x[37] ; };
struct Foo a[10];
struct Foo *p = &(a[5]);
struct Foo *q = &(a[7]);
q - p is still 2. Incidentally, never be tempted to hard code a type's size anywhere. If you are tempted to malloc a struct like this:
struct Foo *r = malloc(41); // int size is 4 + 37 chars
Don't.
Firstly, sizeof(int) is not guaranteed to be 4. Secondly, even if it is, sizeof(struct Foo) is not guaranteed to be 41. Compilers often add padding to struct types to ensure that the members are properly aligned. In this case it is almost a certainty that the compiler will add 3 bytes (or 7 bytes) of padding to the end of struct Foo to ensure that, in arrays, the address of the n member is aligned to the size of an int. always always always use sizeof.
It looks like your understanding how pointer arithmetic works in C is wrong. There is also a problem with data layout assumptions. Finally, there are portability issues and a bad choice of syntax that complicates understanding.
I assume that wit this expression: *( &(sp->aa ) + (i*4) ) you are trying to access the i-th item in the array by taking address of the 0-th item and then adding a byte offset to it. This is wrong of three reasons:
You assume that after sp[0].aa comes sp[1].aa in memory, but you forget that there is sp[0].bb in between.
You assume that size of int is always 4 bytes, which is not true.
You assume that adding an int to secon* will give you a pointer that is offset by specified number of bytes, while in fact it will be offset in specified number of records of size secon.
The second line of output that you see is random junk from unallocated heap memory because when i == 1 your constructions reference memory that is outside of limits allocated for *secon.
To access an i-th item of array referenced by a pointer, use []:
secon[0].aa is the same as (secon +0)->aa, and secon[1].aa is equal to (secon+1)->aa.
This is a complete mess. If you want to access an array of secons, use []
for(int i=0;i<2;i++)
{
sp[i].aa = &first.a; // Same pointer both times
sp[i].bb = &first.b;
}
You have two copies of pointers to the values in first, they point to the same value
for(int i=0;i<2;i++)
{
sp[i].aa = malloc(sizeof(int)); // new pointer each time
*sp[i].aa = first.a; // assigned with the current value
sp[i].bb = malloc(sizeof(int));
*sp[i].bb = first.b;
}
However the compiler is allowed to assume that first does not change, and it is allowed to re-order these expressions, so you are not assured to have different values in your secons
Either way, when you read back the values in second, you can still use []
for(int i=0;i<2;i++)
{
printf("%d %d \n",*sp[i].aa ),*sp[i].bb );
}
This question already has answers here:
Character pointers and integer pointers (++)
(10 answers)
Closed 5 years ago.
there is a sample in the chapter pointer of C Primer Plus Book.
I am so confuse about the code which set the array name into the sump function as formal parameter
Answer = sump(array, array + SIZE);
start is 00EFFBD8 ,it is ok that means arrary[0] address
but when it action:
int *end = array +SIZE // => "array[0] address + 10"
why end is 00EFFC00 (00EFFBD8 + 10*4), why not 00EFFBD8 +10 ???
#include <stdio.h>
#array size
#define SIZE 10
#sum function
int sump(int *start, int *end);
int main(void)
{
int array[SIZE] = { 10,9,8,7,6,5,4,3,2,1 };
long Answer;
Answer = sump(array, array + SIZE);
printf("a is %d\n", Answer);
return 0;
}
int sump(int *start, int *end)
{
int total=0;
while (start < end)
{
printf("start is %p, %d\n", start, *start);
printf("end is %p, %d\n", end, *end);
total += *start++;
}
return total;
}
When something is added to an address (array/pointer), adding one to the address means to force the particular pointer to point the starting byte of the next element in the sequence and not the next byte. Accessing next byte doesn't makes sense because what would you do with the weird result as an int is stored in 4 bytes.
Well, each and every data-type int float long and so on.. each occupy some space in the memory when you declare them. For example:
int k; //occupies 4-bytes of memory
float f; //occupies 4-bytes of memory
long l; //occupies 8-bytes
char c; //occupies 2-bytes
That's the C's convention for allocating memory to the variables. Now when you talk about addresses. Imagine memory is in form of blocks and base address/start address is 100. So when you declare an int type variable, it will place it at 100. But, int needs 4-bytes of memory so, the blocks that the CPU will give to this variable 'k' are, 100, 101, 102 and 103 (considering all these blocks are size 1-byte each). So now blocks 100 to 103 are allocated for variable-k.
When you declare an array of int type: int arr[10], the CPU makes 10 such k-variable that i made up there. So that means:
arr[0] //this will have address from 100 to 103
arr[1] //will have address from 104 to 107
arr[2] //will have address from 108 to 111
and so on, while the base address, that is the address of the whole array arr is 100. So you can calculate the address of arr[1] as base address of array + index*size of int where we know that base address of array is 100, index is what we need to calculate (that is 1) and size of int as i said earlier is 4-bytes. So, address of arr[1] = 100 + 1*4 = 104.
Similarly, the end address, that is the arr[9], will be 100 + 9*4 = 136 and the array will end at, 100 + 10*4. Now in your question the values are hexadecimals and base address is not hundred.
EDIT char in C and C++ follow ASCII code and hence only occupy 1 byte of memory. I was confused with Java following Unicode and thank #David-Bowling for making me realize that mistake.
I was playing with memory addressing in C and I encountered a situation I cannot fully explain.
EDIT: the code is compiled by a c++ compiler. (g++)
#include <cstdlib>
#include <cstdio>
int main()
{
int* array[10]; //array of pointers to integers
for(int i = 0; i < 10; i++)
{
array[i] = (int*)malloc(sizeof(int));
*(array[i]) = i;
}
printf("\n");
for(int i = 0; i < 10; i++)
{
printf("%d:%p\n", *(array[i]), array[i]);
}
printf("\n");
int arr[10]; //array of integers
int* start = arr; //pointer to the first element (array decay)
for(int i = 0; i < 10; i++)
arr[i] = i;
printf("\n");
for(int i = 0; i < 10; i++)
{
printf("%d:%p\n", *(start + i), start + i);
}
printf("\n");
return 0;
}
Everything compile and works however I get strange memory addresses.
For the first array I get something like:
0:0x23e4010
1:0x23e4030 (32 bits between the addresses which is correct)
but for the second array I get:
0:0x7ffdaf876290
1:0x7ffdaf876294 (only 4 bits? or maybe they are bytes - but why the long addresses???)
Can someone explain this? (also is there a function to transform the hex into decimal without any effort?)
In the first instance, your array is an array of pointers. Each element is a pointer and, when you allocate memory for each pointer to point to, it's completely unrelated to the memory you allocate for other pointers in that array. They are in fact 32 bytes apart in this case, but that's just pure chance.
In the latter case, you are creating an array of integers which are all bunched together, or "contiguous", in memory. They will be adjacent, hence the pattern you see when you print their addresses, which are 4 bytes apart. Evidently, int on your system is 4 bytes wide (which is fairly common still).
The "long addresses" are due to your use of dynamic allocation: that'll be the area in virtual memory where your system happens to hold the heap. Nothing to worry about.
So there's nothing "strange" about it.
Int for Array uses 1byte.
Let address of:
- array[0]=5000
Then
- array[1]=5001
- array[2]=5002
- array[3]=5003
- array[4]=5004
- array[5]=5005
- array[6]=5006
- array[7]=5007
- array[8]=5008
- array[9]=5009
Now, You're assigning pointer.
Then address of Pointer:
*(array[0])=5010
*(array[1])=5011
*(array[2])=5012
*(array[3])=5013
*(array[4])=5014
*(array[5])=5015
*(array[6])=5016
*(array[7])=5017
*(array[8])=5018
*(array[9])=5019
Here You can easily see that the difference between array[i] and *(array[i]) will be always 10bytes.
This is because when any Array is called then only it allocates memory total size at once.
Now addresses of second:
Array arr is defined but not called. Hence, no memory will be allocated till you call that arr
Here, calling is for defining it
Now, first line says:
int arr[10];
That only defined the base address.
Then you gave that base address to *start by:
int* start=arr;
Hence pointer gets that address.
Clearly, Let:
Address of:
arr[0]=5020
Then:
*(start+0)=5020
Since, it is a pointer (not an Array) hence will take 4bytes.
Similarly, all addresses range will be:
arr[0]=5020 - 5023
arr[1]=5024- 5028
And so on..
Explanation to Allocation:
Whenever we define an Array, it defines only the Base Address.
Ex:
int a[10];
Will allocate base address, i.e., starting address, i.e., address for a[0];
Whenever you define a pointer, it will also allocate base address only.
Difference lies only in the allocation, i.e., array allocates 1byte and pointer allocates 4byte (GCC/ Linux/32bit Compiler) for a Pointer.
I'm having a hard time understanding this program to illustrate pointers (from http://theocacao.com/document.page/234):
Below I don't understand why:
int * currentSlot = memoryBlock
isn't using &memoryBlock. I read the comment but don't get it. What is memoryBlock putting in there that &memoryBlock wouldn't? Won't both return the pointer to the set of ints created with calloc (assuming I understand what's been done that is)? What is really in * memoryBlock after calloc?
Then here, *currentSlot = rand();, how does the dereferencing work here? I thought the dereference would stop *currentSlot from giving the value of the memory address (the reference) to the actual value (no longer a reference but the value).
#include <stdio.h>
#include <stdlib.h> // for calloc and free
#include <time.h> // for random seeding
main ()
{
const int count = 10;
int * memoryBlock = calloc ( count, sizeof(int) );
if ( memoryBlock == NULL )
{
// we can't assume the memoryBlock pointer is valid.
// if it's NULL, something's wrong and we just exit
return 1;
}
// currentSlot will hold the current "slot" in the,
// array allowing us to move forward without losing
// track of the beginning. Yes, C arrays are primitive
//
// Note we don't have to do '&memoryBlock' because
// we don't want a pointer to a pointer. All we
// want is a _copy_ of the same memory address
int * currentSlot = memoryBlock;
// seed random number so we can generate values
srand(time(NULL));
int i;
for ( i = 0; i < count; i++ )
{
// use the star to set the value at the slot,
// then advance the pointer to the next slot
*currentSlot = rand();
currentSlot++;
}
// reset the pointer back to the beginning of the
// memory block (slot 0)
currentSlot = memoryBlock;
for ( i = 0; i < count; i++ )
{
// use the star to get the value at this slot,
// then advance the pointer
printf("Value at slot %i: %i\n", i, *currentSlot);
currentSlot++;
}
// we're all done with this memory block so we
// can free it
free( memoryBlock );
}
Thank you for any help.
Below I don't understand why:
int * currentSlot = memoryBlock
isn't using &memoryBlock.
Because both memoryBlock and currentSlot are pointers to int. &memoryBlock would be the address of a pointer to int, i.e. an int **.
What is "in" memoryBlock is a pointer to a block of memory.
Then here, *currentSlot = rand();, how does the dereferencing work here?
This is a rule of C: when a dereferencing expression like this occurs on the left-hand side of an expression, the right-hand side's value is stored in the memory location pointed to by the pointer being dereferenced.
int * memoryBlock;
memoryBlock is a variable which can hold the address of a memory block of integers. The size of the memoryBlock variable is the size of an address. Typically 4 or 8 bytes (sizeof(int*)). Its type is "pointer to int".
memoryBlock = calloc ( 5, sizeof(int) );
the memoryBlock variable is assigned the address of the start of the memory block able to hold 5 integers. The memory block size is 5 * sizeof(int) bytes.
memoryBlock + 1 is the address of the second integer in the block.
memoryBlock + 5 is one passed the address of the last integer in the block.
*memoryBlock is the content of the address (the first integer). type is integer.
*(memmoryBlock + 0) = 0;
*(memmoryBlock + 1) = 1;
*(memmoryBlock + 2) = 2;
*(memmoryBlock + 3) = 3;
*(memmoryBlock + 4) = 4;
// *(memmoryBlock + 5) = 5; illegal
Assigns integers to memory block.
Subscipt form same as above.
memmoryBlock[0] = 0;
memmoryBlock[1] = 1;
memmoryBlock[2] = 2;
memmoryBlock[3] = 3;
memmoryBlock[4] = 4;
// memmoryBlock[5] = 5; illegal
&memoryBlock is the address of the memoryBlock variable. This is not the address of the callocated space. It's type is int** "pointer to pointer to integer" not int*.
int ** pmemoryBlock;
pmemoryBlock is a variable which hold the address of an address of a memory block of integers. The size of pmemoryBlock is the size of an address. Typically 4 or 8 bytes (sizeof(int**)).
pmemoryBlock = &memoryBlock;
pmemoryBlock is assigned the address of a variable which holds the address of the start of the memory block able to hold 5 integers.
*pmemoryBlock is the address of the memory block.
**pmemoryBlock is the first integer in the memory block
*((*pmemoryBlock) + 0) is the first integer in the memory block
*((*pmemoryBlock) + 1) is the seconds integer in the memory block
...
memoryBlock is an array of integers (int*). (technically a pointer to an int but since it was allocated with enough room for 10 integers you can think of it as the start of an array)
*memoryBlock is the integer that memoryBlock is pointing to (the first int in the array). While the notation looks the same as the declariation it is actually dereferencing the value. IMHO it is poorly written as it should be declared
int* currentSlot = memoryBlock;
to make it more clear that it's a pointer to an integer, but that's a style choice.
&memoryBlock is the address of the pointer.
int * currentSlot = memoryBlock;
stores the pointer to the first slot in currentSlot. The program is then generating random numbers and putting them in each of the 10 clost by incrementing currentSlot (which internally is incrementing the pointer by the length of an integer.
Hope that helps.
In the code, memoryBlock is apointer to some memory that stores integers. That is, the actual value of the variable memoryBlock is the address just allocated. If you use &memoryBlock you get the address of where the variable is stored, not what it points to.
Lets take an example:
int foo = 5;
/* the variable "foo" is stored in memory,
and that memory contains the number 5 */
int bar = 7;
/* the variable "foo" is stored in memory,
and that memory contains the number 7 */
int *foo_pointer = &foo;
/* the variable "foo_pointer" is stored in memory,
and that memory contains the address of the variable "foo" */
foo_pointer = &bar;
/* the contents of the variable "foo_pointer" is no longer the address
of where the variable "foo" is in memory, instead it is the address
of where the variable "bar" */
I hope this makes some sense, and it helps a little.
It's not supposed to use &memoryBlock, which is the (int ** (heh!)) address of the the pointer into the memory you are clearing. In other words, memoryBLock (iff it's not NULL) points to (i.e., holds the address of) the first int in the calloc( )'ed memory. To reference that cleared-to-0 memory, you use *memoryBlock.
If you ever find yourself trying to use &memoryBlock, don't: it's never the right thing to do in the code fragment you posted.
HTH. If it doesn't help, go back to K&R and study pointers some more. Maybe a lot more.
int * is a pointer, which can be dereferenced. int ** is a pointer to a pointer, which can be dereferenced twice. So what does this mean? Well, a pointer is nothing more than an integer. Memory addresses just start from zero to its max range. For 32-bit systems, its range of addressable memory is 0 to 2^32-1 (or 4294967295). Each of this address has a byte value. If you have an int *, then it will access the address 4-bytes at a time.
Also, for simplicity, let's assume this is a virtual address, you can't just access all this memory, some will be protected (system), some are not valid (not committed). To gain more memory you can ask the system to allocate more from this range. sbrk in Linux, VirtualAlloc in Windows but you will be accessing them usually through C's malloc or calloc.
Let's say, you have starting from 0x100:
0x100: 'h', 'e', 'l', 'l', 'o', '\0'
So this string, occupies memory from 0x100 to 0x105 (including the null terminator). If you have a pointer:
char *p = 0x100;
Then you have:
p // 0x100
*p // 'h'
p+1 // 0x101
*(p+1) // 'e'
p += 2 // 0x102
*p // 'l'
p = 0x200;
p // now points to 0x200 in memory
*p // contains whatever value is in 0x200
If you have int pointers, then you are accessing memory 4-bytes at a time (or however big an int is on your system).
So with all that background, when you run calloc, it returns the address of the block you've requested.
int *memoryBlock = calloc(count, sizeof(int));
// memoryBlock is an array of int, assuming sizeof(int) == 4, then
// you have 40 bytes of memory starting from the address of what is
// returned by calloc.
memoryBlock++; // now memoryBlock is at base address + 4
*memoryBlock = 10; // now that address contains the value 10
(*memoryBlock)++; // now that address contains the value 11
memoryBlock++; // now memoryBlock is 4 bytes further