I'm nearing the end of an introductory book on c programming called "C programming in easy steps" by Mike McGrath. I think I'll have a lot more to learn after this book by the looks of things though. Anyways, I'm working with memory allocation and I wrote this demo program, but it errors closed when I try to run it:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int i, *arr;
arr = calloc(5, sizeof(int));
if(arr!=NULL)
{
printf("Enter 5 integers, seperated by a space:");
for(i=0; i<5; i++) scanf("%d", &arr[i]);
printf("Adding more space...\n");
arr = realloc(8, sizeof(int));
printf("Enter 3 more integers seperated by a space:");
for(i=5; i<8; i++) scanf("%d", &arr[i]);
printf("Thanks.\nYour 8 entries were: ");
for(i=0; i<8; i++) printf("%d, ", arr[i]);
printf("\n");
free(arr);
return 0;
}
else {printf("!!! INSUFFICIENT MEMORY !!!\n"); return 1; }
}
Warning message:
|13|warning: passing argument 1 of 'realloc' makes pointer from integer without a cast|
c:\program files\codeblocks\mingw\bin\..\lib\gcc\mingw32\4.4.1\..\..\..\..\include\stdlib.h|365|note: expected 'void *' but argument is of type 'int'|
||=== Build finished: 0 errors, 1 warnings ===|
The resulting compilation asks for 5 integers and prints "Adding more space..." at which point the program terminates, instead of asking for the additional three integers and printing the input.
Any help would be nice. :) Thanks!
You're not using realloc the way you should:
/* 8 is not valid here. You need to pass the previous pointer. */
arr = realloc(8, sizeof(int));
Try:
tmp = realloc(arr, 8 * sizeof(*arr));
if (NULL != tmp)
arr = tmp;
As an aside, your program looks really crammed which makes it hard to read. Maybe leave an empty line once in a while ?
You need to pass the pointer to the memory you want to resize:
tmp = realloc(arr, 8 * sizeof(int));
if (NULL != tmp)
arr = tmp;
The first argument to realloc should be the previously allocated pointer
Look up how realloc works - you have to pass it the original pointer:
int * tmp = realloc(arr, 8 * sizeof(int));
if (tmp)
{
arr = tmp;
}
else // Error!
Your use of realloc is wrong.
// ptr: Pointer to a memory block previously allocated with malloc, calloc or
// realloc to be reallocated.
void * realloc ( void * ptr, size_t size );
You should use realloc(arr, 8 * sizeof(int));
At fist You gotta learn the the way to use realloc.
The reason for the 1st warning your seeing on your screen
passing argument 1 of 'realloc' makes pointer from integer without a cast
int i, *arr;
arr = calloc(5, sizeof(int)); \\ Not the right way
arr = (int *) calloc (5,sizeof(int)); \\ makes sense
You have to type cast the pointer returned by The calloc before it is being assigned.Thats why you got the warning without a cast.
Note
char *arr ; arr = (char *) realloc (5,sizeof(char))
double *char: arr =(double *) realloc (5,sizeof(double))
I guess you got the point.Typecast it into the type of the pointer your going to assign. because the calloc returns void pointer and you have to type cast into the data type you want before you use it
and As far to my Knowledge
for(i=0; i<5; i++) scanf("%d", &arr[i]); \\ this is not the way to use pointers
this would be mostly used in arrays !
This is the way to use pointers
*(arr+1) or *(arr+any_variable) \\
and remember as your defining arr as integer pointer it increments its address by 2
example arr pointing to 3000 memory location after *(arr+1)
points to 3002 location and if arr pointer is ,char *arr, then
arr pointing to 3000 then *(arr +1 ) now it will point to 3001 location
same for double by 8 and for float 4 .
1 does not mean by 1 it means increment it by the size of the pointer pointing to.
well I never noticed this kind of syntax for pointers
&arr[i]
If that is also the way to use pointers then I'm glad to accept it I learned the other way to access pointers
but think of using these *(arr+i) mostly
well you can also use
(int *) calloc(5, sizeof(int))
\\ the number of bytes allocated by it is 5 * sizeof(int) = 5*2 =10
Thanks.
and please go through these
http://www.cplusplus.com/reference/clibrary/cstdlib/calloc/ and these site is really really promsising site for beginners I hope you enjoy and any doubts we are here to help you
Related
So I was just playing around with Array pointers to see how they work, my example below allocates space for 2 array pointers to an array with 10 ints.
#include <stdio.h>
#include <stdlib.h>
int main(void) {
int (*p)[10] = malloc(sizeof(int[10]) * 2);
for (int arrayI = 0; arrayI < 2; ++arrayI) {
for (int i = 0; i < 10; ++i) {
p[arrayI][i] = (arrayI+1) * i;
}
}
for (int arrayI = 0; arrayI < 2; ++arrayI) {
for (int i = 0; i < 10; ++i) {
printf("%d\n", p[arrayI][i]);
}
printf("\n");
}
}
This seems to work fine and gives me:
C:\Users\USERNAME\Desktop>gcc -Wall -Wextra --std=c18 a.c && a.exe
0
1
2
3
4
5
6
7
8
9
0
2
4
6
8
10
12
14
16
18
For my question, you rarely see code like this, if at all. Is there anything dangerous with doing things like this or is it just "bad code". And again, this is just me playing around with Array pointers.
Is there anything dangerous with doing things like this or is it just "bad code".
No. This is actually a correct way of making a dynamic allocated 2D array.
Instead of
int (*p)[10] = malloc(sizeof(int[10]) * 2);
I prefer
int (*p)[10] = malloc(2 * sizeof *p);
As p is a pointer to an array of 10 ints, *p is an array of 10 ints.
Many prefer to have an explicit release of memory. It's not required as the program terminates anyway. It's opinion based but I would add:
free(p);
return 0;
at the end of the program.
my example below allocates space for 2 array pointers to an array with 10 ints
No, this is one array pointer int (*p)[10]. This gives 2 arrays: sizeof(int[10]) * 2.
Is there anything dangerous with doing things like this
The only danger is the obscure de-referencing syntax. The most correct way to write your example is this:
int (*p)[2][10] = malloc(sizeof(int[2][10]));
or equivalent
int (*p)[2][10] = malloc(sizeof *p);
But if you do that, you have to write the strange-looking (*p)[i][j] when de-referencing. Therefore we drop the left-most dimension, a "manual array decay", and get a int (*)[10] which is actually a pointer to the first element in a int[2][10] array. If you want, you could also rewrite the code as:
int (*arr)[2][10] = malloc(sizeof *arr);
int (*p)[10] = *arr;
Also, you should always free the allocated memory, since free will often result in a crash in case you have any lurking pointer corruption bugs somewhere in the program.
If I'm trying to create a global array to hold an arbitrary number of integers in this case 2 ints. How is it possible that I can assign more numbers to it if I only allocate enough space for just two integers.
int *globalarray;
int main(int argc, char *argv[]) {
int size = 2;
globalarray = malloc(size * sizeof(globalarray[0]));
// How is it possible to initialize this array pass
// the two location that I allocated.
for (size_t i = 0; i < 10; i++) {
globalarray[i] = i;
}
for (size_t i = 0; i < 10; i++) {
printf("%d ", globalarray[i]);
}
printf("%s\n", "");
int arrayLength = sizeof(*globalarray)/sizeof(globalarray[0]);
printf("Array Length: %d\n", arrayLength);
}
When I run this it gives me
0 1 2 3 4 5 6 7 8 9
Array Length: 1
So I wanted to know if someone could clarify this for me.
(1) Am I creating the global array correctly?
(2) Why is the array length 1? When I feel that it should be 2 since I malloced the pointer for 2.
And background info on why I want to know this is because I want to create a global array (shared array) so that threads can later access the array and change the values.
How is it possible to initialize this array pass the two location that I allocated.
Short answer: This is undefined behaviour and anything can happen, also the appearance that it worked.
Long answer: You can only initialize the memory you've allocated, it
doesn't matter that the variable is a global variable. C doesn't prevent you from
stepping out of bounds, but if you do, then you get undefined behaviour and anything can happen
(it can "work" but it also can crash immediately or it can crash later).
So if you know that you need 10 ints, then allocate memory for 10 int.
globalarray = malloc(10 * sizeof *globalarray);
if(globalarray == NULL)
{
// error handling
}
And if you later need more, let's say 15, then you can use realloc to increase
the memory allocation:
globalarray = malloc(10 * sizeof *globalarray);
if(globalarray == NULL)
{
// error handling
// do not contiue
}
....
// needs more space
int *tmp = realloc(globalarray, 15 * sizeof *globalarray);
if(tmp == NULL)
{
// error handling
// globalarray still points to the previously allocated
// memory
// do not continue
}
globalarray = tmp;
Am I creating the global array correctly?
Yes and no. It is syntactically correct, but semantically it is not, because you are
allocating space for only 2 ints, but it's clear from the next lines that
you need 10 ints.
Why is the array length 1? When I feel that it should be 2 since I malloced the pointer for 2.
That's because
sizeof(*globalarray)/sizeof(globalarray[0]);
only works with arrays, not pointers. Note also that you are using it wrong in
two ways:
The correct formula is sizeof(globalarray) / sizeof(globalarray[0])
This only works for arrays, not pointers (see below)
We sometimes use the term array as a visual representation when we do stuff
like
int *arr = malloc(size * sizeof *arr)
but arr (and globalarray) are not arrays,
they are pointers. sizeof returns the amount in bytes that the
expression/variable needs. In your case *globalarray has type int and
globalarray[0] has also type int. So you are doing sizeof(int)/sizeof(int)
which is obviously 1.
Like I said, this only works for arrays, for example, this is correct
// not that arr here is not an array
int arr[] = { 1, 2, 3, 4 };
size_t len = sizeof arr / sizeof arr[0]; // returns 4
but this is incorrect:
int *ptr = malloc(4 * sizeof *ptr);
size_t len = sizeof ptr / sizeof ptr[0]; // this is wrong
because sizeof ptr does not returns the total amount of allocated
bytes, it returns the amount of bytes that a pointer needs to be stored in memory. When you are dealing with
pointers, you have to have a separate variable that holds the size.
C does not prevent you from writing outside allocated memory. When coding in C it is of the utmost importance that you manage your memory properly.
For your second question, this is how you would want to allocate your buffer:
globalarray = malloc(sizeof(int) * size);
And if you are on an older version of C than c11:
globalarray = (int*) malloc(sizeof(int) * size);
I'm having some trouble with using the malloc/realloc command with arrays. I've created a small array with some integers in it, and tried to add one value to it by expanding the size with realloc and adding the value, but when I do that the 0 index's value is not preserved and is seen as garbage.
#include <stdio.h>
#include <stdlib.h>
int main(){
int n;
printf("Enter size of array\n");
scanf("%d",&n);
int *A = malloc(n*sizeof(int));
for(int i = 0; i < n; i++){
A[i] = i + 1;
}
*A = realloc(A, sizeof(A)+ sizeof(int));
A[n] = 1234;
for(int i = 0; i < n + 1; i++){
printf("%d\n",A[i]);
}
return 0;
}
and when i run the program this happens:
Enter size of array
5
14643216
2
3
4
5
1234
Does anyone know why the 0 index of the array is getting this value and not 1?
$ gcc a.c
a.c: In function ‘main’:
a.c:12:12: warning: assignment makes integer from pointer without a cast [-Wint-conversion]
*A = realloc(A, sizeof(A)+ sizeof(int));
^
Make sure to configure your compiler to emit warnings on code that looks suspicious. Any remotely decent compiler would raise at least a warning, if not an error, on this line. realloc returns a pointer, which you're trying to assign to an int object.
You need to assign the resulting pointer to A, not *A. Furthermore, there's another error, which compilers can't warn you about. sizeof(A)+ sizeof(int) is too small, and does not make much sense in context. Note that sizeof(A) is the size of the pointer A. There's no way to use sizeof to find the number of items in the array that A points to, because sizeof relies on compile-time information. To extend the array by one element, you need to add sizeof(int) to the current allocated size, which is n*sizeof(int), i.e. the new size should be (n+1) * sizeof(int).
In addition, it would be better to use sizeof(*A) than sizeof(int). The two are equivalent, but sizeof(*A) has the advantage that it'll still be correct if you decide to change the array elements, e.g. to make them long.
A = realloc(A, (n+1) * sizeof(*A));
Write A = realloc(A, (n + 1) * sizeof(int)); instead of *A = realloc(A, sizeof(A)+ sizeof(int));
*A = ... will overwrite the value of the first index with a "address value" if A is not moved to another place in memory (undefined behaviour otherwise).
Note that sizeof(A) is a constant value (probably 8, and not the amount of memory allocated previously), such that you had a good chance that realloc did not move the memory.
I am trying to track down a bug a big program. I think it is due to how I am passing arrays to my functions. Am I doing this correctly?
main(){
int *x = declarArray(x, 100);
int *y = declarArray(x, 100);
// lines of code....
x = arrayManip(x, 100);
// more code...
int i;
for(i=0; i<100; i++)
y[i] = x[i];
//more code...
free(x);
free(y);
}
This is how I manipulate arrays:
int *arrayManip(int *myarray, int length){
int i;
for(i=0; i<length; i++)
myarray[i] = i;
return array;
}
This is how I initialize the arrays:
int* declareArray(int *myarray, int length){
myarray = (int*) malloc(length*sizeof(int*));
if (myarray==NULL)
printf("Error allocating memory!\n");
int i;
for(i=0; i<length; i++)
myarray[i] = -888;
return myarray;
}
This code seems to work fine on a small scale, but maybe there is a problem once I have many more arrays of larger size that are often getting passed back and forth and copied in my program?
declarArray :
Name is not gramatically correct
The name of the function is not what it does
malloc with sizeof(int*), not sizeof(int). Guarantuee to be a bug in 64 bit machine
malloc fails, you print, but still write to null
passing myarray as argument is a noop as is
-888 is a magic number
There is no error check whatsoever
My advice. Throw it away and start fresh
No, as per my understanding.
You allocating one dim array => elements in that array should be integers and not pointers to integers so instead of this :
myarray = (int*) malloc(length*sizeof(int*));
it should be :
myarray = (int*) malloc(length*sizeof(int));
In function arrayManip you pass param named array, and than you trying to access it as myarray
This:
myarray = (int*) malloc(length*sizeof(int*));
allocates an array of length pointers to an integer, but then puts it into a pointer to an integer (i.e. an array of integers, not pointers to integers). If you want an array of integers, you want:
myarray = (int*) malloc(length*sizeof(int));
or (if you want to zero it):
myarray = (int*) calloc(length, sizeof(int));
which does the size x length calculation itself.
To allocate a list of pointers to integers, you want:
myarray = (int**) malloc(length*sizeof(int*));
or
myarray = (int**) calloc(length, sizeof(int*));
Unless you are fantastically concerned about speed, I find using calloc() results in fewer bugs from uninitialized arrays, and makes the reason for the allocated size more obvious.
The pointer is of word size [2 or 4 ,... depending on machine architecture]. whatever it may point to int,double,float,...
for integer pointer it works if it takes 4 bytes for int in machine. when u go for other data type it 'll lead you to error.
you should allot memory as
pointer = (DataType*) malloc (length * sizeof(DataType));
use malloc and to make your code clear.
void* malloc (size_t size);
malloc reference
use memset to allot default value [-888] for your array.
void *memset(void *str, int c, size_t n)
I want to create an integer pointer p, allocate memory for a 10-element array, and then fill each element with the value of 5. Here's my code:
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
printf("Current value of array: %p\n", *p);
*p += sizeof(int);
i += sizeof(int);
}
I've added some print statements around this code, but I'm not sure if it's actually filling each element with the value of 5.
So, is my code working correctly? Thanks for your time.
First:
*p += sizeof(int);
This takes the contents of what p points to and adds the size of an integer to it. That doesn't make much sense. What you probably want is just:
p++;
This makes p point to the next object.
But the problem is that p contains your only copy of the pointer to the first object. So if you change its value, you won't be able to access the memory anymore because you won't have a pointer to it. (So you should save a copy of the original value returned from malloc somewhere. If nothing else, you'll eventually need it to pass to free.)
while (i < sizeof(array)){
This doesn't make sense. You don't want to loop a number of times equal to the number of bytes the array occupies.
Lastly, you don't need the array for anything. Just remove it and use:
int *p = malloc(10 * sizeof(int));
For C, don't cast the return value of malloc. It's not needed and can mask other problems such as failing to include the correct headers. For the while loop, just keep track of the number of elements in a separate variable.
Here's a more idiomatic way of doing things:
/* Just allocate the array into your pointer */
int arraySize = 10;
int *p = malloc(sizeof(int) * arraySize);
printf("Size of array: %d\n", arraySize);
/* Use a for loop to iterate over the array */
int i;
for (i = 0; i < arraySize; ++i)
{
p[i] = 5;
printf("Value of index %d in the array: %d\n", i, p[i]);
}
Note that you need to keep track of your array size separately, either in a variable (as I have done) or a macro (#define statement) or just with the integer literal. Using the integer literal is error-prone, however, because if you need to change the array size later, you need to change more lines of code.
sizeof of an array returns the number of bytes the array occupies, in bytes.
int *p = (int *)malloc( sizeof(array) );
If you call malloc, you must #include <stdlib.h>. Also, the cast is unnecessary and can introduce dangerous bugs, especially when paired with the missing malloc definition.
If you increment a pointer by one, you reach the next element of the pointer's type. Therefore, you should write the bottom part as:
for (int i = 0;i < sizeof(array) / sizeof(array[0]);i++){
*p = 5;
p++;
}
*p += sizeof(int);
should be
p += 1;
since the pointer is of type int *
also the array size should be calculated like this:
sizeof (array) / sizeof (array[0]);
and indeed, the array is not needed for your code.
Nope it isn't. The following code will however. You should read up on pointer arithmetic. p + 1 is the next integer (this is one of the reasons why pointers have types). Also remember if you change the value of p it will no longer point to the beginning of your memory.
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#define LEN 10
int main(void)
{
/* Allocate memory for a 10-element integer array. */
int array[LEN];
int i;
int *p;
int *tmp;
p = malloc(sizeof(array));
assert(p != NULL);
/* Fill each element with the value of 5. */
printf("Size of array: %d bytes\n", (int)sizeof(array));
for(i = 0, tmp = p; i < LEN; tmp++, i++) *tmp = 5;
for(i = 0, tmp = p; i < LEN; i++) printf("%d\n", tmp[i]);
free(p);
return EXIT_SUCCESS;
}
//Allocate memory for a 10-element integer array.
int array[10];
int *p = (int *)malloc( sizeof(array) );
At this point you have allocated twice as much memory -- space for ten integers in the array allocated on the stack, and space for ten integers allocated on the heap. In a "real" program that needed to allocate space for ten integers and stack allocation wasn't the right thing to do, the allocation would be done like this:
int *p = malloc(10 * sizeof(int));
Note that there is no need to cast the return value from malloc(3). I expect you forgot to include the <stdlib> header, which would have properly prototyped the function, and given you the correct output. (Without the prototype in the header, the C compiler assumes the function would return an int, and the cast makes it treat it as a pointer instead. The cast hasn't been necessary for twenty years.)
Furthermore, be vary wary of learning the habit sizeof(array). This will work in code where the array is allocated in the same block as the sizeof() keyword, but it will fail when used like this:
int foo(char bar[]) {
int length = sizeof(bar); /* BUG */
}
It'll look correct, but sizeof() will in fact see an char * instead of the full array. C's new Variable Length Array support is keen, but not to be mistaken with the arrays that know their size available in many other langauges.
//Fill each element with the value of 5.
int i = 0;
printf("Size of array: %d\n", sizeof(array));
while (i < sizeof(array)){
*p = 5;
*p += sizeof(int);
Aha! Someone else who has the same trouble with C pointers that I did! I presume you used to write mostly assembly code and had to increment your pointers yourself? :) The compiler knows the type of objects that p points to (int *p), so it'll properly move the pointer by the correct number of bytes if you just write p++. If you swap your code to using long or long long or float or double or long double or struct very_long_integers, the compiler will always do the right thing with p++.
i += sizeof(int);
}
While that's not wrong, it would certainly be more idiomatic to re-write the last loop a little:
for (i=0; i<array_length; i++)
p[i] = 5;
Of course, you'll have to store the array length into a variable or #define it, but it's easier to do this than rely on a sometimes-finicky calculation of the array length.
Update
After reading the other (excellent) answers, I realize I forgot to mention that since p is your only reference to the array, it'd be best to not update p without storing a copy of its value somewhere. My little 'idiomatic' rewrite side-steps the issue but doesn't point out why using subscription is more idiomatic than incrementing the pointer -- and this is one reason why the subscription is preferred. I also prefer the subscription because it is often far easier to reason about code where the base of an array doesn't change. (It Depends.)
//allocate an array of 10 elements on the stack
int array[10];
//allocate an array of 10 elements on the heap. p points at them
int *p = (int *)malloc( sizeof(array) );
// i equals 0
int i = 0;
//while i is less than 40
while (i < sizeof(array)){
//the first element of the dynamic array is five
*p = 5;
// the first element of the dynamic array is nine!
*p += sizeof(int);
// incrememnt i by 4
i += sizeof(int);
}
This sets the first element of the array to nine, 10 times. It looks like you want something more like:
//when you get something from malloc,
// make sure it's type is "____ * const" so
// you don't accidentally lose it
int * const p = (int *)malloc( 10*sizeof(int) );
for (int i=0; i<10; ++i)
p[i] = 5;
A ___ * const prevents you from changing p, so that it will always point to the data that was allocated. This means free(p); will always work. If you change p, you can't release the memory, and you get a memory leak.