I need to implement my own printf function in C. However I am having trouble using the ellipsis ("...") feature with my function.
According to my textbook, the parameters passed to a function with an ellipsis should be located on the stack right above where the first parameter is stored. I can not find any of the the additional parameters I am passing on the stack. Here is the code I used to test my function and the output:
#include<stdio.h>
#include<stdlib.h>
int myprintf(char *str, ...)
{
//test code to view data around str on the stack:
int i;
for (i = -8; i <= 8; i++)
{
char *ptr = str + (i * 4); // ptr will iterate through the 8 bytes above and
// below str[0] on the stack
printf ("Bytes from str: %+03d \t
Ptr Addr: %x \t
Val int: %d \t
Val char: %c \n",
(i*4), ptr, *ptr, *ptr);
}
//my implementation of printf...
}
int main(void)
{
myprintf("test string", 1111, 2222, 3333);
}
Here is the output of the myprintf function (a printout of the stack):
Bytes from str: -32 Ptr Addr: 8048922 Val int: 48 Val char: 0
Bytes from str: -28 Ptr Addr: 8048926 Val int: 97 Val char: a
Bytes from str: -24 Ptr Addr: 804892a Val int: 104 Val char: h
Bytes from str: -20 Ptr Addr: 804892e Val int: 32 Val char:
Bytes from str: -16 Ptr Addr: 8048932 Val int: 0 Val char:
Bytes from str: -12 Ptr Addr: 8048936 Val int: 118 Val char: v
Bytes from str: -08 Ptr Addr: 804893a Val int: 93 Val char: ]
Bytes from str: -04 Ptr Addr: 804893e Val int: 37 Val char: % <- my other variables should be here and above
Bytes from str: +00 Ptr Addr: 8048942 Val int: 116 Val char: t <-"test string"
Bytes from str: +04 Ptr Addr: 8048946 Val int: 32 Val char: <-" string"
Bytes from str: +08 Ptr Addr: 804894a Val int: 105 Val char: i <-"ing"
Bytes from str: +12 Ptr Addr: 804894e Val int: 0 Val char:
Bytes from str: +16 Ptr Addr: 8048952 Val int: 3 Val char:
Bytes from str: +20 Ptr Addr: 8048956 Val int: 0 Val char:
Bytes from str: +24 Ptr Addr: 804895a Val int: 0 Val char:
Bytes from str: +28 Ptr Addr: 804895e Val int: -1 Val char: �
Bytes from str: +32 Ptr Addr: 8048962 Val int: 0 Val char:
From what I understand, the values 1111, 2222, and 3333 should be located somewhere in this stack printout. Where are these values going when I make the function call?
EDIT: I cannot use the "stdarg.h" library in my implementation.
Behavior of this program may not granteed by the specification, but for this experiment of searching argument from the stack, you have to move the pointer pointing at the argument instead of the pointer passed as the argument.
#include<stdio.h>
#include<stdlib.h>
int myprintf(char *str, ...)
{
//test code to view data around str on the stack:
int i;
for (i = -8; i <= 8; i++)
{
/* add & before str to get the address of the argument */
char *ptr = (char*)&str + (i * 4); // ptr will iterate through the 4 * 8 bytes above and
// below str on the stack
printf ("Bytes from str: %+03d \t"
"Ptr Addr: %p \t"
"Val int: %d \t"
"Val char: %02X \n",
(i*4), (void*)ptr, *(int*)ptr, (unsigned int)(unsigned char)*ptr);
}
//my implementation of printf...
return 0;
}
int main(void)
{
myprintf("test string", 1111, 2222, 3333);
return 0;
}
Result in my local environment:
Bytes from str: -32 Ptr Addr: 0028FF10 Val int: 213 Val char: D5
Bytes from str: -28 Ptr Addr: 0028FF14 Val int: 1662423109 Val char: 45
Bytes from str: -24 Ptr Addr: 0028FF18 Val int: -2 Val char: FE
Bytes from str: -20 Ptr Addr: 0028FF1C Val int: 1972834658 Val char: 62
Bytes from str: -16 Ptr Addr: 0028FF20 Val int: 2130567168 Val char: 00
Bytes from str: -12 Ptr Addr: 0028FF24 Val int: 0 Val char: 00
Bytes from str: -08 Ptr Addr: 0028FF28 Val int: 0 Val char: 00
Bytes from str: -04 Ptr Addr: 0028FF2C Val int: 4227938 Val char: 62
Bytes from str: +00 Ptr Addr: 0028FF30 Val int: 4235431 Val char: A7
Bytes from str: +04 Ptr Addr: 0028FF34 Val int: 1111 Val char: 57
Bytes from str: +08 Ptr Addr: 0028FF38 Val int: 2222 Val char: AE
Bytes from str: +12 Ptr Addr: 0028FF3C Val int: 3333 Val char: 05
Bytes from str: +16 Ptr Addr: 0028FF40 Val int: 0 Val char: 00
Bytes from str: +20 Ptr Addr: 0028FF44 Val int: 0 Val char: 00
Bytes from str: +24 Ptr Addr: 0028FF48 Val int: 2686824 Val char: 68
Bytes from str: +28 Ptr Addr: 0028FF4C Val int: 4198992 Val char: 50
Bytes from str: +32 Ptr Addr: 0028FF50 Val int: 1 Val char: 01
As @Joe says, use va_*
macro to read variable number arguments.
Otherwise, the program may not work in some environment -- for example, x86_64 where arguments are passed on register, not on the stack.
I made some modification
and ran the code on Wandbox.
Result became like this:
Bytes from str: -64 Ptr Addr: 0x7fff2308b498 Val int: -1473084125 Val char: 23
Bytes from str: -60 Ptr Addr: 0x7fff2308b49c Val int: 0 Val char: 00
Bytes from str: -56 Ptr Addr: 0x7fff2308b4a0 Val int: 4196088 Val char: F8
Bytes from str: -52 Ptr Addr: 0x7fff2308b4a4 Val int: 0 Val char: 00
Bytes from str: -48 Ptr Addr: 0x7fff2308b4a8 Val int: 35 Val char: 23
Bytes from str: -44 Ptr Addr: 0x7fff2308b4ac Val int: 0 Val char: 00
Bytes from str: -40 Ptr Addr: 0x7fff2308b4b0 Val int: -1473063104 Val char: 40
Bytes from str: -36 Ptr Addr: 0x7fff2308b4b4 Val int: 32682 Val char: AA
Bytes from str: -32 Ptr Addr: 0x7fff2308b4b8 Val int: -1470881080 Val char: C8
Bytes from str: -28 Ptr Addr: 0x7fff2308b4bc Val int: 32682 Val char: AA
Bytes from str: -24 Ptr Addr: 0x7fff2308b4c0 Val int: 0 Val char: 00
Bytes from str: -20 Ptr Addr: 0x7fff2308b4c4 Val int: 0 Val char: 00
Bytes from str: -16 Ptr Addr: 0x7fff2308b4c8 Val int: 4195810 Val char: E2
Bytes from str: -12 Ptr Addr: 0x7fff2308b4cc Val int: 0 Val char: 00
Bytes from str: -08 Ptr Addr: 0x7fff2308b4d0 Val int: 0 Val char: 00
Bytes from str: -04 Ptr Addr: 0x7fff2308b4d4 Val int: 0 Val char: 00
Bytes from str: +00 Ptr Addr: 0x7fff2308b4d8 Val int: 4196155 Val char: 3B
Bytes from str: +04 Ptr Addr: 0x7fff2308b4dc Val int: 0 Val char: 00
Bytes from str: +08 Ptr Addr: 0x7fff2308b4e0 Val int: 587773152 Val char: E0
Bytes from str: +12 Ptr Addr: 0x7fff2308b4e4 Val int: 32767 Val char: FF
Bytes from str: +16 Ptr Addr: 0x7fff2308b4e8 Val int: -1477724000 Val char: A0
Bytes from str: +20 Ptr Addr: 0x7fff2308b4ec Val int: 5 Val char: 05
Bytes from str: +24 Ptr Addr: 0x7fff2308b4f0 Val int: -1475311104 Val char: 00
Bytes from str: +28 Ptr Addr: 0x7fff2308b4f4 Val int: 32682 Val char: AA
Bytes from str: +32 Ptr Addr: 0x7fff2308b4f8 Val int: 1111 Val char: 57
Bytes from str: +36 Ptr Addr: 0x7fff2308b4fc Val int: 0 Val char: 00
Bytes from str: +40 Ptr Addr: 0x7fff2308b500 Val int: 2222 Val char: AE
Bytes from str: +44 Ptr Addr: 0x7fff2308b504 Val int: 0 Val char: 00
Bytes from str: +48 Ptr Addr: 0x7fff2308b508 Val int: 3333 Val char: 05
Bytes from str: +52 Ptr Addr: 0x7fff2308b50c Val int: 0 Val char: 00
Bytes from str: +56 Ptr Addr: 0x7fff2308b510 Val int: 4196064 Val char: E0
Bytes from str: +60 Ptr Addr: 0x7fff2308b514 Val int: 0 Val char: 00
Bytes from str: +64 Ptr Addr: 0x7fff2308b518 Val int: -1473063104 Val char: 40
pointer passed = 4196155 0x40073b
As you see, the valued passed as pointer on Bytes from str: +00
, but value of the other arguments are not near the value.