Structs in C Error [closed] - c

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 7 years ago.
Improve this question
I don't understand why the following code doesn't work:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
struct data
{
int age;
char name[20];
};
int main()
{
struct data element[2];
for (int j = 0; j < 2; j++)
{
element[j] = (struct data) malloc(sizeof(struct data));
printf("Enter fav number%d? \n", j);
scanf("d", &element[j].age);
printf("Enter fav word? \n");
scanf("s", &element[j].name);
}
printf("\nThis is what you entered:\n");
for (int k = 0; k < 2; k++)
{
printf("%d. Fav number: %d\n", k, &element[k].age);
printf("%d. Fav word: %s\n", k, &element[k].name);
}
return 0;
}
The compiler error says:
beispiele.c: In function ‘main’:
beispiele.c:199:51: error: conversion to non-scalar type requested
element[j] = (struct data) malloc(sizeof(struct data));
^
beispiele.c:201:3: error: too many arguments for format [-Werror=format-extra-args]
scanf("d", &element[j].age);
^
beispiele.c:203:3: error: too many arguments for format [-Werror=format-extra-args]
scanf("s", &element[j].name);
^
beispiele.c:208:3: error: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘int *’ [-Werror=format=]
printf("%d. Fav number: %d\n", k, &element[k].age);
^
beispiele.c:209:3: error: format ‘%s’ expects argument of type ‘char *’, but argument 3 has type ‘char (*)[20]’ [-Werror=format=]
printf("%d. Fav word: %s\n", k, &element[k].name);
^
cc1: all warnings being treated as errors

element[j] is not a pointer and is a member of the array so already it has memory allocated statically.
If you need to allocate memory then have array of pointers.
struct data *element[2];

There is no need for using malloc (the array allocates all the memory).
Note, using printf does not require the address of the variable, so the & must be omitted before the variable. You do with scanf, as you must pass the address of the variable to which you want to write so that it can be modified (note the %d and %s in the scanf too). However, with the char[20], you do not need the & as the array is a pointer to the begin of the sequence of 20 characters.
int main()
{
struct data element[2];
for (int j = 0; j < 2; j++)
{
printf("Enter fav number%d? \n", j);
scanf("%d", &element[j].age);
printf("Enter fav word? \n");
scanf("%s", element[j].name);
}
printf("\nThis is what you entered:\n");
for (int k = 0; k < 2; k++)
{
printf("%d. Fav number: %d\n", k, element[k].age);
printf("%d. Fav word: %s\n", k, element[k].name);
}
return 0;
}

You have several problems:
Format specifiers start with a % sign. So change
scanf("d", &element[j].age);
to
scanf("%d", &element[j].age);
and
scanf("s", &element[j].name);
to
scanf("%s", element[j].name);
Wondering why I removed the & from the above scanf? It is because array names gets converted to a pointer to its first element.
These
printf("%d. Fav number: %d\n", k, &element[k].age);
printf("%d. Fav word: %s\n", k, &element[k].name);
should be
printf("%d. Fav number: %d\n", k, element[k].age);
printf("%d. Fav word: %s\n", k, element[k].name);
because the %d in the printf expects the value(int) and not the address of the variable(int*). Similarly, %s expects a char*, not a char(*)[20]
The cast here is completely wrong and should be removed:
element[j] = (struct data) malloc(sizeof(struct data));
This is done because malloc returns void* which can be assigned to any pointer type without casting.
etc See other answers.

You're getting 3 types of errors:
beispiele.c:199:51: error: conversion to non-scalar type requested
element[j] = (struct data) malloc(sizeof(struct data));
Check the documentation for malloc - it returns a void pointer to the allocated memory, which you then try to cast to a struct. The struct is obviously not a pointer type, hence the error message.
To be precise, the error message tells you that you're trying to cast to a type that is not scalar (roughly and incorrectly speaking, that is not a "basic" language type). C-style cast is very permissive and would happily perform many casts, for example, a long long * to a long long, without even a warning.
Keep in mind that you should not cast the pointer you get from malloc.
Also, as others have pointed out, this statement:
struct data element[2];
declares and automatically allocates the element variable. By calling malloc, you're asking the compiler to allocate it again, dynamically. If you're confused about memory allocation, take a look here.
beispiele.c:201:3: error: too many arguments for format [-Werror=format-extra-args]
scanf("d", &element[j].age);
Format strings used by scanf and printf use format specifiers starting with the % symbol, which is missing in all your calls. In this specific call, your format string "d" contains 0 format specifiers, so scanf expects 0 variable addresses to store values in. But you provide 1 address, so the compiler complains for "too many arguments".
Also, note that scanf needs a the address of a variable because arguments are passed by value - if it took the variable itself instead, it couldn't store the data to be accessible after the scanf call returned. By contrast, printf does not need to modify variables, so it takes variables rather than their addresses.
^ beispiele.c:208:3: error: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘int *’ [-Werror=format=]
printf("%d. Fav number: %d\n", k, &element[k].age);
This error message is pretty self-explanatory. Refer to the previous point about printf's arguments.

malloc returns a pointer to the allocated data, not the actual data. You should not cast the result of malloc.
Fix the code accordingly:
struct data* element[2];
...
element[j] = malloc(sizeof(struct data));
...
free(element[j]);

malloc returns a pointer to allocated memory, but you cast the pointer to a struct data. This is what the compiler complains about
error: conversion to non-scalar type requested
Furthermore, you don't need to allocate memory at all, because you already did so by
struct data element[2];
So, when you drop the malloc line, this error should be gone.

Related

error: invalid type argument of unary '*' (have 'long int')

I need to read the contents of the stack after executing a function
since I know the highest and lowest address on the stack, I tried to read the contents of the stack
I creat this function into the code
int pile_start =0xd0000890;
int size =0x1890;
void read_stack()
ptrdiff_t i;
for ( i = pile_start; i < size; i++) {
printf("pile = %d", *(pile_start+i)); // error
}
but I had this error :
error: invalid type argument of unary '*' (have 'long int')
can be the way how I read the contents of the stack is not correct
I need your help please
The error message is clear enough. You are trying to apply the indirection operator to an object of the type long int
printf("pile = %d", *(pile_start+i));
^^^^^^^^^^^^^^^
Maybe you mean just
printf("pile = %ld", (pile_start+i));
Or you need to cast the variable pile_start to a pointer as for example
printf("pile = %d", *( unsigned char * )(pile_start+i));
printf("pile = %d", *(pile_start+i));
Here pile_start is a a number - an int, I am assuming i is a number as well as you are using it as index in for loop. (pile_start+1) results in datatype int and value at int is invalid.
To use "*", you need to have a pointer. So first convert (pile_start+1) to pointer and then read value at that location.
If you change your code to
printf("pile = %d", *(uint32_t*)(pile_start+i));
It should show contents at that address.

Problems with local pointer array

I've done some digging around but cant find the solution. In my code below, when I declare my float **array as a global variable my program runs as intended. However I'm attempting to declare it in main() and pass it into functions and I'm getting some nasty errors when I try to compile.
Sample run below:
lab2.c: In function ‘NumOfVal’:
lab2.c:116: error: incompatible types when assigning to type ‘float’ from type ‘void *’
lab2.c:118: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:119: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:124: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:125: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘calculateSum’:
lab2.c:137: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:140: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘calculateAvg’:
lab2.c:150: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:153: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘findMax’:
lab2.c:162: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:165: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:166: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘findMin’:
lab2.c:174: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:175: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:177: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:178: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c: In function ‘printVal’:
lab2.c:187: error: invalid type argument of ‘unary *’ (have ‘float’)
lab2.c:189: error: invalid type argument of ‘unary *’ (have ‘float’)
Now I realize the errors for my "calculation functions" are all the same and but the first error at line 116 is different. I don't understand why once I declare my pointer locally in main(), it gives me all these problems. I have to use pointer arithmetic and don't see how the statement:
*(array + index) = malloc();
Is no longer valid..
Why does a local declaration change the syntax for allocating memory and reading from/writing to an array??
Code below: Im not including some of the "calculation functions" to save space
/* Function declarations */
void printVal();
void userChoice();
void calculateSum();
void calculateAvg();
void findMin();
void findMax();
int main(){
float **array;
int numData;
/*get number of datasets */
numData = NumOfSet();
printf("%d\n",numData);
array = malloc(numData * sizeof(float*));
if(array != 0){
/* get # of values per dataset and enter those values */
NumOfVal(numData, array);
}
else{
printf("Memory Allocation Failed");
}
userChoice();
}
void userChoice(){
int flag = 1;
int setChoice;
int opChoice;
while(1){
if(flag == 0)
break;
printf("Which dataset would you like to perform operations on?: \n");
scanf("%d", &setChoice);
printf("Which operation would you like to perform on dataset #%d\n", setChoice);
printf("1. Calculate sum of all the values\n");
printf("2. Calculate average of all the values\n");
printf("3. Find the minimum value\n");
printf("4. Find the maximum value\n");
printf("5. Print values in dataset\n");
printf("6. Exit the program\n");
scanf("%d", &opChoice);
/* Switch statement which makes function calls to perform whatever the user specified */
switch(opChoice){
case 1:
calculateSum(setChoice);
break;
case 2:
calculateAvg(setChoice);
break;
case 3:
findMin(setChoice);
break;
case 4:
findMax(setChoice);
break;
case 5:
printVal(setChoice);
break;
case 6:
flag = 0;
printf("Thanks for playing!\n");
printf("%d", flag);
}
}
}
int NumOfSet(){
int numData;
printf("Enter number of Datasets: \n");
scanf("%d",&numData);
return(numData);
}
/* for each data set declare size and input float values */
int NumOfVal(int data, float *array){
int index; /* counters */
int array_index;
int copy;
float size;
float val;
for(index = 0; index < data;index++){
printf("Enter size of dataset %d:\n", index);
scanf("%f", &size);
copy = size;
printf("Size = %d\n", (int) size);
printf("Array #: %d\n", index);
/* malloc() for row */
/* array[index] */
*(array + index) = malloc(size * sizeof(float));
/*array[index][0] */
*(*(array + index) + 0) = size;
printf("%f\n", *(*(array + index) + 0));
/* loop for entering float values */
for(array_index = 1; array_index <= copy; array_index++){
printf("Enter each float value:");
scanf("%f", &val);
*(*(array + index) + array_index) = val;
printf("%f\n", *(*(array + index) + array_index));
printf("count: %d\n",array_index);
printf("size: %d\n",copy);
}
}
}
void calculateSum(int setChoice, float *array){
int i;
int first = *(*(array + setChoice-1) + 0);
float sum = 0;
for(i = 1; i <= first; i++){
sum += *(*(array + setChoice-1) + i);
}
printf("The sum of the values is: %.3f\n", sum);
}
P.S. Of course, when I had declared array as global, I didn't have array as a parameter of those functions.
So it seems if I declare pointer to a pointer to a float float **array in main(). I need to have float **array as the parameter of my functions and not just float *array.
**array --> a pointer which points to a list of float arrays(?)
*array --> simply a pointer to a single float array(?)
correct me if I'm wrong please
First you've got to understand what pointers are. A pointer is variable which
stores an address. It may be the address of another variable, it may be the
start of a memory block that you've got from dynamically allocating memory with
malloc & friends or the start of an array.
*array --> simply a pointer to a single float array(?)
Not necessarily.
Let's take a look at this:
float *array;
First, forget about the name of the variable, what really is important is the
type of the variable. In this case you've got a pointer to a float.
It may point to a single float variable
float n = 8.7;
float *array = &n;
but it also may point to the start of a sequence of floats (aka array):
float na[] = { 1.1, 2.2, 3.3, 4.4 };
float *array = na;
//or
float *array = na + 2;
Which one (pointing to a single object vs pointing to an array of objects) is the
correct one depends on the context. The documentation of the function will tell
you what it is expecting. That is what counts, not the variable name. If the
variable name is array, it may not be pointing to an array, the name is then
misleading, actually is a poorly chosen name.
**array --> a pointer which points to a list of float arrays(?)
Again, not necessarily.
Let's take one step further. A double pointer
float **array;
is a pointer that points to another pointer of float. Once again, forget about
the name of the variable, the context is important. It may point to a pointer
that points to a single variable:
float n = 8.7;
float *array = &n;
float **p2arr = &array;
or it may point to a pointer that points to the start of an array
float na[] = { 1.1, 2.2, 3.3, 4.4 };
float *array = na;
float **p2arr = &array;
// *p2arr[0] == 1.1
// *(p2arr[0] + 1) == 2.2
// *(p2arr[0] + 2) == 3.3
or it may point to an array of pointers that point to a single float values:
float a=1.1, b=2.2, c=3.3;
float **ppa = calloc(3, sizeof *ppa);
ppa[0] = &a;
ppa[1] = &b;
ppa[2] = &b;
or it may point to an array if pointers that point to an array of float
values:
float **ppa = calloc(3, sizeof *ppa);
ppa[0] = calloc(5, sizeof *ppa[0]);
ppa[1] = calloc(2, sizeof *ppa[1]);
ppa[2] = calloc(9, sizeof *ppa[2]);
ppa[0][0] = 1.1;
ppa[0][1] = 2.2;
ppa[1][0] = 10.8;
ppa[2][5] = 11.1;
The context matter, and if you are using a function that has a float **arg
argument, the function documentation will tell you what it will expect from such
a pointer. If you are creating a function, you decide the context,
because you know what you are working with.
So about your code. As far as I can see, float **array; in main allocates
memory for an array of pointers. I'd suggest in this case to use calloc
instead, because calloc sets the allocated memory to 0. It makes initializing
and freeing the whole block easier even if subsequent calls of
malloc/realloc/calloc fail.
array = calloc(numData, sizeof *array);
Also note that I'm not using the sizeof(float*) here but instead sizeof *array.
The former is not incorrect, but it is easier to make mistakes like forgetting
the * or adding more than needed, specially when
dealing with double pointer. The later however will always return the correct
size, regardless of the type.
Now you're array is allocated and initialized. All pointers array[0],
array[1], etc are initialized and point to NULL. The you call
NumOfVal(numData, array); and that's where all goes wrong.
Let's see the signature of the function:
int NumOfVal(int data, float *array);
It expects a single pointer, so that's not good, you cannot pass the double
pointer. Since you are writing the function yourself, you can change the
function and set your own context.
Before fixing the function, let's look at this line in NumOfVal:
*(array + index) = malloc(size * sizeof(float));
Again here, I'd suggest using calloc. Second let's take look at this:
*(array + index). It is the same as doing array[index] and will return you
a float. You are essentially doing:
float f = malloc(sizeof * sizeof(float));
This is just wrong, because malloc returns a void pointer, you cannot set a
float to a void pointer.
But also you train of thoughts are wrong here, because the array variable in
main is a double pointer, the memory layout is different. Why?
I will changed the name of the variable, to make it clear which variable I'm referring to.
*(array_main + index) is the same as doing array_main[index]. It returns you
a pointer to float. When you pass array_main to NumOfVal, you are now
treating it like a single pointer. The size of a float and the size of a
pointer to float might not be the same, so array_main + index and array + index will return you a
different memory location. In fact it will return you a memory location where a
pointer is saved, not where the float is saved, so you are destroying the
pointers saved in array_main.
pfs = sizeof(float*)
fs = sizeof(float)
real address base base+pfs base+2*pfs base+3*pfs
pointer arithmetic base base+1 base+2 base+3
+---------+----------+----------+
| float* | float * | float * |
+---------+----------+----------+
real address base base+fs base+2*fs base+3*fs
pointer arithmetic base base+1 base+2 base+3
+-----------+-----------+-----------+
| float | float | float |
+-----------+-----------+-----------+
The graph above shows you the same memory address base seen as a
float** (top) and seen as a float* (bottom). Basically the top representation
is what you have for array in main. The bottom one is what you have for
array in NumOfVal. You see the pointer arithmetic doesn't line up and so you
are accessing the incorrect memory locations and that yields undefined
behaviour.
How to fix it? Fix the NumOfVal like this:
int NumOfVal(int data, float **array) {
int index; /* counters */
int array_index;
int copy;
float size;
float val;
for(index = 0; index < data;index++){
printf("Enter size of dataset %d:\n", index);
scanf("%f", &size);
copy = size;
printf("Size = %d\n", (int) size);
printf("Array #: %d\n", index);
/* malloc() for row */
/* array[index] */
array[index] = calloc(size + 1, sizeof *index);
array[index][0] = size;
I see you want to use the first element to save the size. It's a nice strategy,
but you need to allocate one more element because of this, otherwise you for
loop will overflow.
You have the same problem in calculateSum, same fix:
void calculateSum(int setChoice, float **array){
int i;
int first = array[setChoice-1][0];
float sum = 0;
for(i = 1; i <= first; i++){
sum += array[setChoice - 1][i];
}
printf("The sum of the values is: %.3f\n", sum);
}
Never forget to check the return value of malloc & friends, if they return
NULL, you cannot access that memory. Also write a function that frees the
memory. Here calloc comes in handy because free(NULL); is legal.
void free_array(int size, float **array)
{
if(array == NULL)
return;
for(int i = 0; i < size; ++i)
free(array[i]);
free(array);
}
In your NumOfVal function you should do:
array[index] = calloc(size + 1, sizeof *index);
if(array[index] == NULL)
{
// error handling
return 0;
}
Also you are forgetting to return a value in NumOfVal. If your function is not
going to return a value anyway, declare it as void.
Now in main after doing your calculations:
free_array(numData, array);
to free the memory.

C - Pointers within struct not affecting the code

I am trying to understand why this code works
#include<stdio.h>
struct identity {
int age;
char name[20];
} test;
int main(void) {
printf("Enter name: ");
scanf("%s", &test.name);
printf("Enter age: ");
scanf("%d", &test.age);
printf("NAME: %s", test.name);
printf("\nAGE: %d", test.age);
}
even if I define the struct this way:
struct identity {
int *age;
char *name[20];
} test;
No matter how I write it, it works. I can understand that it works this way, but why does it work if I use the pointers?I mean, shouldn't it require printf("NAME: %s", *test.name); and printf("\nAGE: %d", *test.age); so as to print the value held inside the address of test.name and test.age respectively?
Is this a wrong way to use pointers within a struct? Therefore it works because I actually don't use pointers?
Its because when you put * your age works as an array, and char name[20] works as 2D array. In C when you have some array[] or array2d[][] when you put somewhere array it is your first element array[0] and when you put array2d it is your first poem (array[0][]). You also can do *(array+1) and this is the same like array[1].
It occurs to me that an int will fit in the space of an int *, on today's computers, so you can put the int value in the address space of the int var, without corrupting the other values of the struct. I added this to main():
printf("\nsizeof int: %d", (int) sizeof(int));
printf("\nsizeof int*: %d", (int) sizeof(int *));
and got this output on my system:
sizeof int: 4
sizeof int*: 8
Seems to me that's why it's working when the pointer vars are used instead of vars themselves?
Like many other questions, if you paid attention to compiler warnings, it'd be clear to you. When you change both struct members to pointers, you do get following compiler warnings:
str.c:11:5: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
printf("NAME: %s", test.name);
^
str.c:12:5: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘int *’ [-Wformat=]
printf("\nAGE: %d", test.age);
What does those mean? So effectively you have changed it to 2D character array and a integer array (or int*). It still works because the starting address of them both remains the same still. So accessing a variable or a pointer just with starting address yields the same result. However, you do notice difference if you did something like,
test.age++
In case of age being an int, that increments the value by 1. In case age being an int* in increments the pointer to the next slot (sizeof(int) increment).

%d expecting int* in c [duplicate]

This question already has answers here:
SegFault after scanf?
(4 answers)
Closed 6 years ago.
As per what I know, %d expects an int value. I don't understand why gcc compiler is saying that it expects int* instead.
Here is my code:
#include<stdio.h>
#include<stdlib.h>
struct student
{
int rn, m[5];
char nm[25];
};
int main()
{
struct student* s[5];
struct student **q=s;
int i = 0;
printf("Enter data");
for(i=0;i<5;i++)
{
printf("\nStudent %d:\n",i+1);
printf("Roll number: ");
scanf("%d",(s[i])->rn);
printf("\n%d",s[i]->rn);
}
}
And here is the warning:
warning: format ‘%d’ expects argument of type ‘int *’, but argument 2 has type ‘int’ [-Wformat=]
scanf("%d",(s[i])->rn);
scanf reads a value into an int, it takes an pointer to the variable to read into.
scanf("%d",&((s[i])->rn));
printf takes an int for %d, but scanf takes the address of an int (an int *) so it can store the converted value.
RTFM would help here. scanf and related functions (sscanf etc) always need pointers of the variable(s) to which they'll read the values to. scanf documentation

malloc() pointer output clarification

I'm trying to learn C, more specifically pointers and malloc(). I wrote the following program and need a few clarifications about warning messages I got and the output.
#include<stdio.h>
#include<stdlib.h>
void printem(char *ptr, char loopagain)
{
int i;
for (i = 0; i < loopagain; i++)
{
printf("Found %c at address %c \n",ptr[i],&ptr[i]);
}
return;
}
void initializeblock(char *ptr, char loopagain)
{
int i;
for (i = 0; i < loopagain; i++)
{
ptr[i] = 65+i;
}
return;
}
int main()
{
char neededbytes = 10;
char *p;
p = (char *) malloc(neededbytes * sizeof(char));
if(p==NULL)
{
printf("Error! memory not allocated.");
exit(0);
}
else
{
printem(p,neededbytes);
initializeblock(p,neededbytes);
printem(p,neededbytes);
}
free(p);
}
The first problem I have is I don't get the address of each of the 10 char elements to print out correctly as numbers. Instead of a numbers I get symbols. This is the line of code that prints out the values and addresses.
printf("Found %c at address %c \n",ptr[i],&ptr[i]);
What am I doing wrong?
The second problem is inside the else statement I have the following code
printem(p,neededbytes);
initializeblock(p,neededbytes);
printem(p,neededbytes);
originally I used an & before p but got the following warnings
[Warning] passing argument 1 of 'printem' from incompatible pointer type
[Note] expected 'char *' but argument is of type 'char **'
The examples I found online show that a function expecting a pointer should have the address passed to it, why am I getting the warings when I use
printem(&p,neededbytes);
initializeblock(&p,neededbytes);
printem(&p,neededbytes);
Also, when I allocate a block using malloc(), is there another way to access/modify the data other than using array brackets, p[i]?
Is there a way to know the size of the block allocated so I don't have to pass it as an argument in the following line
printem(p,neededbytes);
First of all
printf("Found %c at address %c \n",ptr[i],&ptr[i]);
should be at least
printf("Found %c at address %p \n",ptr[i],(void *)&ptr[i]);
because, &ptr[i] is an address and it needs %p format specifier. Then, printf() being a variadic function, only default argument promotion takes place, so you need to cast the argument to void *, the expected type of %p. Using inappropriate type argument for conversion specifier leads to undefined behavior.
That said, even this won't save you. At the point you're calling printem(), the memory location pointed by p is uninitialized [#]and the content of it is undeterministic. Using uninitialized value will again lead you to UB. So, you need to initialize the memory before trying to print the value.
Then, check the signature of initializeblock()
void initializeblock(char *ptr, char loopagain)
and the call on which you got the warning
initializeblock(&p,neededbytes);
in this call, you're trying to pass &p which is of type char ** and trying to receive the same in a char *, which triggers the warning. You should be fine with a call like
initializeblock(p,neededbytes);
in this case.
Lastly
Is there a way to know the size of the block allocated so I don't have to pass it as an argument in the following line...
I'm afraid, no. There is no standard way of knowing the allocated size just from the pointer, so you have to pass the size as a second parameter.
[#] malloc() returns uninitialized memory.

Resources