1

I am missing a fundamental point on passing values.

In my code, I wrote this prototype/function:

void drawFont (char A[],unsigned char length, char x1, char y1, uint16 FGcolor);

I call the function using a call like this:

drawFont ("William",7,15,25,YEL,0);

or

drawFont ("W",1,15,25,YEL,0);

Both of these work fine in the code. If I examine A[0] in the function, I will see a value of '57' representing an ASCII 'W'. All fine and good.

My question/problem is: When I attempt to replicate the 'W' using the ASCII value instead of the string representation, my code fails Example:

drawFont (57,1,15,25,YEL,0);

The value of A[0] in the code is: 0, but the address of A is 57. So somehow the compiler assumes that I want to pass a pointer? I'm confused, why did it pass the string fine, but not the value?

Thanks in advance from a novice C programmer.

4
  • "somehow the compiler assumes that I want to pass a pointer" - that is exactly what char A[] is in the context of that parameter list. A debugger and/or printf("%p : %s", A, A); at the top of drawFont for your first two examples will likely be something you find interesting. Commented Oct 28, 2014 at 6:29
  • Not really. Im using a debugger, that is how I know what is happening. I really wish printf was available to me! That would soooo simplify things. But this is a microcontroller, so most of my questions are theoretical, as output is difficult to test. I usually have to examine values and ask,"Why?". Commented Oct 28, 2014 at 7:06
  • the prototype shows 5 parameters however, each of the invocations shows 6 parameters. The compiler should have issued a (at least) warning message. for each of the invocations. did you use a parameter on the compile something like (for GCC compiler) -Wall? Commented Oct 28, 2014 at 15:50
  • Good eye, but off topic. I shorten the parameter list so you didn't have to scroll to the right. Commented Oct 28, 2014 at 16:51

4 Answers 4

2

If you pass

drawFont (57,1,15,25,YEL,0);

you will be doming the same as

drawFont ('W',1,15,25,YEL,0);

which is just one character. The function requires an array of characters, that's why it's not correct.

Sign up to request clarification or add additional context in comments.

Comments

1

The prototype for your function declares that the first parameter is a pointer to a character:

void drawFont (char A[],...);

If you pass an integer, you are breaking the rules. The compiler should warn about it. Mine gives a warning about the following code on the line with func(57):

void func(char a[])
{
}

char arr[] = {87,84,70};

int main()
{
    func(57);
    func("W");
    func(arr);
}
x.c(9) : warning C4047: 'function' : 'char *' differs in levels of indirection from 'int'
x.c(9) : warning C4024: 'func' : different types for formal and actual parameter 1

If you look at the assembly output from the compiler, you can see the problem more clearly (I cut out the uninteresting parts):

PUBLIC  _arr
_DATA   SEGMENT
_arr    DB      057H                ;Here's the char array at an address in memory.
        DB      054H
        DB      046H
        ORG $+1
$SG1297 DB      'W', 00H   ;Here's the "W" at an address in memory (nul-terminated)
_DATA   ENDS

; 9    :     func(57);

  00003 6a 39            push    57                  ; Push 57 as the address, WRONG!
  00005 e8 00 00 00 00   call    _func
  0000a 83 c4 04         add     esp, 4

; 10   :     func("W");

  0000d 68 00 00 00 00   push    OFFSET $SG1297      ; Push the address of the string.
  00012 e8 00 00 00 00   call    _func
  00017 83 c4 04         add     esp, 4

; 11   :     func(arr);

  0001a 68 00 00 00 00   push    OFFSET _arr         ; Push the address of the array.
  0001f e8 00 00 00 00   call    _func
  00024 83 c4 04         add     esp, 4

The code is expecting to go to an address to read characters. Who knows what is in address 57.

4 Comments

Thanks for the response. Your function array parameter is declared as indirect, I don't know if that is why your compiler is complaining. Mine does not give a warning, nor is it declared as such. Further, a char is a 8bit number/ a small integer so to speak, the compiler wont care how you are using it. My problem specifically is why the "W" gets pushed into the char array as 57, but the literal 57 ends up as an address/pointer. So phrased another way, if I wanted to push a slew of literals into that array how would I do that?
There is no difference between declaring char* a and char a[]. It generates the exact same code and even the exact same error (including the char * in the message. I'll update it to match your declaration, but they are two ways to declare that a char pointer is expected.
You cannot pass a 57 to a function expecting a pointer without problems. That your compiler doesn't even warn you about the problem is unfortunate. Perhaps check that you can increase the warning level with a command line parameter?
Pass an actual array of characters not a single number. The function expects an address. I'll update my example with another version of the call.
1

The value of A[] is actually a pointer, such as &A[0] (you could rewrite the function using char *A instead of char A[]

That is the address of the first slot, not what is stored in it. In the memory location pointed to by the pointer, there exists a value 57. When you write a function with a char array or char pointer parameter, you tell the compiler: I will pass you a memory address. Go to that address and start reading each char (number) until you arrive at the null byte, then stop.

But when you pass literal integer 57 as the argument, that is not a valid pointer to an array of characters. You are missing the level of indirection.

So lets assume your char A[] resides at 0xfeaa0011

In RAM at 0xfeaa0011 -> "William" (or 52, ...)

The correct call to drawFont() actually looks like drawFont(0xfeaa0011, 1, 15, 25, YEL, 0)

So you see replacing the pointer with 57 isn't the same thing.

16 Comments

I understand what you are saying about the indirection of the pointer. What I am still missing is; the char value being passed is a value (in the end), so how would I 'cast' the literal 57 to pass properly, or is there a operator that instructs the compiler to treat the literal (57) as a literal and not a pointer reference?
You are still not connecting something. You could store 57 somewhere in a memory address, and then pass the address of the 57 to the function. That is what an array is. It isn't about literal vs pointer, it is literally a memory address in one case vs a small integer (57) in the other. That function will think you meant address 57
The only way you can add a level of indirection to the 57 is to store it somewhere. By itself, the 57 is a literal or "immediate" value, which doesn't even allow you to take the address of it.
Solely for illustration, you could do this extremely dangerous, ugly thing: char c = 57; char t = 0; drawFont(&c, ...); where the t is needed to be a null "terminator" but there is no guarantee that t will follow. Otherwise, use of the array is the only right way to do it.
I am nodding and agreeing, the array is a storage mechanism. It 'shouldn't' care if I pass a literal or a string, both are values. I thought both would arrive in the function as the same value (57), but one does, the other arrives as an address (pointer). So why is the literal being seen as a pointer, clearly I am doing something wrong.
|
0

Your function requires a string ( char[] ) as an argument. When you pass "William" it is interpreted as a string, that's normal. When you pass "W" it is also interpreted as a string:

string[2] = { 'W' + 0 } //notice the null byte following your char

That's because you used double-quotes " instead of single-quotes '. Therefore passing 57 or 'W' is viewed as a single char and not a char[]/string which then gives you an error since your function is expecting a char[] and you gave it a char.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.