I am trying to find what is the allowed limit for the number of characters to be printed by printf() in the C standard. I only found the answer in a discussion forum, which indicates INT_MAX.
For example, I checked the following:
#include <stdio.h>
// INT_MAX 2147483647
int main()
{
int x=3;
int y = printf("%2147483647d \n\n", x); --> Confirms INT_MAX ?
// If I change the above to 2147483648, y in set to -1
printf("y = %d\n\n", y);
return 0;
}
I wanted to ask why is printf() limited by INT_MAX ? Can anyone point out a C standard reasoning or source code reference ?
Edit
The closest answer I found was for fprintf(). At this link, on page 568, its mentioned (under undefined behavior):
The number of characters or wide characters transmitted by a formatted output
function (or written to an array, or that would have been written to an array) is
greater than INT_MAX.
Will the above justify for printf() as well ?
printf is stated to return number of characters printed or -1 in case or an error. Its return type is int. Maximum number you can store is int is INT_MAX.
What happens if you try to print more characters? Then printf cannot fulfill its contract: to return number of characters written. Standard does not says what to do when contract is impossible to fulfill, so the behavior in this case is undefined by not being defined in standard.
Well, if you print with the format specifier %d, which indicates a integer number, of course your maximum printable number would be INT_MAX. But your example is wrong. You are trying to tell it to print INT_MAX digits on a number, but that, of course, far exceeds the actual numerical value INT_MAX.
As to why your example fails, I suppose printf() stores the amount of digits to print in an integer number itself.
"Printf just prints the result".
In other words, the number of characters that printf can print depends on the format specifier specified.
The standard syntax for printf is,
int printf ( const char * format, ... );
here based on "format", the character count limit is set.
from you snippet:
int y = printf("%2147483647d \n\n", x);
because, the value specified is well with the range.
Likewise, when you changed the value to 2147483648 it goes beyond range.
This should have been a comment but due to space restrictions, I had to submit this as an answer.
#include<stdio.h>
#include<limits.h>
#include<malloc.h>
struct ec
{
char *c;
};
int main(void)
{
printf("INTMAX : %d\n",INT_MAX);
struct ec obj;
size_t max=(size_t)INT_MAX+1000;
size_t i;
obj.c=malloc(max*sizeof(char));
if(obj.c==NULL)
{
printf("Can't allocate such big memory chunk\n");
exit(0);
}
for(i=0;i<(max-1);i++)
obj.c[i]='0';
obj.c[i]='\0';
printf(obj.c); // This appear to print fine
/* Not bothered to put a free(obj.c) here*/
return 0;
}
I believe the problem is more with how int return type of the printf function. The return value is the number of characters printed and so it should be incremented per character print. I cannot think of what happens when printf prints (INT_MAX+1)nth character
Note: I neglected the compiler warnings.
Related
I know the size of destination is small so that my code not working correctly but all I want to know when I put 35 in destination character print in infinite loop why it become infinite only when I put 35 in other number it crash or work in bigger number.
I am using Windows 7 Code Block with gcc.
using namespace std;
int main()
{
char dest[35] = "This is an example";//when put another number it work or crash but at this number it print infinite number of character why what is logic
char src[50] = " to show working of strncat() this is not added";
strncat(dest, src, 29);
cout << dest ;
return 0;
}
You have 17 characters plus a null byte in the initialized dest array.
When you call strncat(dest, src, 29), you say "it is safe to add 29 extra characters to dest" — which is nonsense as you can only add 17 characters without overflowing the array.
You invoked undefined behaviour. That means the program can work, or crash, or go into an infinite loop, and all those behaviours are OK because undefined behaviour doesn't have to behave in any specific way.
Note that strncat(dst, sizeof(dst), very_long_string) is a boundary error, even if dst[0] == '\0'. You can use strncat(dst, sizeof(dst)-1, very_long_string) if the destination is empty. (The very long string is any string longer than sizeof(dst) - 1, of course.)
What is proper size of an char array (buffer) when i want to use sprintf function?
I dont know why this part of code is working if buffer can hold only 1 char? I put a lot more chars inside than 1.
/* sprintf example */
#include <stdio.h>
int main ()
{
char buffer[1];
int n, a=5, b=3;
n = sprintf (buffer, "%d plus %d is %d", a, b, a+b);
printf ("[%s] is a string %d chars long\n", buffer, n);
return 0;
}
Results:
[5 plus 3 is 8] is a string 13 chars long
What is proper size of an char array (buffer) when i want to use sprintf function?
There isn't one.
If you can work out an upper bound from the format string and types of input, then you might use that. For example, a 32-bit int won't take up more than 11 characters to represent in decimal with an optional sign, so your particular example won't need more than 44 characters (unless I miscounted).
Otherwise, use something safer: std::stringstream in C++, or snprintf and care in C.
I don't know why this part of code is working if buffer can hold only 1 char?
It isn't. It's writing past the end of the buffer into some other memory.
Maybe that won't cause any visible errors; maybe it will corrupt some other variables; maybe it will cause a protection fault and end the program; maybe it will corrupt the stack frame and cause all kinds of havoc when the function tries to return; or maybe it will cause some other kind of undefined behaviour. But it's certainly not behaving correctly.
In your code a buffer overflow occurred, there were no apparent consequences, but that doesn't mean it worked correctly, try using a memory debugger like valgrind and you will see what I mean.
You can't ensure that sprintf() will not overflow the buffer, that's why there is a snprintf() function to which you pass the size of the buffer.
Sample usage
char buffer[100];
int result;
result = snprintf(buffer, sizeof(buffer), "%d plus %d is %d", a, b, a + b);
if (result >= sizeof(buffer))
{
fprintf(stderr, "The string does not fit `buffer'.\n");
}
Assuming code must use sprintf() and not some other function:
pre-determine the worse case output size and add margin.
Unless there are major memory concerns, suggest a 2x buffer. Various locales can do interesting things like add ',' to integer output as in "123,456,789".
#include <stdio.h>
#include <limits.h>
#define INT_DECIMAL_SIZE(i) (sizeof(i)*CHAR_BIT/3 + 3)
#define format1 "%d plus %d is %d"
char buffer[(sizeof format1 * 3 * INT_DECIMAL_SIZE(int)) * 2];
int n = sprintf(buffer, format1, a, b, a + b);
A challenging example is when code tries sprintf(buf,"%Lf", some_long_double) as the output could be 1000s of characters should x == LDBL_MAX. About 5000 characters with binary128 as long double.
// - 123.............456 . 000000 \0
#define LDBL_DECIMAL_SIZE(i) (1 + 1 + LDBL_MAX_10_EXP + 1 + 6 1)
Is there any function in C or C++ to perform the inverse of an snprintf, such that
char buffer[256]
snprintf( buffer, 256, "Number:%i", 10);
// Buffer now contains "Number:10"
int i;
inverse_snprintf(buffer,"Number:%i", &i);
// i now contains 10
I can write a function that meets this requirement myself, but is there already one within the standard libraries?
Yes, there is sscanf(). It returns the number of tokens successfully matched to the input, so you can check the return value to see how far it made it into the input string.
if (sscanf(buffer, "Number:%i", &i) == 1) {
/* The number was successfully parsed */
}
In addition to sscanf(), if you are only going to scan numbers, you can safely scan numeric values using the strto*() functions: strtol(), strtoll(), strtoul(), strtoull(), strtof(), strtod(), strtold(). You can also use atoi(), atol() and atoll(), but note that these functions return 0 if the string is not an integer that can be converted.
Can anyone spot the reason why nothing gets printed onto console using below C++ code;
string array[] = { "a", "b", "c", "d" };
int length = sizeof(array);
try
{
for (int i = 0; i < length; i++)
{
if (array[i] != "") cout << array[i];
}
}
catch (exception &e)
{
e.what();
}
You use the wrong length:
int length = sizeof(array)/sizeof(array[0])
The actual reason you don't see anything on the console is because the output is buffered, and since you haven't wrote a newline it's not flushed. In the meantime your app crashes.
No end of line character.
Also as mentioned by Dave, sizeof is not the length of the array
This answer assumes that string == std::string.
let T be an arbitrary type, and n be an arbitrary positive integer - then:
sizeof(T[n]) == n * sizeof(T)
That is - sizeof(array) is not the length of the array, but the total amount of memory used by the array (in chars). Your std::string implementation could very well be using more than 1 char's worth of memory to store its structure. This leads to length holding a value much greater than 4.
This causes the program to read from past the end of array; an operation for which C++ imposes no requirements (it is Undefined Behaviour).
In terms of the C++ abstract machine, a program containing Undefined Behaviour can do absolutely anything, even before the point in the execution of the program at which the Undefined Behaviour was encountered. In your particular case your program exhibits this behaviour by not printing anything (even though you had made 4 well defined calls to operator<< before the erroneous array indexing).
You have tagged this eclipse-cdt, so I will assume that you are using GCC to compile your program, and are running it under a modern operating system with memory-protection. In this case the actual reason for the behaviour that you are seeing is probably that std::cout is buffering the first few strings that you stream into it and so not immediately printing them to the console. After that you get to the buffer overrun and your operating system interrupts the process with a EXC_BAD_ACCESS signal or similar. This causes the immediate termination of your program, which does not give std::cout a chance to flush its buffered values. All up, this means that nothing gets printed.
As mentioned in another answer, you should replace the line:
length = sizeof(array);
with:
length = sizeof(array)/sizeof(array[0]);
This will guarantee that length will hold the value 4, rather than the value 4 * sizeof(string), that could be many times the length of the array.
I don't see this an option in things like sprintf().
How would I convert the letter F to 255? Basically the reverse operation of conversion using the %x format in sprintf?
I am assuming this is something simple I'm missing.
char const* data = "F";
int num = int(strtol(data, 0, 16));
Look up strtol and boost::lexical_cast for more details and options.
Use the %x format in sscanf!
The C++ way of doing it, with streams:
#include <iomanip>
#include <iostream>
#include <sstream>
int main() {
std::string hexvalue = "FF";
int value;
// Construct an input stringstream, initialized with hexvalue
std::istringstream iss(hexvalue);
// Set the stream in hex mode, then read the value, with error handling
if (iss >> std::hex >> value) std::cout << value << std::endl;
else std::cout << "Conversion failed" << std::endl;
}
The program prints 255.
You can't get (s)printf to convert 'F' to 255 without some black magic. Printf will convert a character to other representations, but won't change its value. This might show how character conversion works:
printf("Char %c is decimal %i (0x%X)\n", 'F', 'F', 'F');
printf("The high order bits are ignored: %d: %X -> %hhX -> %c\n",
0xFFFFFF46, 0xFFFFFF46, 0xFFFFFF46, 0xFFFFFF46);
produces
Char F is decimal 70 (0x46)
The high order bits are ignored: -186: FFFFFF46 -> 46 -> F
Yeah, I know you asked about sprintf, but that won't show you anything until you do another print.
The idea is that each generic integer parameter to a printf is put on the stack (or in a register) by promotion. That means it is expanded to it's largest generic size: bytes, characters, and shorts are converted to int by sign-extending or zero padding. This keeps the parameter list on the stack in sensible state. It's a nice convention, but it probably had it's origin in the 16-bit word orientation of the stack on the PDP-11 (where it all started).
In the printf library (on the receiving end of the call), the code uses the format specifier to determine what part of the parameter (or all of it) are processed. So if the format is '%c', only 8 bits are used. Note that there may be some variation between systems on how the hex constants are 'promoted'. But if a value greater thann 255 is passed to a character conversion, the high order bits are ignored.