As far as I know #define is just a string replacement and it's not a variable, so it doesn't have any memory address or something.
Suppose this code:
#include <stdio.h>
#define ONE "a"
main() {
printf("the number is: %d\n", ONE);
}
Then when I compile and run this program, I get a random string each time:
the number is: 8179551
the number is: 21127007
the number is: 57114463
...
If the #define doesn't have any memory address, then what's this value and why it's changed every time?
In your code
printf("the number is: %d\n", ONE);
is equivalent to
printf("the number is: %d\n", "a");
In fact you are printing the address of the string "a" as a decimal.
And you are getting random value in each execution that's because the address of "a" is got random address in each execution
The string "a" is a literal string and it's stored in the read only memory. The printf is printing the address of this memory
MOHAMED is right, you printing the adress of a string
what you what to do this
#define ONE 'a'
everything between two ''s are characters, only one character is allowed
This program invokes undefined behavior because the format specification doesn't match the type of argument (int versus char *).
C99, 7.19.6.1 # 9 (fprintf)
If a conversion specification is invalid, the behavior is
undefined.239) If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.
The correct way to print an address is with %p and via a (void *) argument:
printf("the address is: %p\n", (void *)ONE);
Related
Okay this is going to be somewhat lengthy.
So I've got a program that uses two %n format parameters in it's a printf() statement. %n essentially writes data without displaying anything... So when my format function encounters %n parameter, it writes the number of bites that have been written by the function to the address of the corresponding function argument.
#include <stdio.h>
#include <stdlib.h>
int main() {
int A = 5, B = 7, count_one, count_two;
printf("The number of bytes written up to this point X%n is being stored in
count_one, and the number of bytes up to here X%n is being stored in
count_two.\n", &count_one, &count_two);
printf("count_one: %d\n", count_one);
printf("count_two: %d\n", count_two);
printf("A is %d and is at %08x. B is %x.\n", A, &A, B);
exit(0);
}
the output of the program is:
The number of bytes written up to this point X is being stored in count_one,and the number of bytes up to here X is being stored in count_two.
count_one: 46
count_two: 113
A is 5 and is at bffff7f4. B is 7.
With regards to this printf
printf("A is %d and is at %08x. B is %x.\n", A, &A, B);
Now, the arguments are pushes to the stack in reverse order first the value of B then the value address of A then the value address of A, and finally the address of the format string...
Now if only two arguments are pushed to the stack with a format string that uses three format parameters?
So I removed the last argument in the code above to match this printf() argument
printf("A is %d and is at %08x. B is %x.\n", A, &A);
and what happens when I compile and execute is...
The number of bytes written up to this point X is being stored in count_one, and the number of
bytes up to here X is being stored in count_two.
count_one: 46
count_two: 113
A is 5 and is at bffffc24. B is b7fd6ff4
So I get this b7fd6ff4, what is that? What does this mean with relations to the stack frame for the format function?
Any insight or explanation would be much appreciated.
Having either the wrong number of format specifiers or mismatched format specifiers invokes undefined behavior.
From section 7.21.6.1 of the C standard regarding the fprintf function:
9 If a conversion specification is invalid, the behavior is undefined.282) If any argument is not the correct type for the
corresponding conversion specification, the behavior is undefined.
What this means is that you can't make any reliable prediction about what value the function will receive if you don't pass it enough parameters. What will most likely happen in an implementation that uses a stack and has optimizations disabled is that it will grab whatever value happens to be next in memory next to the last parameter pushed onto the stack.
the following proposed code:
fixes the problems listed in the comments to the question
cleanly compiles
performs the desired functionality
and now the proposed code:
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int A = 5;
int B = 7;
int count_one;
int count_two;
printf("The number of bytes written up to this point X%n is being stored"
" in count_one, and the number of bytes up to here X%n is being"
" stored in count_two.\n",
&count_one,
&count_two);
printf("count_one: %d\n", count_one);
printf("count_two: %d\n", count_two);
printf("A is %d and is at %p. B is %x.\n", A, (void*)&A, B);
exit(0);
}
a typical run of the program results in:
The number of bytes written up to this point X is being stored in count_one, and the number of bytes up to here X is being stored in count_two.
count_one: 46
count_two: 113
A is 5 and is at 0x7fff19c28ea8. B is 7.
Under the 32-bit x86 calling convention all function parameters are passed on the stack. If you call printf() with more format specifiers than arguments the function will gladly keep walking up the stack and grabbing whatever values are there to find something to display.
The specific contents of the stack are going to be variable- usually function-local variables, function return pointers, or stack pointers.
printf assumes that you pushed all 4 arguments on the stack. It is expecting B to be on the stack regardless of whether you provided it or not. If you did not provide it then it will use whatever is in that memory location and print it.
int main(){
printf("the value is %d \n " ,'x'+ "x");
return 0;
}
Output
4196024
But the former one ('x') is an integer and latter one ("x")is a string .
Can I know how ? Or is it giving me a garbage value.
Literal strings have type char [N] where N is just large enough for all characters in the literal plus the terminating '\0' (namely "x" has type char[2]).
In the context of the expression 'x' + "X", the array gets converted to a pointer to its first element, then that address is added with the int value 'x'. The resulting address is passed on to printf() with an invalid conversion specification.
You have invoked Undefined Behaviour!
Try this
printf("the valus is %p\n", (void*)('x' + "x"));
Also note that the address 'x' + "x" is not part of any object in your program. Merely evaluating it is already Undefined Behaviour.
Basically,
printf("the value is %d \n " ,'x'+ "x");
invokes undefined behaviour. What you need is %p format specifier here.
Otherwise, in general,
"string" gives you the base address of the string literal
'p' gives you the ASCII value of the char representation.
So, what essentially is being done here is to print the address of the member in 'x'th element of the string "x" (which does not make much sense, practically).
For better understanding, you can re-write the print statement as
printf("the pointer is %p\n", (void *) ("x"+ 'x'));
which is equivalent to
printf("the pointer is %p\n", (void *) &("x"['x']));
Note that you don't need spaces before or after the newline in the print format.
What you are asking for in the formatted string is an integer so it is printing the integer value of the character 'x' added to the base address of the string literal "x".
'x' is 120 so if you use a memory viewer to peek at the outputted value minus 120 bytes, you will probably find an 'x' followed by a '\0' (= 0).
i am trying to print value of an array in C-language.I am using 3 format specifier for only one value of array , my problem is that i don't understand that how other two values are coming in my output .
here is my code:
int arr[6] = {3,4,42,2,77,8};
printf("%d %d %d ",arr[2]);
output :
42 3 4
According to the C Standard
If there are insufficient arguments for the format, the behavior is
undefined.
In your call of printf
printf("%d %d %d ",arr[2]);
the arguments are exhausted after the first format specjfjer. So the function call has undefined behaviour and the output can contain any garbage.
You shall write
printf( "%d ", arr[2] );
or for example
printf( "%d %d %d ", arr[2], arr[3], arr[4] );
When printf() sees three format specifiers, it looks at specific locations, either in stack memory or in CPU registers, depending on the conventions of the compiler, for three arguments.
You provided one, but some data that you have no control over exists in the other two locations, and that's what gets printed.
The other two values are garbage and don't have any meaning. The function printf requires as many arguments as there are format specifiers, so in your case three. Since you only provided one argument (arr[2]), the other two specifier 'don't know' what to print - thus gargabe will come out. Make sure to provide the required number of arguments.
If you want to print the array number by number, you will have to use a for loop.
The signature of printf is.
int printf(char*, ...);
So, you can have a variable number of arguments, then.
printf("%d %d %d ",arr[2]);
Is a valid call of the function printf.
However, because you provided no values yourself, then you will get whatever... that in your special case it seems that it printed arr[0] and arr[1].
Hello Everyone I just want to clarify a doubt regarding pointers.So that I can know whether I understood it correctly or not.
void main ()
{
char c[10]="COMPUTERS";
printf("The first is %d\n",c); //1
printf("The second is %f\n",c); //2
printf("The third is %u\n",c); //3
printf("The fourth is %s\n",c); //4
printf("The fifth is %c\n",c); //5
}
The first printf will print the address of first location of character array 'c',
Similarly second printf will also try to print the address in float form.
The third printf will print the address again.
While the fourth printf will print the character array.
My doubt is associated with the 5th printf. It is printing random values or sometimes no values is it because the value of 'c' is memory address of first character of array 'c' and I am trying to print that value as a character?
all of those prints are undefined behavior except the %s one. the weird behavior you are seeing with %c format specifier is due to underlying casts on the adress of the pointer which can change from running it one time to the next.
if you want to print out the adress the pointer points to use %p like this:
printf("address: %p\n", (void *)c);
(These are not "doubts", they are questions or uncertainties perhaps).
All of those except %s are undefined behavior, since they all mis-match the actual type of the value provided (char *) with the formatting specifier.
printf("The fifth is %c\n",c[0]);
This makes sense. Printing the first character of the array.
Trying to print the address just as a character makes no sense.
Only this printf() is good
printf("The fourth is %s\n",c);
The rest of the printf()'s have undefined behavior.
The first printf will print the address of first location of character array 'c',
Strictly speaking, the first printf will invoke undefined behavior since you are using the wrong format specifier to print a pointer. But yeah it will probably print the address on most systems.
Similarly second printf will also try to print the address in float form.
No it will just give you some binary goo. You never convert the address to a float format, you only attempt to print it as if it was. This is completely undefined behavior.
The third printf will print the address again.
Same as 1. Undefined behavior, but yeah, it will probably print the address...
While the fourth printf will print the character array.
Yes.
My doubt is associated with the 5th printf. It is printing random values or sometimes no values is it because the value of 'c' is memory address of first character of array 'c' and I am trying to print that value as a character?
Again, undefined behavior. It can print anything.
Theoretical analysis:
printf("The first is %d\n",c); // undefined behavior by the standard
printf("The second is %f\n",c); // undefined behavior by the standard
printf("The third is %u\n",c); // undefined behavior by the standard
printf("The fifth is %c\n",c); // undefined behavior by the standard
Practical analysis:
printf("The first is %d\n",c); // requires sizeof(void*) == sizeof(int)
printf("The second is %f\n",c); // requires sizeof(void*) == sizeof(double)
printf("The third is %u\n",c); // requires sizeof(void*) == sizeof(unsigned int)
printf("The fifth is %c\n",c); // different between big-endian and little-endian
Detailed practical analysis:
sizeof(void*) < sizeof(...) will potentially yield a memory access violation during runtime
sizeof(void*) > sizeof(...) will yield different printout between big-endian and little-endian
#include <stdio.h>
#define slice(bare_string,start_index) #bare_string+start_index
#define arcane_slice(bare_string,start_index) "ARCANE" #bare_string+start_index
int main(){
printf("slice(FIRSTA,0)==> `%s`\n",slice(FIRSTA,0));
printf("slice(SECOND,2)==> `%s`\n",slice(SECOND,2));
printf("slice(THIRDA,5)==> `%s`\n",slice(THIRDA,5));
printf("slice(FOURTH,6)==> `%s`\n",slice(FOURTH,6));
printf("slice(FIFTHA,7)==> `%s`\n",slice(FIFTHA,7));
printf("arcane_slice(FIRSTA,0)==> `%s`\n",arcane_slice(FIRST,0));
printf("arcane_slice(SECOND,2)==> `%s`\n",arcane_slice(SECOND,2));
printf("arcane_slice(THIRDA,5)==> `%s`\n",arcane_slice(THIRDA,5));
printf("arcane_slice(FOURTH,6)==> `%s`\n",arcane_slice(FOURTH,6));
printf("arcane_slice(FIFTHA,7)==> `%s`\n",arcane_slice(FIFTHA,7));
return 0;
}
OUTPUT:
slice(FIRSTA,0)==> `FIRSTA`
slice(SECOND,2)==> `COND`
slice(THIRDA,5)==> `A`
slice(FOURTH,6)==> ``
slice(FIFTHA,7)==> `slice(FIFTHA,7)==> `%s`
`
arcane_slice(FIRSTA,0)==> `ARCANEFIRST`
arcane_slice(SECOND,2)==> `CANESECOND`
arcane_slice(THIRDA,5)==> `ETHIRDA`
arcane_slice(FOURTH,6)==> `FOURTH`
arcane_slice(FIFTHA,7)==> `IFTHA`
I have the above C code that I need help on. I am getting weird behaviour from
the function-like macro slice that is supposed to 'slice' from a passed index
to the end of the string. It does not slice in the real sense but passes
a pointer from a certain point to printf which starts printing from that
address. I have managed to figure out that in arcane_slice the strings
are concatenated first then 'sliced'. I also have figured out that when start_index
is equal to 6 printf starts printing from the null byte and that is why
you get the 'empty' string. The strange part is when start_index is 7. It prints
the first argument to printf(interpolator string) concatendated with the passed bare string in both.
arcane_slice and slice(as shown in the 5th and 10th lines in the output)
Why is that so?
My wildest guess is that when the start_index exceeds the length of the strings,
the pointer points to the start of the data segment in the program's address space. But
then you could counter that with "why didn't it start printing from FIRSTA"
Not any "data segment", the stack. This is what I remember: when C calls a function it first puts data on stack, first variable arguments, then the format, all being the addresses to the memory sequentially allocated with your text. In that block of memory, the last argument (c-string) goes first, and the first goes last, thus:
Memory:
"FIFTHA\0slice(FIFTHA,7)==> `%s`\n\0"
Arguments:
<pointer-to-"FIFTHA"> <pointer-to-"slice...">
Since you overincrement the first one it skips the '\0' character and points at the format as well.
Try to experiment with this with more placeholders, like
printf("1: %s, 2: %s\n", slice(FIFTHA,7), slice(FIFTHA,6));
slice(bare_string,start_index) #bare_string+start_index
you are passing a string and bare_string stores the starting address of string which you have passed and then you returning changed pointer location which is bare_string+start_index
char str[6]="Hello";
char *ptr =str;
printf("%s\n",str);//prints hello
printf("%s\n",str+1);//prints ello
printf("%s\n",str+2);//prints llo
printf("%s\n",str+3);//prints lo
printf("%s\n",str+4);//prints o
printf("%s %c=%d \n",str+5,*(str+5),*(str+5));//prints Null
printf("%s %c=%d \n",str+6,*(str+6),*(str+6));//prints Null or may be Undefined behavior
printf("%s %c=%d \n",str+7,*(str+7),*(str+7));//prints Null or may be Undefined behaviour
the same scenario is happing in your case.
Test Code:
#include<stdio.h>
main()
{
char str[6]="Hello";
char *ptr =str;
printf("%s\n",str);//prints hello
printf("%s\n",str+1);//prints ello
printf("%s\n",str+2);//prints llo
printf("%s\n",str+3);//prints lo
printf("%s\n",str+4);//prints o
printf("%s %c=%d \n",str+5,*(str+5),*(str+5));//prints Null
printf("%s %c=%d \n",str+6,*(str+6),*(str+6));//prints Null or may be Undefined behavior
printf("%s %c=%d \n",str+7,*(str+7),*(str+7));//prints Null or may be Undefined behaviour
}
You have answered your question yourself. "FIFTHA"+7 gives you a pointer outside the string object, which is undefined behavior in C.
There's no easy way to get a more Python-like behavior for such "slices" in C. You could make it work for indexes up to a certain upper limit by adding a suffix to your string, full of zero bytes:
#define slice(bare_string,start_index) ((#bare_string "\0\0\0\0\0\0\0")+(start_index))
Also, when using macros, it's good practice (and avoids bugs too) to use parentheses excessively.
#define slice(bare_string,start_index) ((#bare_string)+(start_index))
#define arcane_slice(bare_string,start_index) (("ARCANE" #bare_string)+(start_index))