1

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);
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
WhatIf
  • 653
  • 2
  • 8
  • 18

1 Answers1

3

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.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261