4

I am trying to program a microchip in C. Right now my I'm working to update a line on an LCD screen but it doesnt work correctly. Can anyone shed some light on this?

float slope = 0.0626;
char *mystring;
int8_t    LCDline1[20];

void myfunction(){
    sprintf(*mystring, "%ld", (long)(slope * 10000));
    memcpy(LCDline1, *mystring, strlen(*mystring)+1);
}

When I run compile code I get the following three errors.

calibrate.c:60:5: warning: passing argument 1 of 'sprintf' makes
pointer from integer without a cast. note: expected 'char *'
but argument is of type 'char'

calibrate.c:61:5: warning: passing argument 1 of 'strlen' makes
pointer from integer without a cast.  note: expected 'const char *'
but argument is of type 'char'

calibrate.c:61:5: warning: passing argument 2 of 'memcpy' makes
pointer from integer without a cast. note: expected 'const void *' but
argument is of type 'char'

I am not sure what I am doing wrong, I am using the following definitions for my starting point

void *memcpy(void *str1, const void *str2, size_t n)
size_t strlen(const char *str)
char *p = "String";
NAND
  • 663
  • 8
  • 22
Bob
  • 159
  • 1
  • 1
  • 6

3 Answers3

12

mystring is already a pointer. *mystring de-references it to give the first character. You want to just pass in mystring.

You must also allocation some memory for mystring, either statically or dynamically using malloc.

float slope = 0.0626;
char* mystring;
/* char mystring[50]; */ // or just do this, as Sahu and John suggested
int8_t    LCDline1[20];

void myfunction(){
    mystring = (char*)malloc(mystring_size); // set this to any size
    sprintf(mystring, "%ld", (long)(slope * 10000));
    memcpy(LCDline1, mystring, strlen(mystring)+1);
}

NB whenever you are allocating memory for the string, make sure to allocate one more than the string's length, to store the zero-delimiter character (strlen and many other functions need this)

  • What I need is a string that can be any size, because the value of slope can have anywhere from 3 to 8 digits of precesion. I was using http://stackoverflow.com/questions/8732325/how-to-declare-strings-in-c for my declaration. How do I declare a pointer which I can change the contents of? – Bob Jun 29 '16 at 20:46
  • @Bob, you can make it easier for you by using `char mystring[50];` – R Sahu Jun 29 '16 at 20:47
  • That's the point of dynamic allocation - you can use `malloc` to allocate whatever size you want (within machine / OS limits); also don't forget to allocate one extra character space to store the zero delimiter character –  Jun 29 '16 at 20:48
  • Why is it that you dont need to declare that sprintf is writing the value to the target of the pointer mystring? Wouldn't the way you have it write the value of slope*1000 to the stored memory address of mystring? – Bob Jun 29 '16 at 20:57
  • What do you mean? Look at the manual for `sprintf` - by passing `mystring` to the first argument you _are_ declaring that `sprintf` should write the integer to `mystring` –  Jun 29 '16 at 20:58
  • @Bob: You're better off statically declaring an array of fixed size, large enough for the longest possble string plus 1 extra character for the 0 terminator. Since the value of slope can be anywhere from 3 to 8 digits, declare `mystring` as an *array* of `char` like so - `char mystring[9];`. – John Bode Jun 29 '16 at 21:00
  • @JohnBode the size of `long` is at least 32 bits on modern platforms, so you'd need 11 (9 for the billionth digit, 10 for the minus sign) - just to be on the safe side. –  Jun 29 '16 at 21:02
  • int sprintf(char *str, const char *format, ...) Doesnt that mean I need to declare the target of the pointer so it doesnt mess up the memory location? – Bob Jun 29 '16 at 21:03
  • @Bob the pointer _is_ the target (or represents the target). that's the _point_ of its existence. ( get it? :] ) –  Jun 29 '16 at 21:04
  • 1
    @willywonkadailyblah: In the first comment, the OP claimed that the value of `slope` can have anywhere from 3 to 8 digits of precision; I'm just taking him at his word. Of course, if you want to cover the max number of decimal digits that can be represented in a 32 bit integral type plus the sign. then yes, you'd need an 11- or 12-element array to store it. – John Bode Jun 29 '16 at 21:09
  • Ok I think I got it. Now I just have to figure out why char* mystring = (char*)malloc(21); exploded my compiler – Bob Jun 29 '16 at 21:12
  • @Bob really? give us the error message. did you include `stdlib.h` ? –  Jun 29 '16 at 21:13
  • I did include stdlib.h My error is "calibrate.c:53:1: error: initializer element is not constant". – Bob Jun 29 '16 at 21:20
  • @Bob apologies it was partly my fault. you need to do `malloc` and other kinds of dynamic initialization _inside_ a function, not outside; see edit –  Jun 29 '16 at 21:21
  • Why is that? Does that mean you cannot make a dynamic variable global? – Bob Jun 29 '16 at 21:22
  • @Bob you can make variables global anytime, but you can't _allocate them dynamically_ outside functions; generally you can't call a function outside a function in C –  Jun 29 '16 at 21:25
3

You are incorrectly using pointers. A "string" is defined as an array of characters, and so when you write char *mystring, you are declaring a pointer to a character array (or a string).

Now, if you dereference mystring using *mystring in your code, you are getting the first element of that array, which is just a character. As the warnings say, those functions accept char* parameters, not char.

So, just pass in the pointer, without dereferencing:

void myfunction(){
    sprintf(mystring, "%ld", (long)(slope * 10000));
    memcpy(LCDline1, mystring, strlen(mystring)+1);
}
Rushy Panchal
  • 16,979
  • 16
  • 61
  • 94
  • I am tying to understand pointers better, taking the sprintf function you wrote, wouldnt that write the value of slope*1000 into the pointer of mystring, rather than its target? – Bob Jun 29 '16 at 20:48
  • @Bob: No, `sprintf` assumes that pointer is the starting address of a buffer, and will write the resulting string to that buffer. – John Bode Jun 29 '16 at 21:03
0
Char *c;

This can be starting address of array to store characters but,

c //is the pointer to array
*c // will give starting character of array
Joseph
  • 97
  • 1
  • 8