How to store the exact literal of #define in a string for printing [duplicate] - c-preprocessor

This question already has answers here:
How to make a char string from a C macro's value?
(3 answers)
Converting a #defined constant number to a string
(1 answer)
Convert a preprocessor token to a string
(6 answers)
Closed 5 days ago.
There is a Macro #define buried deep in the libraries that I would like to quickly know the exact value of. Is there a way to store the value of the definition into a String so I could print it?
#define intgr 12
#define bnry 0b00000001
#define hex 0x0A
#define str "Hello World"
String myStr;
myStr = intgr;
cout<< myStr << endl; //Simple enough, work no problem
//12 <- actual
//12 <- expected
myStr = bnry; // using "bnry" would not work as #define does not touch inside quotes
cout<< myStr << endl;
//1 <- actual
//0b00000001 <- expected
myStr = hex;
cout<< myStr << endl;
//10 <- actual
//0x0A <- expected
myStr = str;
cout<< myStr << endl;
//Hello World <- actual
//"Hello World" <- expected, must include the quotation

You can use the well-known process of "stringizing" a pre-processor symbol, as shown below.
#include <stdio.h>
#define intgr 12
#define bnry 0b00000001
#define hex 0x0A
#define str "Hello World"
#define STRING(x) #x
#define STRINGIZE(x) STRING(x)
int main(void) {
char* strintgr = STRINGIZE(intgr);
char* strbnry = STRINGIZE(bnry);
char* strhex = STRINGIZE(hex);
char* strstr = STRINGIZE(str);
printf("%s\n", strintgr);
printf("%s\n", strbnry);
printf("%s\n", strhex);
printf("%s\n", strstr);
return 0;
}
Link to IDEOne Code in C
Link to IDEOne Code in C++
P.S. I used C syntax and char* type, however, after the pre-processor macros, C++ output and string type should work just as well.
Output
12
0b00000001
0x0A
"Hello World"

Related

Why is the Parent String printing by itself when I'm printing a substring of it? [duplicate]

This question already has answers here:
Passing not null terminated string to printf results in unexpected value
(6 answers)
Printing string using printf without null character [duplicate]
(1 answer)
how to make a not null-terminated c string?
(7 answers)
'\0' and printf() in C
(9 answers)
What are the repercussions of not using null termination in strings?
(3 answers)
Closed 8 months ago.
#include <stdio.h>
#include <stdlib.h>
int main()
{
char s[40]="Who are you tell me that I can not code?";
char c=s[8];
char st[2];
st[0]=s[0],st[1]=s[1];
printf("%s \n",st);
return 0;
}
Why is it printing my original string 's' also when I'm printing st?
Output:-
WhWho are you tell me that I can not code?►
Process returned 0 (0x0) execution time : 0.048 s
Press any key to continue.
s is not a proper C string because it has exactly 40 bytes and 40 characters. C strings must have a null terminator byte. You should define it as:
char s[] = "Who are you tell me that I can not code?";
There is the same problem for st that you define as an array of 2 bytes where you store 2 characters. You should define st as an array of 3 bytes and set a '\0' null character at st[2].
Both of these problems can cause undefined behavior. and the second does as you pass st to printf() for a %s format which expects a proper C string pointer.
Here is a modified version:
#include <stdio.h>
int main() {
char s[] = "Who are you tell me that I can not code?";
char st[3];
st[0] = s[0];
st[1] = s[1];
st[2] = '\0';
printf("%s\n", st);
return 0;
}
Note that you can also print a substring with printf using the precision field:
#include <stdio.h>
int main() {
char s[] = "Who are you tell me that I can not code?";
// print the 3 characters at offset 4
printf("%.3s\n", st + 4);
return 0;
}

sprintf() function changing the input arguments [duplicate]

This question already has answers here:
Undefined, unspecified and implementation-defined behavior
(9 answers)
Closed 2 years ago.
My code is following
#include <iostream>
int main(int argc, char *argv[])
{
int i = 10;
char c[3];
std::cout << i << std::endl;
sprintf(c, "%d", i);
std::cout << i << std::endl;
return 0;
}
Result of it's execution:
10
10
Great, make scene. Let's make char array too small.
#include <iostream>
int main(int argc, char *argv[])
{
int i = 100;
char c[3];
std::cout << i << std::endl;
sprintf(c, "%d", i);
std::cout << i << std::endl;
return 0;
}
Result of it's execution:
100
0
How on Earth i was changed? So sprintf() can change input variables? Why?
"How on Earth i was changed?"
Undefined behaviour.
To elaborate, in the second case, the destination buffer does not have a space to store the terminating null character, thereby the access is made past the valid memory, causing undefined behaviour.
Quoting the sprintf() behaviour (from C11, chapter 7.21.6.6, emphasis mine)
"The sprintf function is equivalent to fprintf, except that the output is written into an array (specified by the argument s) rather than to a stream. A null character is written at the end of the characters written; it is not counted as part of the returned value."
So, while using the function, you need to ensure that the destination buffer is long enough to hold the required value, plus a null terminator.
It's UB.
Looks like i is allocated right after c. When you sprintf "100" it's actually changes 4 bytes, including \0 terminator. So it overwrites i.

Split hex representation of an integer and save it in a string

I am trying to split the hex values of a variable in a string. For this I am using sprintf. But I am getting an error: Segmentation fault (core dumped)
Below is the code which I tried:
#include <stdio.h>
#include <string.h>
int main() {
char* t1;
char* t2;
int n = 0x23A;
sprintf(t1, "%X", n & 0xFF);
printf("t1 is : %s\n",t1);
sprintf(t2, "%X", (n >> 8) & 0xFF);
printf("t2 is : %s\n",t2);
return 0 ;
}
For example I want to split 0x23A in 0x02 and 0x3A
And I am using two string because my idea is concatenate them in the end to form a single string with 023A.
Is there any other way to get this output then please let me know.
You're using an uninitialized pointer, that gives undefined behavior.
Just use a character array, so you have some space for the string:
char t1[16];
sprintf(t1, "%X", n & ff);
printf("t1 is '%s'\n", t1);
This should print 3A.

Preprocessor and subsitution of format string

If I put:
#define SIZE 10
and after:
scanf("%SIZEs", s);
I have a runtime error. The preprocessor should substitute SIZE with 10 before to compile, so this should equal (in my opinion) to write
scanf("%10s", s);
so, where is the mistake?
It is not possible to replace the contents of the string literal by macro.
For example, it does the following:
#include <stdio.h>
#define S_(x) #x
#define S(x) S_(x)
#define SIZE 10
int main(void){
char s[SIZE + 1];
scanf("%" S(SIZE) "s", s);
puts(s);
return 0;
}
In your code, the problem is in
scanf("%SIZEs", s);
Anything residing between the quotes " " of a format string (string literal, in general) will not get substituted through MACRO substitution.
So, your scanf() remains the same as you're written, after preprocessing, and %S (or, %SIZEs, in whole) being one invalid format specifier, you get into undefined behaviour and hence got the error.
You can try the workaround as
scanf("%"SIZE"s", s);
This way, SIZE will be outside the quotes and will be considered for substitution in preprocessing stage.
If you are using SIZE only for formatting, you can also use:
#define SIZE "10"
scanf("%"SIZE"s", s);

strerror_r has no effect

Here is a simple program which illustrates the problem.
#include <string.h>
#include <iostream>
int main () {
char buf [30];
strerror_r (0, buf, sizeof (buf));
std :: cout << "strerror_r(0): " << buf << std :: endl;
std :: cout << "strerror(0): " << strerror (0) << std :: endl;
}
Here is the output.
strerror_r(0):
strerror(0): Success
Why is there nothing in buf?
(Compiled on Ubuntu with gcc.)
From man strerror_r:
The XSI-compliant version of strerror_r() is provided if:
(_POSIX_C_SOURCE >= 200112L || _XOPEN_SOURCE >= 600) && ! _GNU_SOURCE
Otherwise, the GNU-specific version is provided.
and further down:
The GNU-specific strerror_r() returns a pointer to a string containing the error message. This may be either a pointer to a string that the function stores in buf, or a pointer to some (immutable) static string (in which case buf is unused). If the function stores a string in buf, then at most buflen bytes are stored (the string may be truncated if buflen is too small and errnum is unknown). The string always includes a terminating null byte.
The program must be using the GNU-specific version and not populating buf. I reproduced the behaviour of the posted program but stored the return value of strerror_r() and it was not the same address as buf.

Resources