Array of buffers in C programming? - c

I am trying to create an array of buffers. I need to store an integer into each buffer. I'm not quite sure how this should be done.
int BUFFER_LENGTH = 50; //the size of each buffer
int numberOfBuffers = 10; //number of buffers
int *pBuffers; //array of buffers
pBuffers = (int *) calloc (numberOfBuffers, sizeof(int)); //make array size of numberOfBuffers
int i;
for (i = 0; i < n; i++){ //initialize each buffer to zero.
&pBuffers[i] = 0x00;
}
What is it that I am doing wrong? This code isn't really working.

You might want to allocate enough space. Right there you only allocate enough space for 10 ints; looks like you want to allocate enough for 500. The simple way is int buffers[10][50]. But if you want to calloc, you have to calloc(BUFFER_LENGTH, sizeof(int)) numberOfBuffers times.
Also, calloc automatically clears the allocated memory, so no need to do that.
#define BUFFER_LENGTH 50 /* the size of each buffer */
#define BUFFERS 10 /* number of buffers */
int **pBuffers; /* array of buffers */
pBuffers = calloc (BUFFERS, sizeof(int *)); //make array of arrays
int i;
for (i = 0; i < BUFFERS; i++) {
pBuffers[i] = calloc(BUFFER_LENGTH, sizeof(int)); // make actual arrays
}

What you're creating with your sample is an array of integers. Instead, you'll want to create an array of integer arrays. The setup is similar, but you'll need to declare the variable as an int** and allocate each buffer individually.
int **ppBuffer = (int**) calloc(numberOfBuffers, sizeof(int*));
for(int i = 0; i < numberOfBuffers; ++i)
ppBuffer[i] = (int*) calloc(BUFFER_LENGTH, sizeof(int));
There's not much point in going through and initializing the arrays to 0 since calloc will already do that for you.
Of course, the easier thing if you know the size of each buffer is going to be the constants would be to put it on the stack (and change you're int sizes to constants):
int ppBuffer[numberOfBuffers][BUFFER_LENGTH] = { 0 };

I think what your asking is for an array of arrays, which isn't what your doing here in the code, rather you've created one array.
Try something like:
#define BUFFER_LENGTH 50
#define numberOfBuffers 10
int** pBuffers;
pBuffers = (int**) calloc(numberOfBuffers, sizeof(int*));
for (int i = 0; i < numberOfBuffers; i++)
pBuffers[i] = (int*) calloc(BUFFER_LENGTH, sizeof(int));
As others said calloc initializes to 0 for you so you don't need to repeat that work. You may need to define int i outside the for loop depending on the version of C you're using.
There are some other things that can be said about style and naming conventions but one step at a time :)

I am very rusty in C, but I think you should change
&pBuffers[i] = 0x00;
to
pBuffers[i] = 0x00;
(The [i] means you are already accessing the item in location i so there is no need to add the &.)
But I might be wrong :-(

Related

How to free pointer to an array of integers

I'm having problems figuring out how to free a pointer to an array of integers, my code is as follow:
int (*gameInfo)[2]; // [0] # of fouls || [1] # of players
gameInfo = (int *)malloc(size * sizeof(int*));
for (int i = 0; i < size; i++) {
memset(gameInfo[i], 0, 2 * sizeof(int));
}
I declare the pointer in the first line, initialize it in the second, and sets all values to 0 inside the for. It works fine.
After I load the new values, and use them I want to free the pointer. I do the following:
for (int i = 0; i < size; i++) {
free(gameInfo[i]);
}
free(gameInfo);
I'm trying to free the arrays first, and then free the pointer. I get a "has triggered a breakpoint" the first time it tries to execute "free(gameInfo[i])".
I've read that the array, since it doesn't have dynamic allocated memory, doesn't need to be free, but if I remove the for and just leave free(gameInfo); it gives the same error.
I've read this in a blog somewhere, so I'm not sure if it's trustworthy.
Thank you!
First, for your stated purposes, the declaration:
int (*gameInfo)[2]; // [0] # of fouls || [1] # of players
Could be:
int *gameInfo[2]; // [0] # of fouls || [1] # of players
Then, allocation for both elements of the array would look like this:
int size = 10; // for example
gameInfo[0] = malloc(size * sizeof(*gameInfo[0]));
gameInfo[1] = malloc(size * sizeof(*gameInfo[1]));
This essentially creates a quantity of space equivalent to that you would have with a 2D int array such as:
int gameInfo[2][10];
After use, free them:
free(gameInfo[0]);
free(gameInfo[1]);
A better option, as mentioned in the comments might be to create a struct:
typedef struct {
int fouls;
int players;
} GAME;
Usage can then include creating, using then freeing an array of games:
GAME *game;
game = calloc(10, sizeof(*game));
...
game[0].fouls = 3;
game[0].players = 2;
...
game[9].fouls = 6;
game[9].players = 3;
...
free(game);
To begin with, you allocate incorrectly. You are using an array pointer, so it should be set to point at an array, not to some fragmented pointer look-up table.
int (*gameInfo)[players]; // [0] # of fouls || [1] # of players
gameInfo = calloc(1, sizeof( int[fouls][players] ));
...
gameInfo[x][y] = something;
...
free(gameInfo);
That's it.
Not only did this turn the code much more readable, it also improves performance drastically.
Further study: Correctly allocating multi-dimensional arrays.
int(*gameInfo)[2];
gameInfo = (int*)malloc(4 * sizeof(int*));
for (int i = 0; i < 2; i++) {
memset(gameInfo[i], 0, 2 * sizeof(int));
}
free(gameInfo);
After some tests, I updated it. The reason lies on nonalignment of memset and malloc. Obviously you applied 2*sizeof(int) memory and memset 2 times of 2*sizeof(int), which is out of the range of 8 byte you applied. Apply 16 byte, in my system fixed the problem. And thanks for #Lundin for reminding me the problem.

Accessing elements in a two dimensional lattice C

Why can I not access Lattice using [ ][ ] without raising a seg fault?
int *LatticeHeight;
int **Lattice;
LatticeHeight = (int*)malloc(Height*sizeof(int));
Lattice = (int**)malloc(Length*sizeof(LatticeHeight));
for(i=0;i<Height; i++)
{
for(j=0; j<Length; j++)
{
Lattice[j][i] = 0;
}
}
I'm interpreting this as;
I have my pointer to one dimensional array of height
Then I set Lattice so that is can store Length-many copies of LatticeHeight (making a grid)
Then I access each element of the lattice and set it's value to 0
Moreover could someone explain why this works in 1D but not in 2D, i.e.
for(i=0;i<Height;i++)
{
LatticeHeight[i] = 0;
}
Does not throw a seg fault
You didn't allocate the array properly. Your first malloc allocates one row; your second malloc allocates space to store a pointer to each row but it does not actually allocate any rows to go in there (and it does not have any association to the single row you allocated earlier, either).
The simplest way to write this code, if you do not require to have rows of different lengths to each other, is to allocate a single memory block:
int (*Lattice)[Length] = calloc( Height, sizeof *Lattice );
If you do want to have a jagged array for some reason (i.e. each row is allocated in a separate memory block) then the code is:
int **Lattice = malloc( Height * sizeof *Lattice );
for ( size_t row = 0; row != Height; ++row )
Lattice[row] = calloc( Length * sizeof **Lattice );
Note that calloc allocates the memory and also zeroes it, so you don't need your zero loop afterwards, and don't cast malloc
I think you should initialize your array like this:
Lattice = (int**)malloc(Length*sizeof(int*));
for(int i = 0; i < Length; ++i) {
LatticeHeight = (int*)malloc(Height*sizeof(int));
}
You have to allocate memory for Lattice which is a pointer to a pointer to int.
Lattice = malloc(Length * sizeof(LatticeHeight));
And then iterate through the "array" of pointers to int that you just have created and allocate memory for each one, like this.
for(i = 0; i < Lenght; i++)
LatticeHeight = malloc(Height * sizeof(int));
With that you would have a two-dimensional "array".
Although, as Matt McNabb said, there are other options for what you want to do.

Trouble allocating memory in 2Darray of a structure

I am trying to develop the TicTacToe game in C and I am using the following structures.The myboard->a member is used to store 'X' or 'O' ,meaning the move a player has made in the same coordinates as the board , ie. 'X' in (1.1) or 'O' (3.1)
typedef struct{
int** a;
int size;
}_board;
typedef _board* board;
board myboard =(board) malloc(sizeof(board));
scanf_s("%d", &(myboard->size));
Size=is the size of the TicTacToe board nxn.
myboard->a =(int**)malloc(myboard->size*sizeof(char *));
if (myboard->a = NULL)
{
printf("ERROR!!!");
}
Until this point everything seems to work but when a try to allocate memory as you see bellow, a get a segmentation fault.
int i;
for (i = 0; j<myboard->size; i++)
{
myboard->a[i] = malloc(sizeof(char));
if (myboard->a[i] == NULL)
{
printf("ERROR");
}
}
I am using free for its malloc at the end of me program.
Thanks, in advance for any answer , and sorry for my bad english. Any help is apreciated.
I don't really understand why you are using a int** variable for storing your board data, when you could just use one simple int*, which you could later assign with malloc(3) as in:
int* b_data;
int b_size = 9;
b_data = malloc(b_size * sizeof(int));
// ... Your code
free(b_data);
If however, you really want to use a int** variable, you could do something like:
int** b_data;
int b_size_x = 3;
int b_size_y = 3;
int i;
b_data = malloc(b_size_x * sizeof(int*));
for(i = 0; i < b_size_x; i++)
*(b_data + i) = malloc(b_size_y * sizeof(int));
// ... Your code where you access your array of size_x containing
// arrays of size_y of int typed "cells"
for(i = 0; i < b_size_x; i++)
free(*(b_data + i));
free(b_data);
But this is really unnecessarily complicated, and I would dis-advise from doing so unless for learning purposes: in most cases, the allocated memory will be contiguous, so the second solution will allocate a nearly identical structure in memory, but will be less efficient (the "2D" array solution takes b_size_x times sizeof(int*) more memory), and the first solution will be simpler to read/write (so less prone to bugs, and easier to maintain).
Concerning your code, your problem is that myboard->a is NULL right after the "check" (which is in fact an allocation - note that the "ERROR" is never shown because myboard-> is then NULL, which evaluate to 'false'.):
if (myboard->a = NULL)
which should be:
if (myboard->a == NULL)
In addition, as pointed by #WhozCraig in his comment on your post, you might want to use i in the condition of your for loop, rather than j; and you also probably want to use int and int* types rather than char and char* types respectively in your malloc(s), since the a member of the board structure is an int**. Oh and also, think about putting newlines after your printf(3) strings, or use puts(3).

Is this code doing what I want it to do?

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.

How to declare an array with an arbitrary size

Ok, this is a C programming homework question. But I'm truly stuck.
I ask the user to input words, and then I insert the input into an array, but I can't have any control over the number of words the user types.
I guess what I'm asking is how do you declare a an array in C without declaring its length and without asking the user what the length should be.
I know this has something to do with malloc, but if you could give me some examples of how to do this, I would really appreciate it.
You can malloc a block of memory large enough to hold a certain number of array items.
Then, before you exceed that number, you can use realloc to make the memory block bigger.
Here's a bit of C code that shows this in action, reallocating an integer array whenever it's too small to hold the next integer.
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int *xyzzy = NULL; // Initially NULL so first realloc is a malloc.
int currsz = 0; // Current capacity.
int i;
// Add ten integers.
for (i = 0; i < 10; i++) {
// If this one will exceed capacity.
if (i >= currsz) {
// Increase capacity by four and re-allocate.
currsz += 4;
xyzzy = realloc (xyzzy, sizeof(int) * currsz);
// Should really check for failure here.
}
// Store number.
xyzzy[i] = 100 + i;
}
// Output capacity and values.
printf ("CurrSz = %d, values =", currsz);
for (i = 0; i < 10; i++) {
printf (" %d", xyzzy[i]);
}
printf ("\n");
return 0;
}
You can realloc it every time like:
int size = 0;
char **array = malloc(0);
while(/* something */)
{
char *string = // get input
size++;
array = realloc(array, size * sizeof(char*));
array[size - 1] = string;
}
Or in chunks if you care about speed.
Yes, you want malloc. Checkout this tut.
http://www.cprogramming.com/tutorial/dynamic_memory_allocation.html
This site is good in general for learning.
Here is an example of using realloc, it is basically exactly what you are asking to do.
http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
0) obviously you will need multiple buffers, so you will need a list like structure: perhaps a record with char array 100 chars and a pointer to next structure
1) You need to capture the words char by char and store them in your buffer
2) once the buffer is full you allocate another record, chain it with the previous one and keep going until you are out of mem or the process is over.
That should be better performance than realloc function. I believe malloc is trying to give contious block of memory. Therefore the list like structure will be faster and work better.

Resources