C - Struct- Integer to a pointer without cast - c

So I'm having a bit of trouble figuring out what is going on when I malloc an array that is a member of the struct?
The following error message occurred :
"assignment makes integer from pointer without a cast".
It would be greatly appreciated if someone can help me see where I went wrong in the malloc.
typedef struct _big_num {
int nbytes; // size of array
Byte *bytes; /// array of Bytes
} BigNum;
void initBigNum(BigNum *n, int Nbytes)
{
int i;
n->nbytes = Nbytes;
for (i = 0; i < Nbytes; i++) {
n->bytes[i] = malloc(sizeof(Byte)); //This is where the error came up
n->bytes[i] = 0;
assert(n->bytes[i] == 0);
}
return;
}

n->bytes[i] is of type Byte, it's a single element in the "array". The malloc call returns a pointer.
You don't allocate the array itself, but instead try to allocate each element separately, which isn't how it works. Besides the compiler message, n->bytes may not point to a valid location, making the dereference n->bytes[i] invalid for any index.
You probably want
void initBifNum(BigNum *n, int NBytes)
{
// Initialize members and allocate memory for array
n->nbytes = NBytes;
n->bytes = malloc(sizeof *n->bytes * NBytes);
// Initialize all elements in the array to zero
memset(n->bytes, 0, sizeof *n->nbytes * NBytes);
}

n->bytes[i] is really *n->(bytes+i). So you're assigning the memory address returned by malloc to type Byte instead of to a pointer.
It's worth pointing out that in the very next line, you assign 0 to n->bytes[i], even though you just attempted to assign it an address. If you're trying to allocate memory that's set to 0, just use calloc - it allocates memory and sets it to 0 for you.

Related

How to pass an array with unknown 1-d dimension into function in C

I try something like below but all the time I have a segmentation fault.
I don't really want to use (e.g.) #define N 1000 and then declare int buffer[N].
Just in case..I'm not allowed to use any headers except stdio.h as well as dynamic memory.
void input (int *buffer, int *length);
int main()
{
int length, *buffer = NULL, *numbers = NULL;
input(buffer, &length);
}
void input(int *buffer, int *length) {
scanf("%d", length);
if (*length < 0) {
error = 1;
return;
}
for (int i = 0; i < *length; i++) {
scanf("%d", *buffer[i]);
}
}
How to pass an array with unknown 1-d dimension into function
In C, arrays cannot exist until their size is known.
There are other approaches though.
In C, code cannot pass an array to a function. some_function(some_array) converts the array some_array to the address of the first element of the array: &some_array[0]. That is what the function receives, a pointer, not an array. The original size information of the array is not passed, thus also pass the length to the function.
Sample:
Read desired length.
{
int length = 0;
scanf("%d", &length);
Form a variable length array, length >= 1.
if (length <= 0) {
return NULL;
}
int buffer[length];
Now call a function, passing the length and the address of the first element of the array.
// Do stuff with length and buf, like read data
foo1(length, buffer);
// foo1() receives the length & address of the first element of the array as an int *
// Do more stuff with length and buf, like write data
foo2(length, buffer);
}
At the end of the block }, buffer no longer available.
In C, you can't create an array if you can't know its size at compile time (or at least not in certain implementations and standards), so doing something like buffer[length] won't work (again at least not in certain implementations/standards).
What you need to do to make sure this works everywhere is to use a pointer (as I see you're trying to use here). However, what you're doing wrong here that causes your segfault with the pointers is you assign them the value of NULL. This also won't work due to how when you assign a pointer an arbitrary value, there is no memory allocated for the pointer (This applies for everything other than addresses of "regular" variables using the & operator and assigning other pointers that are checked to be OK). Your pointers are just pointing to address 0 and can't be used for anything.
What you need to do here to fix the pointers is to use dynamic memory allocation, so you can have a truly variable-sized array. Specifically, you need to use a function like malloc or calloc to allocate memory for the pointers so they are usable. In your case, using calloc and reading its documentation, we see that it takes 2 parameters: The number of elements it should allocate memory for and the size of each element. We also know that it returns a pointer to the starting address of the allocated memory and that in case of failure (which can only happen if you're out of memory), it returns NULL. Using this, we understand that in your case the call to calloc would be like this:
int *buffer = (int *) calloc(length, sizeof(int));
The sizeof() function returns the size of a data type in bytes. Here you allocated enough memory for the pointer to hold length integers (since you'll use it as an array you need enough memory for all the integers, you're not just pointing to 1 integer but storing all of them), and calloc is also noted to initialize every allocated element to 0, so you have an array of integers that are all initialized to 0 (Also note that type casting has been used to make sure the allocated memory block is appropriate for use with an integer array, you can read more about type casting in this small article from Tutorialspoint if you'd like). Then, after this has been allocated, you can start reading your integers into the array. The complete code looks like this:
void input (int *buffer, int *length);
int main() {
// NOTE: I don't see the numbers pointer used here, maybe remove it?
int length, *buffer, *numbers;
input(buffer, &length);
}
void input(int *buffer, int *length) {
scanf("%d", length);
if (*length < 0) {
// Consider printing the exact error here
error = 1;
return;
}
buffer = (int *) calloc(length, sizeof(int));
if (buffer == NULL) {
printf("Couldn't allocate memory for buffer\n");
error = 1;
return;
}
// Accessing the elements of an array doesn't need * and in fact * here can (and probably will) cause terrible things
for (int i = 0; i < *length; i++) {
scanf("%d", buffer[i]);
}
}
Also don't forget to call free() on the pointer after you're done using it to avoid memory leaks (in your case that'd be after the call to input()).
Hope this helped, good luck!
You cannot use arrays because their memory size must be known to the compiler at compile time. Also you can't use Variable Length Arrays because they are allocated at the point of declaration and deallocated when the block scope containing the declaration exits.
The solution to your problem might be to use malloc

using sizeof(void) inside malloc

I'm a beginner in C and I'm facing this problem: I created a function based on the fast matrix allocation method (Oliveira and Stewart, "Writing Scientific Software", pag. 94) and I want to use it for any data type.
I therefore changed it a bit as follows:
void ** malloc_array2d(size_t m, size_t n){
/* pointer to array of pointers */
void ** pointer;
size_t i;
/* allocate pointer array of length m */
pointer = malloc(m*sizeof(void));
if(pointer == NULL){
return NULL;
}
/* allocate storage for m*n entries */
pointer[0] = malloc(m*n*sizeof(void));
if (pointer[0] == NULL) {
free(pointer);
return NULL;
}
/* set the pointers */
for (i = 1; i < m; i++) {
pointer[i] = pointer[0] + i*n;
}
return pointer;
}
but I get segmentation fault.
The question is: how to allow for memory allocation of different data type, since sizeof(void) is not working (and indeed it returns just 1)?
Any feedback is really appreciated.
Thanks.
void is not the matching type of what pointer references. pointer references void *, not void.
Avoid the mistake in the future by not coding the size of the referenced type, but coding the size of the de-referenced pointer.
// pointer = malloc(m*sizeof(void));
pointer = malloc(sizeof *pointer * m);
For the next allocation, sizeof(void) * m *n is not well defined. Code needs a new approach.
// pointer[0] = malloc(m*n*sizeof(void));
To allocate for various types, pass in the size of the data type.
void ** malloc_array2d(size_t m, size_t n, size_t data_size){
...
unsigned char *p = malloc(data_size * m *n);
...
for (i = 0; i < m; i++) {
pointer[i] = p + i*n*data_size;
}
Sizeof returns the quantity of bytes that every datatype are. 1 for byte, 2 for int16, 4 for int32, etc... You can then pass it as parameter, with any kind of problem, as at the moment of use of malloc_2darray function you should know final datatype to map to.
Note that always you use your malloc_2darray function you should cast to final datatype pointer for a correct interpretation of returned pointers.
Firstly the value of the sizeof(void) is always 1, here void refers to pointer memory allocation for untyped datatype. I don't think any other datatype takes that much less memory. Well int, float, etc consumes more bit of data. If you want the value of sizeof() to return 1, You can just manually specify the size in malloc() function instead of using sizeof() functionalities along with different datatypes.

How to differentiate empty and 0 in an int array in C?

I'm a beginner of C and now I'm learning pointer and dynamic memory allocation. I want to write a simple program to create empty arrays and check for the existence of a given number. Here's my code:
/* create an empty array pointer */
int* createArray(){
int *a = (int*) malloc(sizeof(int));
return a;
}
void findArrayElement(int *list, int element){
int i;
int len = (sizeof(list) / sizeof(int));
if (sizeof(list) == 0) {
printf("NO\n");
return;
}
for (i=0; i<len; i++) {
if (list[i] == element) {
printf("YES\n");
return;
}
}
printf("NO\n");
}
int main(int argc, const char * argv[]) {
int *p;
p = createArray();
printf("size of int is: %lu\n", sizeof(int));
printf("size of p is: %lu\n", sizeof(p));
printf("LENGTH of p is: %lu\n", ARRLENGTH(p));
findArrayElement(p, 2);
findArrayElement(p, 0);
return 0;
}
But when I run the program, I always get 'YES' when I looking for 0, so
Is there a way to differentiate integer 0 and a complete empty array?
Also I'm not sure whether my function createArray() is a correct way to create an empty array.
Thanks guys.
Is there a way to differentiate integer 0 and a complete empty array?
How do you define an empty array? Once you allocate a memory chunk and assign it to a pointer, it already has some value (which is undefined in case of alloc). The most used way to mark a pointer as not used or not allocated os to assign NULL to it.
Also I'm not sure whether my function createArray() is a correct way to create an empty array.
sizeof returns the number of bytes which the given object (or type) occupies in the memory. In your case sizeof(list) returns 8 as it is a pointer.
In oder to allocate an array, the function has to receive its size. Currently it always allocates size for one integer only.
Edit: Adding example.
/* create an empty array pointer */
int* createArray(size_t size)
{
return (size ? (int*) malloc(sizeof(int)*size) : NULL);
}
So now the returned pointer should be 'coupled' with the size of the array. Which means that each function that receives an array as a parameter should receive also its size.
sizeof returns the memory size of the array pointer, regardless of contents.
edit: if it exists in memory, it will be nonzero.
edit 3: removed inaccurate information, see the comments about creating a variable to record the length. Also from comments, note that your createArray function is creating an array for exactly 1 integer. In C, arrays are of fixed length. So this Array will always be the same size (whether you stored something in it or not). sizeof(pointer) will always return the memory allocated for the pointer, not the memory allocated for the array at which it is pointing.

Segmentation fault when initialization array

I have a structure called string
typedef struct {
char *s;
int len;
} string_t;
typedef struct {
uint32_t numb;
} msg_t;
where in the function
void myfunct()
{
msg_t msg;
memset(&msg, 0, sizeof(msg));
msg.numb = 1;
char *ClientSendBuf[sizeof(msg)];
string_t buffer = {ClientSendBuf[sizeof(msg)],strlen(ClientSendBuf[sizeof(msg)])};
}
Tried to initialize an array (basically a buffer that I need to send later on) using UDP,
but it gives me an error of segmentation fault (on the third line in void myfunct.
So the thing with buffer is that it should be a type of string_t, how can I fix this segmentation fault?
P.S. I forgot to mention, I want to copy the whole structure to the buffer variable (that should be type string_t) using memcopy. So am I doing the wrong thing above? How can I do this?
There are a few things you have to consider in initializing your structure, as it has a pointer member char *s simple assignment will not work. Simple assignment will just copy the pointer address and not the content it is pointing to.
There are a few problems in your assignment code:
1. You declared an array of char * with sizeof(msg) elements, none of which are allocated memory; but your structure need char * and not char *[]
2. You are accessing an array element which is out of bounds (ClientSendBuf[sizeof(msg)]) and also not pointing to any valid address.
You can create a simple char array & copy it to the structure. As you are using a pointer member it is your responsibility to allocate memory and free memory.
Hope the code below can provide you with some references:
void myfunct()
{
msg_t msg;
memset(&msg, 0, sizeof(msg));
msg.numb = 1;
char ClientSendBuf[] = "This is my message";
string_t buffer = {
strdup(ClientSendBuf), /*Can return NULL so add error check*/
strlen(ClientSendBuf)
};
/** Or **/
string_t buffer;
buffer.s = malloc(strlen(ClientSendBuf)+1);
if(NULL == buffer.s)
{
/* Memory allocation failed. Handle error.*/
}
/* Zero fill */
memset(buffer.s, 0, strlen(ClientSendBuf)+1);
strcpy(buffer.s, ClientSendBuf);
buffer.len = strlen(ClientSendBuf);
/*Opeartions with buffer*/
/*Call free in both cases !*/
free(buffer.s);
}
Hope this help!
ClientSendBuf - put some thing in it and also put it on the heap.
The problem is that you don't allocate memory to any element of ClientSendBuf. You should use malloc here to first allocate the memory.
I see two things that are wrong. First, accessing ClientSendBuf[sizeof(msg)] is undefined behavior, because that character is after the end of CliendSendBuf. Then you're assigning a char (namely ClientSendBuf[sizeof(msg)]) when a char * is expected.
And if you want to use buffer outside that function you have to put ClientSendBuf on the heap, because it will be overwritten by other stack frames after you exit (i.e. sort of deleted), so the pointed data will be throwed off.
Now, since you want a copy of the whole ClientSendBuff, you need an array of string_t. Then, you assign every pointer in ClienSendBuff to buffer:
char *ClientSendBuff[sizeof(msg)];
string_t buffer[sizeof(msg)];
int i;
for(i = 0; i < sizeof(msg); i++) {
ClientSendBuff[i] = malloc(100); // you have to initialize (and free when
buffer[i].s = ClientSendBuff[i]; // you don't need them anymore) every pointer
buffer[i].len = 100;
}
But I'm not sure if I got your point. How can a char * [] fit in a char*?

How to make the bytes of the block be initialized so that they contain all 0s

I am writing the calloc function in a memory management assignment (I am using C). I have one question, I wrote the malloc function and thinking about using it for calloc as it says calloc will take num and size and return a block of memory that is (num * size) which I can use malloc to create, however, it says that I need to initialize all bytes to 0 and I am confused about how to do that in general?
If you need more info please ask me :)
So malloc will return a pointer (Void pointer) to the first of the usable memory and i have to go through the bytes, initialize them to zero, and return the pointer to that front of the usable memory.
I am assuming you can't use memset because it's a homework assignment assignment, and deals with memory management. So, I would just go in a loop and set all bytes to 0. Pseudocode:
for i = 1 to n:
data[i] = 0
Oh, if you're having trouble understanding how to dereference void *, remember you can do:
void *b;
/* now make b point to somewhere useful */
unsigned char *a = b;
When you need to set a block of memory to the same value, use the memset function.
It looks like this: void * memset ( void * ptr, int value, size_t num );
You can find more information about the function at: http://www.cplusplus.com/reference/clibrary/cstring/memset/
If you can't use memset, then you'll need to resort to setting each byte individually.
Since you're calling malloc from your calloc function, I'm going to assume it looks something like this:
void *calloc (size_t count, size_t sz) {
size_t realsz = count * sz;
void *block = malloc (realsz);
if (block != NULL) {
// Zero memory here.
}
return block;
}
and you just need the code for "// Zero memory here.".
Here's what you need to know.
In order to process the block one byte at a time, you need to cast the pointer to a type that references bytes (char would be good). To cast your pointer to (for example) an int pointer, you would use int *block2 = (int*)block;.
Once you have the right type of pointer, you can use that to store the correct data value based on the type. You would do this by storing the desired value in a loop which increments the pointer and decrements the count until the count reaches zero.
Hopefully that's enough to start with without giving away every detail of the solution. If you still have problems, leave a comment and I'll flesh out the answer until you have it correct (since it's homework, I'll be trying to get you to do most of the thinking).
Update: Since an answer's already been accepted, I'll post my full solution. To write a basic calloc in terms of just malloc:
void *calloc (size_t count, size_t sz) {
size_t realsz, i;
char *cblock;
// Get size to allocate (detect size_t overflow as well).
realsz = count * sz;
if (count != 0)
if (realsz / count != sz)
return NULL;
// Allocate the block.
cblock = malloc (realsz);
// Initialize all elements to zero (if allocation worked).
if (cblock != NULL) {
for (i = 0; i < realsz; i++)
cblock[i] = 0;
}
// Return allocated, cleared block.
return cblock;
}
Note that you can work directly with char pointers within the function since they freely convert to and from void pointers.
Hints:
there is already a posix library function for zeroing a block of memory
consider casting the void * to some pointer type that you can dereference / assign to.

Resources